[cig-commits] r21143 - in cs/spatialdata/trunk: libsrc libsrc/geocoords libsrc/spatialdb modulesrc/spatialdb spatialdata spatialdata/spatialdb tests/libtests/spatialdb tests/libtests/spatialdb/data tests/pytests/spatialdb tests/pytests/spatialdb/data

brad at geodynamics.org brad at geodynamics.org
Thu Dec 13 11:10:06 PST 2012


Author: brad
Date: 2012-12-13 11:10:06 -0800 (Thu, 13 Dec 2012)
New Revision: 21143

Added:
   cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.cc
   cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.hh
   cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridAscii.i
   cs/spatialdata/trunk/spatialdata/spatialdb/SimpleGridAscii.py
Modified:
   cs/spatialdata/trunk/libsrc/Makefile.am
   cs/spatialdata/trunk/libsrc/geocoords/CSPicklerAscii.cc
   cs/spatialdata/trunk/libsrc/spatialdb/Makefile.am
   cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.cc
   cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.hh
   cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.icc
   cs/spatialdata/trunk/libsrc/spatialdb/spatialdbfwd.hh
   cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridDB.i
   cs/spatialdata/trunk/modulesrc/spatialdb/spatialdb.i
   cs/spatialdata/trunk/spatialdata/Makefile.am
   cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.cc
   cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.hh
   cs/spatialdata/trunk/tests/libtests/spatialdb/data/Makefile.am
   cs/spatialdata/trunk/tests/pytests/spatialdb/TestSimpleGridDB.py
   cs/spatialdata/trunk/tests/pytests/spatialdb/data/Makefile.am
Log:
Added writer for SimpleGridDB. Small tweaks to improve SimpleGridDB implementation and unit tests.

Modified: cs/spatialdata/trunk/libsrc/Makefile.am
===================================================================
--- cs/spatialdata/trunk/libsrc/Makefile.am	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/Makefile.am	2012-12-13 19:10:06 UTC (rev 21143)
@@ -43,6 +43,7 @@
 	spatialdb/SimpleDBQuery.cc \
 	spatialdb/SimpleIO.cc \
 	spatialdb/SimpleIOAscii.cc \
+	spatialdb/SimpleGridAscii.cc \
 	spatialdb/TimeHistory.cc \
 	spatialdb/TimeHistoryIO.cc \
 	spatialdb/UniformDB.cc \

Modified: cs/spatialdata/trunk/libsrc/geocoords/CSPicklerAscii.cc
===================================================================
--- cs/spatialdata/trunk/libsrc/geocoords/CSPicklerAscii.cc	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/geocoords/CSPicklerAscii.cc	2012-12-13 19:10:06 UTC (rev 21143)
@@ -35,6 +35,8 @@
 spatialdata::geocoords::CSPicklerAscii::pickle(std::ostream& s,
 					       const CoordSys* pCS)
 { // pickle
+  assert(pCS);
+
   pCS->pickle(s);
 } // pickle
 
@@ -44,7 +46,7 @@
 spatialdata::geocoords::CSPicklerAscii::unpickle(std::istream& s,
 						 CoordSys** ppCS)
 { // unpickle
-  assert(0 != ppCS);
+  assert(ppCS);
 
   delete *ppCS; *ppCS = 0;
 

Modified: cs/spatialdata/trunk/libsrc/spatialdb/Makefile.am
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/Makefile.am	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/spatialdb/Makefile.am	2012-12-13 19:10:06 UTC (rev 21143)
@@ -36,6 +36,7 @@
 	SimpleDBData.icc \
 	SimpleGridDB.hh \
 	SimpleGridDB.icc \
+	SimpleGridAscii.hh \
 	GravityField.hh \
 	GravityField.icc \
 	SCECCVMH.hh \

Added: cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.cc
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.cc	                        (rev 0)
+++ cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.cc	2012-12-13 19:10:06 UTC (rev 21143)
@@ -0,0 +1,506 @@
+// -*- C++ -*-
+//
+// ----------------------------------------------------------------------
+//
+// Brad T. Aagaard, U.S. Geological Survey
+//
+// This code was developed as part of the Computational Infrastructure
+// for Geodynamics (http://geodynamics.org).
+//
+// Copyright (c) 2010-2012 University of California, Davis
+//
+// See COPYING for license information.
+//
+// ----------------------------------------------------------------------
+//
+
+#include <portinfo>
+
+#include "SimpleGridAscii.hh" // implementation of class methods
+
+#include "SpatialDB.hh" // USES SimpleDB
+#include "SimpleDB.hh" // USES SimpleDB
+
+#include "SimpleDBData.hh" // USES SimpleDBData
+#include "spatialdata/geocoords/CoordSys.hh" // USES CSCart
+#include "spatialdata/geocoords/CSCart.hh" // USES CSCart
+#include "spatialdata/geocoords/CSPicklerAscii.hh" // USES CSPicklerAscii
+
+#include "spatialdata/utils/LineParser.hh" // USES LineParser
+
+#include <fstream> // USES std::ofstream, std::ifstream
+#include <iomanip> // USES setw(), setiosflags(), resetiosflags()
+#include <cmath> // USES pow()
+#include <algorithm> // USES std::sort()
+#include <vector> // USES std::vector
+
+#include <stdexcept> // USES std::runtime_error
+#include <sstream> // USES std::ostringsgream
+#include <strings.h> // USES strcasecmp()
+#include <string.h> // USES strlen()
+#include <assert.h> // USES assert()
+
+// ----------------------------------------------------------------------
+const char* spatialdata::spatialdb::SimpleGridAscii::FILEHEADER = "#SPATIAL_GRID.ascii";
+
+// ----------------------------------------------------------------------
+// Read ascii database file.
+void
+spatialdata::spatialdb::SimpleGridAscii::read(SimpleGridDB* db)
+{ // read
+  assert(db);
+
+  try {
+    std::ifstream filein(db->_filename.c_str());
+    if (!filein.is_open() || !filein.good()) {
+      std::ostringstream msg;
+      msg << "Could not open spatial database file '" << db->_filename
+	  << "' for reading.\n";
+      throw std::runtime_error(msg.str());
+    } // if
+
+    _readHeader(filein, db);
+    _readData(filein, db);
+    
+    if (!filein.good())
+      throw std::runtime_error("Unknown error while reading.");
+
+    filein.close();
+  } catch (const std::exception& err) {
+    std::ostringstream msg;
+    msg << "Error occurred while reading spatial database file '"
+	<< db->_filename << "'.\n"
+	<< err.what();
+    throw std::runtime_error(msg.str());
+  } catch (...) {
+    std::ostringstream msg;
+    msg << "Unknown error occurred while reading spatial database file '"
+	<< db->_filename << "'.\n";
+    throw std::runtime_error(msg.str());
+  } // try/catch
+} // read
+
+
+// ----------------------------------------------------------------------
+// Write ascii database file.
+void
+spatialdata::spatialdb::SimpleGridAscii::write(const SimpleGridDB& db)
+{ // write
+  try {
+    std::ofstream fileout(db._filename.c_str());
+    if (!fileout.is_open() || !fileout.good()) {
+      std::ostringstream msg;
+      msg << "Could not open spatial database file '" << db._filename
+	  << "' for writing.\n";
+      throw std::runtime_error(msg.str());
+    } // if
+    
+    _writeHeader(fileout, db);
+    _writeData(fileout, db);
+    
+    if (!fileout.good())
+      throw std::runtime_error("Unknown error while writing.");
+
+    fileout.close();
+  } catch (const std::exception& err) {
+    std::ostringstream msg;
+    msg << "Error occurred while writing spatial database file '"
+	<< db._filename << "'.\n"
+	<< err.what();
+    throw std::runtime_error(msg.str());
+  } catch (...) {
+    std::ostringstream msg;
+    msg << "Unknown error occurred while writing spatial database file '"
+	<< db._filename << "'.\n";
+    throw std::runtime_error(msg.str());
+  } // try/catch
+} // write
+
+
+// ----------------------------------------------------------------------
+// Read data file header.
+void
+spatialdata::spatialdb::SimpleGridAscii::_readHeader(std::istream& filein,
+						     SimpleGridDB* const db)
+{ // _readHeader
+  assert(db);
+
+  utils::LineParser parser(filein, "//");
+  parser.eatwhitespace(true);
+
+  std::istringstream buffer;
+
+  buffer.str(parser.next());
+  buffer.clear();
+
+  const int headerLen = strlen(FILEHEADER);
+  std::string hbuffer;
+  hbuffer.resize(headerLen+1);
+  buffer.read((char*) hbuffer.c_str(), sizeof(char)*headerLen);
+  hbuffer[headerLen] = '\0';
+  if (0 != strcasecmp(FILEHEADER, hbuffer.c_str())) {
+    std::ostringstream msg;
+    msg
+      << "Magic header '" << buffer << "' does not match expected header '"
+      << FILEHEADER << "' in spatial database file '" << db->_filename << "'.\n";
+    throw std::runtime_error(msg.str());
+  } // if
+
+  std::string token;
+  const int maxIgnore = 256;
+
+  buffer.str(parser.next());
+  buffer.clear();
+  buffer >> token;
+  if (0 != strcasecmp(token.c_str(), "SimpleGridDB")) {
+    std::ostringstream msg;
+    msg << "Could not parse '" << token << "' into 'SimpleGridDB'.\n";
+    throw std::runtime_error(msg.str());
+  } // else
+
+  db->_numX = 0;
+  db->_numY = 0;
+  db->_numZ = 0;
+  delete[] db->_x; db->_x = 0;
+  delete[] db->_y; db->_y = 0;
+  delete[] db->_z; db->_z = 0;
+  
+  db->_numValues = 0;
+  delete[] db->_names; db->_names = 0;
+  delete[] db->_units; db->_units = 0;
+
+  buffer.str(parser.next());
+  buffer.clear();
+  buffer >> token;
+  while (buffer.good() && token != "}") {
+    if (0 == strcasecmp(token.c_str(), "num-x")) {
+      buffer.ignore(maxIgnore, '=');
+      buffer >> db->_numX;
+    } else if (0 == strcasecmp(token.c_str(), "num-y")) {
+      buffer.ignore(maxIgnore, '=');
+      buffer >> db->_numY;
+    } else if (0 == strcasecmp(token.c_str(), "num-z")) {
+      buffer.ignore(maxIgnore, '=');
+      buffer >> db->_numZ;
+    } else if (0 == strcasecmp(token.c_str(), "space-dim")) {
+      buffer.ignore(maxIgnore, '=');
+      buffer >> db->_spaceDim;
+    } else if (0 == strcasecmp(token.c_str(), "num-values")) {
+      buffer.ignore(maxIgnore, '=');
+      buffer >> db->_numValues;
+    } else if (0 == strcasecmp(token.c_str(), "value-names")) {
+      if (db->_numValues > 0) {
+	db->_names = new std::string[db->_numValues];
+      } else
+	throw std::runtime_error("Number of values must be specified BEFORE "
+				 "names of values in SimpleGridDB file.");
+      buffer.ignore(maxIgnore, '=');
+      for (int iVal=0; iVal < db->_numValues; ++iVal)
+	buffer >> db->_names[iVal];
+    } else if (0 == strcasecmp(token.c_str(), "value-units")) {
+      if (db->_numValues > 0) {
+	db->_units = new std::string[db->_numValues];
+      } else
+	throw std::runtime_error("Number of values must be specified BEFORE "
+				 "units of values in SimpleGridDB file.");
+      buffer.ignore(maxIgnore, '=');
+      for (int iVal=0; iVal < db->_numValues; ++iVal)
+	buffer >> db->_units[iVal];
+    } else if (0 == strcasecmp(token.c_str(), "cs-data")) {
+      buffer.ignore(maxIgnore, '=');
+      std::string rbuffer(buffer.str());
+      filein.putback('\n');
+      filein.clear();
+      int i = rbuffer.length()-1;
+      while (i >= 0) {
+	filein.putback(rbuffer[i]);
+	if ('=' == rbuffer[i--])
+	  break;
+      } // while
+      filein.clear();
+      spatialdata::geocoords::CSPicklerAscii::unpickle(filein, &db->_cs);
+    } else {
+      std::ostringstream msg;
+      msg << "Could not parse '" << token << "' into a SimpleGridDB setting.";
+      throw std::runtime_error(msg.str());
+    } // else
+    
+    buffer.str(parser.next());
+    buffer.clear();
+    buffer >> token;
+  } // while
+  if (token != "}" || !filein.good())
+    throw std::runtime_error("I/O error while parsing SimpleGridDB settings.");
+  
+  bool ok = true;
+  std::ostringstream msg;
+  if (db->_numValues <= 0) {
+    ok = false;
+    msg << "SimpleGridDB settings must include 'num-values'.\n";
+  } // if
+  if (db->_spaceDim <= 0) {
+    ok = false;
+    msg << "SimpleGridDB settings must include positive 'space-dim'.\n";
+  } // if
+
+  if (db->_spaceDim > 0 && db->_numX <= 0) {
+    ok = false;
+    msg << "SimpleGridDB settings must include 'num-x'.\n";
+  } // if
+  if (db->_spaceDim > 1 && db->_numY <= 0) {
+    ok = false;
+    msg << "SimpleGridDB settings must include 'num-y' with 2-D and 3-D data.\n";
+  } // if
+  if (db->_spaceDim > 2 && db->_numZ <= 0) {
+    ok = false;
+    msg << "SimpleGridDB settings must include 'num-z' with 3-D data.\n";
+  } // if
+  if (!db->_names) {
+    ok = false;
+    msg << "SimpleGridDB settings must include 'value-names'.\n";
+  } // if
+  if (!db->_units) {
+    ok = false;
+    msg << "SimpleGridDB settings must include 'value-units'.\n";
+  } // if
+  if (!ok)
+    throw std::runtime_error(msg.str());
+
+  // Set data dimension based on dimensions of data.
+  db->_dataDim = 0;
+  if (db->_numX > 1) {
+    db->_dataDim += 1;
+  } // if
+  if (db->_numY > 1) {
+    db->_dataDim += 1;
+  } // if
+  if (db->_numZ > 1) {
+    db->_dataDim += 1;
+  } // if
+
+  assert(db->_cs);
+  db->_cs->initialize();
+} // _readHeader
+
+// ----------------------------------------------------------------------
+// Read data values.
+void
+spatialdata::spatialdb::SimpleGridAscii::_readData(std::istream& filein,
+						   SimpleGridDB* const db)
+{ // _readData
+  delete[] db->_x; db->_x = 0;
+  delete[] db->_y; db->_y = 0;
+  delete[] db->_z; db->_z = 0;
+  delete[] db->_data; db->_data = 0;
+
+  const int numX = db->_numX;
+  const int numY = db->_numY;
+  const int numZ = db->_numZ;
+  const int numValues = db->_numValues;
+  const int spaceDim = db->_spaceDim;
+
+  utils::LineParser parser(filein, "//");
+  parser.eatwhitespace(true);
+
+  std::istringstream buffer;
+
+  int numLocs = 1;
+  if (numX >= 1) {
+    numLocs *= numX;
+    db->_x = new double[numX];
+    buffer.str(parser.next());
+    buffer.clear();
+    for (int i=0; i < numX; ++i) {
+      buffer >> db->_x[i];
+    } // for
+    std::vector<double> xVec(numX);
+    for (int i=0; i < numX; ++i)
+      xVec[i] = db->_x[i];
+    std::sort(xVec.begin(), xVec.end());
+    for (int i=0; i < numX; ++i)
+      db->_x[i] = xVec[i];
+  } // if
+
+  if (numY >= 1) {
+    numLocs *= numY;
+    db->_y = new double[numY];
+    buffer.str(parser.next());
+    buffer.clear();
+    for (int i=0; i < numY; ++i) {
+      buffer >> db->_y[i];
+    } // for
+    std::vector<double> yVec(numY);
+    for (int i=0; i < numY; ++i)
+      yVec[i] = db->_y[i];
+    std::sort(yVec.begin(), yVec.end());
+    for (int i=0; i < numY; ++i)
+      db->_y[i] = yVec[i];
+  } // if
+
+  if (numZ >= 1) {
+    numLocs *= numZ;
+    db->_z = new double[numZ];
+    buffer.str(parser.next());
+    buffer.clear();
+    for (int i=0; i < numZ; ++i) {
+      buffer >> db->_z[i];
+    } // for
+    std::vector<double> zVec(numZ);
+    for (int i=0; i < numZ; ++i)
+      zVec[i] = db->_z[i];
+    std::sort(zVec.begin(), zVec.end());
+    for (int i=0; i < numZ; ++i)
+      db->_z[i] = zVec[i];
+  } // if
+
+  assert(numLocs > 0);
+  assert(numValues > 0);
+  db->_data = new double[numLocs*db->_numValues];
+  assert(spaceDim > 0);
+  double* coords = new double[spaceDim];
+  for (int iLoc=0; iLoc < numLocs; ++iLoc) {
+    buffer.str(parser.next());
+    buffer.clear();
+    for (int iDim=0; iDim < spaceDim; ++iDim) {
+      buffer >> coords[iDim];
+    } // for
+    
+    int indexX = 0;
+    int indexY = 0;
+    int indexZ = 0;
+    if (spaceDim > 2) {
+      indexX = int(std::floor(db->_search(coords[0], db->_x, numX)+0.5));
+      indexY = int(std::floor(db->_search(coords[1], db->_y, numY)+0.5));
+      indexZ = int(std::floor(db->_search(coords[2], db->_z, numZ)+0.5));
+    } else if (spaceDim > 1) {
+      indexX = int(std::floor(db->_search(coords[0], db->_x, numX)+0.5));
+      indexY = int(std::floor(db->_search(coords[1], db->_y, numY)+0.5));
+    } else {
+      assert(1 == spaceDim);
+      indexX = int(std::floor(db->_search(coords[0], db->_x, numX)+0.5));
+    } // if
+    
+    const int indexData = db->_dataIndex(indexX, indexY, indexZ);
+    for (int iVal=0; iVal < db->_numValues; ++iVal) {
+      buffer >> db->_data[indexData+iVal];
+    } // for
+    if (buffer.bad()) {
+      throw std::runtime_error("Error reading points.");
+    } // if
+  } // for
+  delete[] coords; coords = 0;
+  if (!filein.good())
+    throw std::runtime_error("I/O error while reading SimpleGridDB data.");
+
+  // Set dimensions without any data to 1.
+  if (0 == db->_numX) {
+    db->_numX = 1;
+  } // if
+  if (0 == db->_numY) {
+    db->_numY = 1;
+  } // if
+  if (0 == db->_numZ) {
+    db->_numZ = 1;
+  } // if
+
+  // Check compatibility of dimension of data, spatial dimension and
+  // number of points
+  db->_checkCompatibility();
+
+  // Convert to SI units
+  SpatialDB::_convertToSI(db->_data, db->_units, numLocs, db->_numValues);  
+} // _readData
+
+// ----------------------------------------------------------------------
+// Write the data file header.
+void
+spatialdata::spatialdb::SimpleGridAscii::_writeHeader(std::ostream& fileout,
+						      const SimpleGridDB& db)
+{ // _writeHeader
+  const int version = 1;
+  const int numValues = db._numValues;
+  const int spaceDim = db._spaceDim;
+    
+  fileout
+    << FILEHEADER << " " << version << "\n"
+    << "SimpleGridDB {\n"
+    << "  num-x = " << db._numX << "\n"
+    << "  num-y = " << db._numY << "\n"
+    << "  num-z = " << db._numZ << "\n"
+    << "  space-dim = " << spaceDim << "\n"
+    << "  num-values = " << numValues << "\n"
+    << "  value-names =";
+
+  assert(db._names);
+  for (int iVal=0; iVal < numValues; ++iVal)
+    fileout << "  " << db._names[iVal];
+  fileout << "\n";
+
+  assert(db._units);
+  fileout << "  value-units =";
+  for (int iVal=0; iVal < numValues; ++iVal)
+    fileout << "  " << db._units[iVal];
+  fileout << "\n";
+  fileout << "  cs-data = ";
+  spatialdata::geocoords::CSPicklerAscii::pickle(fileout, db._cs);
+  fileout << "}\n";
+
+  if (!fileout.good())
+    throw std::runtime_error("I/O error while writing SimpleGridDB settings.");
+} // _writeHeader
+  
+
+// ----------------------------------------------------------------------
+// Write data values.
+void
+spatialdata::spatialdb::SimpleGridAscii::_writeData(std::ostream& fileout,
+						    const SimpleGridDB& db)
+{ // _writeData
+  fileout
+    << std::resetiosflags(std::ios::fixed)
+    << std::setiosflags(std::ios::scientific)
+    << std::setprecision(6);
+
+  const int numX = db._numX;
+  const int numY = db._numY;
+  const int numZ = db._numZ;
+  const int numValues = db._numValues;
+
+  fileout << "// x-coordinates\n";
+  for (int i=0; i < numX; ++i) {
+    fileout << std::setw(14) << db._x[i];
+  } // for
+  fileout << "\n";
+  
+  fileout << "// y-coordinates\n";
+  for (int i=0; i < numY; ++i) {
+    fileout << std::setw(14) << db._y[i];
+  } // for
+  fileout << "\n";
+  
+  fileout << "// z-coordinates\n";
+  for (int i=0; i < numZ; ++i) {
+    fileout << std::setw(14) << db._z[i];
+  } // for
+  fileout << "\n";
+
+  fileout << "// data\n";
+  for (int iZ=0; iZ < numZ; ++iZ) {
+    for (int iY=0; iY < numY; ++iY) {
+      for (int iX=0; iX < numX; ++iX) {
+	const int iD = db._dataIndex(iX, iY, iZ);
+	fileout 
+	  << std::setw(14) << db._x[iX]
+	  << std::setw(14) << db._y[iY]
+	  << std::setw(14) << db._z[iZ];
+	for (int iV=0; iV < numValues; ++iV) {
+	  fileout << std::setw(14) << db._data[iD+iV];
+	} // for
+	fileout << "\n";
+      } // for
+    } // for
+  } // for
+} // _writeData
+
+
+// End of file 

Added: cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.hh
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.hh	                        (rev 0)
+++ cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridAscii.hh	2012-12-13 19:10:06 UTC (rev 21143)
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//
+// ----------------------------------------------------------------------
+//
+// Brad T. Aagaard, U.S. Geological Survey
+//
+// This code was developed as part of the Computational Infrastructure
+// for Geodynamics (http://geodynamics.org).
+//
+// Copyright (c) 2010-2012 University of California, Davis
+//
+// See COPYING for license information.
+//
+// ----------------------------------------------------------------------
+//
+
+/** @file libsrc/spatialdb/SimpleGridAscii.hh
+ *
+ * @brief C++ object for reading/writing SimpleGridDB info as ASCII
+ * files.
+ */
+
+#if !defined(spatialdata_spatialdb_simplegridascii_hh)
+#define spatialdata_spatialdb_simplegridascii_hh
+
+#include "SimpleGridDB.hh" // ISA SimpleGridDB
+
+#include <iosfwd> // USES std::istream
+
+// ----------------------------------------------------------------------
+class spatialdata::spatialdb::SimpleGridAscii
+{ // SimpleGridAscii
+
+public :
+  // PUBLIC METHODS /////////////////////////////////////////////////////
+
+  // Using default constructor.
+  
+  // Using default destructor.
+
+  // Using default copy constructor
+  
+  /** Read the database.
+   *
+   * @param db Spatial database.
+   */
+  static
+  void read(SimpleGridDB* db);
+
+  /** Write the database.
+   *
+   * @param db Spatial database.
+   */
+  static
+  void write(const SimpleGridDB& db);
+
+private :
+  // PRIVATE METHODS ////////////////////////////////////////////////////
+
+  /** Read data file header.
+   *
+   * @param filein Input stream.
+   * @param db Spatial database.
+   */
+  static
+  void _readHeader(std::istream& filein,
+		   SimpleGridDB* const db);
+  
+  /** Read data values.
+   *
+   * @param filein Input stream.
+   * @param db Spatial database.
+   */
+  static
+  void _readData(std::istream& filein,
+		 SimpleGridDB* const db);
+
+  /** Write the data file header.
+   *
+   * @param fileout Output stream.
+   * @param db Spatial database.
+   */
+  static
+  void _writeHeader(std::ostream& fileout,
+		    const SimpleGridDB& db);
+  
+  /** Write data values.
+   *
+   * @param fileout Output stream.
+   * @param db Spatial database.
+   */
+  static
+  void _writeData(std::ostream& fileout,
+		  const SimpleGridDB& db);
+
+ private :
+  // PRIVATE MEMBERS ////////////////////////////////////////////////////
+
+  /** Magic header in ascii files */
+  static const char* FILEHEADER;
+
+}; // class SimpleGridAscii
+
+#endif // spatialdata_spatialdb_SimpleGridAscii_hh
+
+
+// End of file 

Modified: cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.cc
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.cc	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.cc	2012-12-13 19:10:06 UTC (rev 21143)
@@ -18,15 +18,15 @@
 
 #include "SimpleGridDB.hh" // Implementation of class methods
 
+#include "SimpleGridAscii.hh" // USES SimpleGridAscii
+
 #include "spatialdata/geocoords/CSGeoProj.hh" // USES CSGeoProj
 #include "spatialdata/geocoords/Projector.hh" // USES Projector
 #include "spatialdata/geocoords/Converter.hh" // USES Converter
 #include "spatialdata/geocoords/CSPicklerAscii.hh" // USES CSPicklerAscii
 #include "spatialdata/utils/LineParser.hh" // USES LineParser
 
-#include <math.h> // USES pow()
-#include <algorithm> // USES std::sort()
-#include <vector> // USES std::vector
+#include <cmath> // USES std::floor()
 
 #include <fstream> // USES std::ifstream
 #include <sstream> // USES std::ostringstream
@@ -36,9 +36,6 @@
 #include <assert.h> // USES assert()
 
 // ----------------------------------------------------------------------
-const char* spatialdata::spatialdb::SimpleGridDB::FILEHEADER = "#SPATIAL_GRID.ascii";
-
-// ----------------------------------------------------------------------
 // Constructor
 spatialdata::spatialdb::SimpleGridDB::SimpleGridDB(void) :
   _data(0),
@@ -56,7 +53,7 @@
   _names(0),
   _units(0),
   _filename(""),
-  _cs(new geocoords::CSGeoProj),
+  _cs(0),
   _queryType(NEAREST)
 { // constructor
 } // constructor
@@ -77,6 +74,7 @@
   delete[] _units; _units = 0;
   delete[] _queryVals; _queryVals = 0;
   _querySize = 0;
+
   delete _cs; _cs = 0;
 } // destructor
 
@@ -93,32 +91,7 @@
 void
 spatialdata::spatialdb::SimpleGridDB::open(void)
 { // open
-  try {
-    std::ifstream filein(_filename.c_str());
-    if (!filein.is_open() || !filein.good()) {
-      std::ostringstream msg;
-      msg << "Could not open spatial database file '" << _filename
-	  << "' for reading.\n";
-      throw std::runtime_error(msg.str());
-    } // if
-
-    _readHeader(filein);
-    _readData(filein);
-    
-    if (!filein.good())
-      throw std::runtime_error("Unknown error while reading.");
-  } catch (const std::exception& err) {
-    std::ostringstream msg;
-    msg << "Error occurred while reading spatial database file '"
-	<< _filename << "'.\n"
-	<< err.what();
-    throw std::runtime_error(msg.str());
-  } catch (...) {
-    std::ostringstream msg;
-    msg << "Unknown error occurred while reading spatial database file '"
-	<< _filename << "'.\n";
-    throw std::runtime_error(msg.str());
-  } // try/catch
+  SimpleGridAscii::read(this);
 } // open
 
 // ----------------------------------------------------------------------
@@ -280,13 +253,16 @@
     indexX = _search(_xyz[0], _x, _numX);
     numX = _numX;
   } // if/else
-  if (-1.0 == indexX || -1.0 == indexY || -1.0 == indexZ) {
-    queryFlag = 1;
-    return queryFlag;
-  } // if
   
   switch (_queryType) {
   case LINEAR : 
+    if (indexX < 0.0 || (indexX > 0 && indexX > numX-1.0) ||
+	indexY < 0.0 || (indexY > 0 && indexY > numY-1.0) ||
+        indexZ < 0.0 || (indexZ > 0 && indexZ > numZ-1.0)) {
+  queryFlag = 1;
+  return queryFlag;
+    } // if
+
     switch (_dataDim) {
     case 1: {
       _interpolate1D(vals, numVals, indexX, numX);
@@ -306,9 +282,15 @@
     } // switch
     break;
   case NEAREST : {
-    const int indexNearestX = int(floor(indexX+0.5));
-    const int indexNearestY = int(floor(indexY+0.5));
-    const int indexNearestZ = int(floor(indexZ+0.5));
+    indexX = std::min(indexX, numX-1.0);
+    indexX = std::max(indexX, 0.0);
+    indexY = std::min(indexY, numY-1.0);
+    indexY = std::max(indexY, 0.0);
+    indexZ = std::min(indexZ, numZ-1.0);
+    indexZ = std::max(indexZ, 0.0);
+    const int indexNearestX = int(std::floor(indexX+0.5));
+    const int indexNearestY = int(std::floor(indexY+0.5));
+    const int indexNearestZ = int(std::floor(indexZ+0.5));
     const int indexData = _dataIndex(indexNearestX, indexNearestY, indexNearestZ);
     for (int iVal=0; iVal < querySize; ++iVal) {
       vals[iVal] = _data[indexData+_queryVals[iVal]];
@@ -331,299 +313,217 @@
   return queryFlag;
 } // query
 
+
 // ----------------------------------------------------------------------
-// Read data file header.
+// Allocate data.
 void
-spatialdata::spatialdb::SimpleGridDB::_readHeader(std::istream& filein)
-{ // _readHeader
-  utils::LineParser parser(filein, "//");
-  parser.eatwhitespace(true);
+spatialdata::spatialdb::SimpleGridDB::allocate(const int numX,
+					       const int numY,
+					       const int numZ,
+					       const int numValues,
+					       const int spaceDim,
+					       const int dataDim)
+{ // allocate
+  _numX = numX;
+  _numY = numY;
+  _numZ = numZ;
+  _numValues = numValues;
+  _spaceDim = spaceDim;
+  _dataDim = dataDim;
+  
+  _checkCompatibility();
 
-  std::istringstream buffer;
+  const int numLocs = _numX * _numY * _numZ;
+  delete[] _data; _data = (numLocs*numValues > 0) ? new double[numLocs*numValues] : 0;
 
-  buffer.str(parser.next());
-  buffer.clear();
+  delete[] _x; _x = (numX > 0) ? new double[numX] : 0;
+  delete[] _y; _y = (numY > 0) ? new double[numY] : 0;
+  delete[] _z; _z = (numZ > 0) ? new double[numZ] : 0;
+} // allocate
 
-  const int headerLen = strlen(FILEHEADER);
-  std::string hbuffer;
-  hbuffer.resize(headerLen+1);
-  buffer.read((char*) hbuffer.c_str(), sizeof(char)*headerLen);
-  hbuffer[headerLen] = '\0';
-  if (0 != strcasecmp(FILEHEADER, hbuffer.c_str())) {
+
+// ----------------------------------------------------------------------
+// Set coordinates along x-axis;
+void
+spatialdata::spatialdb::SimpleGridDB::x(const double* values,
+					const int size)
+{ // x
+  if (size != _numX) {
     std::ostringstream msg;
-    msg
-      << "Magic header '" << buffer << "' does not match expected header '"
-      << FILEHEADER << "' in spatial database file '" << _filename << "'.\n";
+    msg << "Mismatch in size (" << _numX << " != " << size
+	<< ") for number of values along x-axis in simple grid spatial database.";
     throw std::runtime_error(msg.str());
   } // if
+  if (!_x) {
+    _x = (size > 0) ? new double[size] : 0;
+  } // if
 
-  std::string token;
-  const int maxIgnore = 256;
+  assert(_x);
+  for (int i=0; i < size; ++i) {
+    _x[i] = values[i];
+  } // for
+} // x
+ 
 
-  buffer.str(parser.next());
-  buffer.clear();
-  buffer >> token;
-  if (0 != strcasecmp(token.c_str(), "SimpleGridDB")) {
+// ----------------------------------------------------------------------
+// Set coordinates along y-axis;
+void
+spatialdata::spatialdb::SimpleGridDB::y(const double* values,
+					const int size)
+{ // y
+  if (size != _numY) {
     std::ostringstream msg;
-    msg << "Could not parse '" << token << "' into 'SimpleGridDB'.\n";
+    msg << "Mismatch in size (" << _numY << " != " << size
+	<< ") for number of values along y-axis in simple grid spatial database.";
     throw std::runtime_error(msg.str());
-  } // else
-
-  _numX = 0;
-  _numY = 0;
-  _numZ = 0;
-  delete[] _x; _x = 0;
-  delete[] _y; _y = 0;
-  delete[] _z; _z = 0;
-  
-  _numValues = 0;
-  delete[] _names; _names = 0;
-  delete[] _units; _units = 0;
-
-  buffer.str(parser.next());
-  buffer.clear();
-  buffer >> token;
-  while (buffer.good() && token != "}") {
-    if (0 == strcasecmp(token.c_str(), "num-x")) {
-      buffer.ignore(maxIgnore, '=');
-      buffer >> _numX;
-    } else if (0 == strcasecmp(token.c_str(), "num-y")) {
-      buffer.ignore(maxIgnore, '=');
-      buffer >> _numY;
-    } else if (0 == strcasecmp(token.c_str(), "num-z")) {
-      buffer.ignore(maxIgnore, '=');
-      buffer >> _numZ;
-    } else if (0 == strcasecmp(token.c_str(), "space-dim")) {
-      buffer.ignore(maxIgnore, '=');
-      buffer >> _spaceDim;
-    } else if (0 == strcasecmp(token.c_str(), "num-values")) {
-      buffer.ignore(maxIgnore, '=');
-      buffer >> _numValues;
-    } else if (0 == strcasecmp(token.c_str(), "value-names")) {
-      if (_numValues > 0) {
-	_names = new std::string[_numValues];
-      } else
-	throw std::runtime_error("Number of values must be specified BEFORE "
-				 "names of values in SimpleGridDB file.");
-      buffer.ignore(maxIgnore, '=');
-      for (int iVal=0; iVal < _numValues; ++iVal)
-	buffer >> _names[iVal];
-    } else if (0 == strcasecmp(token.c_str(), "value-units")) {
-      if (_numValues > 0) {
-	_units = new std::string[_numValues];
-      } else
-	throw std::runtime_error("Number of values must be specified BEFORE "
-				 "units of values in SimpleGridDB file.");
-      buffer.ignore(maxIgnore, '=');
-      for (int iVal=0; iVal < _numValues; ++iVal)
-	buffer >> _units[iVal];
-    } else if (0 == strcasecmp(token.c_str(), "cs-data")) {
-      buffer.ignore(maxIgnore, '=');
-      std::string rbuffer(buffer.str());
-      filein.putback('\n');
-      filein.clear();
-      int i = rbuffer.length()-1;
-      while (i >= 0) {
-	filein.putback(rbuffer[i]);
-	if ('=' == rbuffer[i--])
-	  break;
-      } // while
-      filein.clear();
-      spatialdata::geocoords::CSPicklerAscii::unpickle(filein, &_cs);
-    } else {
-      std::ostringstream msg;
-      msg << "Could not parse '" << token << "' into a SimpleGridDB setting.";
-      throw std::runtime_error(msg.str());
-    } // else
-    
-    buffer.str(parser.next());
-    buffer.clear();
-    buffer >> token;
-  } // while
-  if (token != "}" || !filein.good())
-    throw std::runtime_error("I/O error while parsing SimpleGridDB settings.");
-  
-  bool ok = true;
-  std::ostringstream msg;
-  if (_numValues <= 0) {
-    ok = false;
-    msg << "SimpleGridDB settings must include 'num-values'.\n";
   } // if
-  if (_spaceDim <= 0) {
-    ok = false;
-    msg << "SimpleGridDB settings must include positive 'space-dim'.\n";
+  if (!_y) {
+    _y = (size > 0) ? new double[size] : 0;
   } // if
 
-  if (_spaceDim > 0 && _numX <= 0) {
-    ok = false;
-    msg << "SimpleGridDB settings must include 'num-x'.\n";
-  } // if
-  if (_spaceDim > 1 && _numY <= 0) {
-    ok = false;
-    msg << "SimpleGridDB settings must include 'num-y' with 2-D and 3-D data.\n";
-  } // if
-  if (_spaceDim > 2 && _numZ <= 0) {
-    ok = false;
-    msg << "SimpleGridDB settings must include 'num-z' with 3-D data.\n";
-  } // if
-  if (!_names) {
-    ok = false;
-    msg << "SimpleGridDB settings must include 'value-names'.\n";
-  } // if
-  if (!_units) {
-    ok = false;
-    msg << "SimpleGridDB settings must include 'value-units'.\n";
-  } // if
-  if (!ok)
-    throw std::runtime_error(msg.str());
+  assert(_y);
+  for (int i=0; i < size; ++i) {
+    _y[i] = values[i];
+  } // for
+} // y
+ 
 
-  // Set data dimension based on dimensions of data.
-  _dataDim = 0;
-  if (_numX > 1) {
-    _dataDim += 1;
+// ----------------------------------------------------------------------
+// Set coordinates along z-axis;
+void
+spatialdata::spatialdb::SimpleGridDB::z(const double* values,
+					const int size)
+{ // z
+  if (size != _numZ) {
+    std::ostringstream msg;
+    msg << "Mismatch in size (" << _numZ << " != " << size
+	<< ") for number of values along z-axis in simple grid spatial database.";
+    throw std::runtime_error(msg.str());
   } // if
-  if (_numY > 1) {
-    _dataDim += 1;
+  if (!_z) {
+    _z = (size > 0) ? new double[size] : 0;
   } // if
-  if (_numZ > 1) {
-    _dataDim += 1;
-  } // if
 
-  assert(_cs);
-  _cs->initialize();
-} // _readHeader
+  assert(_z);
+  for (int i=0; i < size; ++i) {
+    _z[i] = values[i];
+  } // for
+} // z
+ 
 
 // ----------------------------------------------------------------------
-// Read data values.
+// Set data values.
 void
-spatialdata::spatialdb::SimpleGridDB::_readData(std::istream& filein)
-{ // _readData
-  delete[] _x; _x = 0;
-  delete[] _y; _y = 0;
-  delete[] _z; _z = 0;
-  delete[] _data; _data = 0;
-
-  const int numX = _numX;
-  const int numY = _numY;
-  const int numZ = _numZ;
-  const int numValues = _numValues;
-  const int spaceDim = _spaceDim;
-
-  utils::LineParser parser(filein, "//");
-  parser.eatwhitespace(true);
-
-  std::istringstream buffer;
-
-  int numLocs = 1;
-  if (numX >= 1) {
-    numLocs *= numX;
-    _x = new double[numX];
-    buffer.str(parser.next());
-    buffer.clear();
-    for (int i=0; i < numX; ++i) {
-      buffer >> _x[i];
-    } // for
-    std::vector<double> xVec(numX);
-    for (int i=0; i < numX; ++i)
-      xVec[i] = _x[i];
-    std::sort(xVec.begin(), xVec.end());
-    for (int i=0; i < numX; ++i)
-      _x[i] = xVec[i];
+spatialdata::spatialdb::SimpleGridDB::data(const double* coords,
+					   const int numLocs,
+					   const int spaceDim,
+					   const double* values,
+					   const int numLocs2,
+					   const int numValues)
+{ // data
+  if (numLocs != numLocs2) {
+    std::ostringstream msg;
+    msg << "Mismatch in number of locations (" << numLocs << " != " << numLocs2
+	<< ") for number of locations in simple grid spatial database.";
+    throw std::runtime_error(msg.str());
   } // if
-
-  if (numY >= 1) {
-    numLocs *= numY;
-    _y = new double[numY];
-    buffer.str(parser.next());
-    buffer.clear();
-    for (int i=0; i < numY; ++i) {
-      buffer >> _y[i];
-    } // for
-    std::vector<double> yVec(numY);
-    for (int i=0; i < numY; ++i)
-      yVec[i] = _y[i];
-    std::sort(yVec.begin(), yVec.end());
-    for (int i=0; i < numY; ++i)
-      _y[i] = yVec[i];
+  if (spaceDim != _spaceDim) {
+    std::ostringstream msg;
+    msg << "Mismatch in coordinate dimension (" << _spaceDim << " != " << spaceDim
+	<< ") for locations in simple grid spatial database.";
+    throw std::runtime_error(msg.str());
   } // if
-
-  if (numZ >= 1) {
-    numLocs *= numZ;
-    _z = new double[numZ];
-    buffer.str(parser.next());
-    buffer.clear();
-    for (int i=0; i < numZ; ++i) {
-      buffer >> _z[i];
-    } // for
-    std::vector<double> zVec(numZ);
-    for (int i=0; i < numZ; ++i)
-      zVec[i] = _z[i];
-    std::sort(zVec.begin(), zVec.end());
-    for (int i=0; i < numZ; ++i)
-      _z[i] = zVec[i];
+  if (numValues != _numValues) {
+    std::ostringstream msg;
+    msg << "Mismatch in number of values (" << _numValues << " != " << numValues
+	<< ") for simple grid spatial database.";
+    throw std::runtime_error(msg.str());
   } // if
+    
+  if (!_data) {
+    const int size = numLocs*numValues;
+    _data = (size > 0) ? new double[size] : 0;
+  } // if
 
-  assert(numLocs > 0);
-  assert(numValues > 0);
-  _data = new double[numLocs*_numValues];
-  assert(spaceDim > 0);
-  double* coords = new double[spaceDim];
+  assert(_data);
   for (int iLoc=0; iLoc < numLocs; ++iLoc) {
-    buffer.str(parser.next());
-    buffer.clear();
-    for (int iDim=0; iDim < spaceDim; ++iDim) {
-      buffer >> coords[iDim];
-    } // for
-    
     int indexX = 0;
     int indexY = 0;
     int indexZ = 0;
+    const int ii = iLoc*spaceDim;
     if (spaceDim > 2) {
-      indexX = int(floor(_search(coords[0], _x, numX)+0.5));
-      indexY = int(floor(_search(coords[1], _y, numY)+0.5));
-      indexZ = int(floor(_search(coords[2], _z, numZ)+0.5));
+      indexX = int(std::floor(_search(coords[ii+0], _x, _numX)+0.5));
+      indexY = int(std::floor(_search(coords[ii+1], _y, _numY)+0.5));
+      indexZ = int(std::floor(_search(coords[ii+2], _z, _numZ)+0.5));
     } else if (spaceDim > 1) {
-      indexX = int(floor(_search(coords[0], _x, numX)+0.5));
-      indexY = int(floor(_search(coords[1], _y, numY)+0.5));
+      indexX = int(std::floor(_search(coords[ii+0], _x, _numX)+0.5));
+      indexY = int(std::floor(_search(coords[ii+1], _y, _numY)+0.5));
     } else {
       assert(1 == spaceDim);
-      indexX = int(floor(_search(coords[0], _x, numX)+0.5));
+      indexX = int(std::floor(_search(coords[ii+0], _x, _numX)+0.5));
     } // if
-    
-    const int indexData = _dataIndex(indexX, indexY, indexZ);
-    for (int iVal=0; iVal < _numValues; ++iVal) {
-      buffer >> _data[indexData+iVal];
+
+    const int iD = _dataIndex(indexX, indexY, indexZ);
+    const int jj = iLoc*numValues;
+    for (int iV=0; iV < numValues; ++iV) {
+      _data[iD+iV] = values[jj+iV];
     } // for
-    if (buffer.bad()) {
-      throw std::runtime_error("Error reading points.");
-    } // if
   } // for
-  delete[] coords; coords = 0;
-  if (!filein.good())
-    throw std::runtime_error("I/O error while reading SimpleGridDB data.");
+} // data
 
-  // Set dimensions without any data to 1.
-  if (0 == _numX) {
-    _numX = 1;
+
+// ----------------------------------------------------------------------
+// Set names of data values.
+void
+spatialdata::spatialdb::SimpleGridDB::names(const char* const* values,
+					    const int numValues)
+{ // names
+  assert(values);
+  if (numValues != _numValues) {
+    std::ostringstream msg;
+    msg << "Mismatch in number of values (" << _numValues << " != " << numValues
+	<< ") for names of values in simple grid spatial database.";
+    throw std::runtime_error(msg.str());
   } // if
-  if (0 == _numY) {
-    _numY = 1;
+  delete[] _names; _names = (numValues > 0) ? new std::string[numValues] : 0;
+  for (int i=0; i < numValues; ++i) {
+    _names[i] = values[i];
+  } // for
+} // names
+ 
+
+// ----------------------------------------------------------------------
+// Set units of data values.
+void 
+spatialdata::spatialdb::SimpleGridDB::units(const char* const* values,
+					    const int numValues)
+{ // units
+  assert(values);
+  if (numValues != _numValues) {
+    std::ostringstream msg;
+    msg << "Mismatch in number of values (" << _numValues << " != " << numValues
+	<< ") for units of values in simple grid spatial database.";
+    throw std::runtime_error(msg.str());
   } // if
-  if (0 == _numZ) {
-    _numZ = 1;
-  } // if
+  delete[] _units; _units = (numValues > 0) ? new std::string[numValues] : 0;
+  for (int i=0; i < numValues; ++i) {
+    _units[i] = values[i];
+  } // for
+} // units
+ 
 
-  // Check compatibility of dimension of data, spatial dimension and
-  // number of points
-  _checkCompatibility();
-
-  // Convert to SI units
-  SpatialDB::_convertToSI(_data, _units, numLocs, _numValues);  
-} // _readData
-
 // ----------------------------------------------------------------------
-/// Check compatibility of spatial database parameters.
+// Set filename containing data.
 void
+spatialdata::spatialdb::SimpleGridDB::coordsys(const geocoords::CoordSys& cs)
+{ // coordsys
+  delete _cs; _cs = cs.clone();
+  _cs->initialize();
+} // coordsys
+ 
+// ----------------------------------------------------------------------
+// Check compatibility of spatial database parameters.
+void
 spatialdata::spatialdb::SimpleGridDB::_checkCompatibility(void) const
 { // _checkCompatibility
   const int spaceDim = _spaceDim;
@@ -677,6 +577,7 @@
     throw std::runtime_error(msg.str());
   } // if
 
+  assert(_cs);
   if (spaceDim != _cs->spaceDim()) {
     msg << "Number of dimensions in coordinates of spatial distribution ("
 	<< spaceDim << ") does not match number of dimensions in coordinate "
@@ -735,7 +636,7 @@
 						     const int numX) const
 { // _interpolate1D
   assert(numX >= 2);
-  const int indexX0 = std::min(numX-2, int(floor(indexX)));
+  const int indexX0 = std::min(numX-2, int(std::floor(indexX)));
   const double wtX0 = 1.0 - (indexX - indexX0);
   const int indexX1 = indexX0 + 1;
   const double wtX1 = 1.0 - wtX0;
@@ -776,7 +677,7 @@
 						     const int numY) const
 { // _interpolate2D
   assert(numX >= 2);
-  const int indexX0 = std::min(numX-2, int(floor(indexX)));
+  const int indexX0 = std::min(numX-2, int(std::floor(indexX)));
   const double wtX0 = 1.0 - (indexX - indexX0);
   const int indexX1 = indexX0 + 1;
   const double wtX1 = 1.0 - wtX0;
@@ -784,7 +685,7 @@
   assert(0 <= indexX1 && indexX1 < numX);
 
   assert(numY >= 2);
-  const int indexY0 = std::min(numY-2, int(floor(indexY)));
+  const int indexY0 = std::min(numY-2, int(std::floor(indexY)));
   const double wtY0 = 1.0 - (indexY - indexY0);
   const int indexY1 = indexY0 + 1;
   const double wtY1 = 1.0 - wtY0;
@@ -836,7 +737,7 @@
   const int numZ = _numZ;
 
   assert(numX >= 2);
-  const int indexX0 = std::min(numX-2, int(floor(indexX)));
+  const int indexX0 = std::min(numX-2, int(std::floor(indexX)));
   const double wtX0 = 1.0 - (indexX - indexX0);
   const int indexX1 = indexX0 + 1;
   const double wtX1 = 1.0 - wtX0;
@@ -844,7 +745,7 @@
   assert(0 <= indexX1 && indexX1 < numX);
 
   assert(numY >= 2);
-  const int indexY0 = std::min(numY-2, int(floor(indexY)));
+  const int indexY0 = std::min(numY-2, int(std::floor(indexY)));
   const double wtY0 = 1.0 - (indexY - indexY0);
   const int indexY1 = indexY0 + 1;
   const double wtY1 = 1.0 - wtY0;
@@ -852,7 +753,7 @@
   assert(0 <= indexY1 && indexY1 < numY);
   
   assert(numZ >= 2);
-  const int indexZ0 = std::min(numZ-2, int(floor(indexZ)));
+  const int indexZ0 = std::min(numZ-2, int(std::floor(indexZ)));
   const double wtZ0 = 1.0 - (indexZ - indexZ0);
   const int indexZ1 = indexZ0 + 1;
   const double wtZ1 = 1.0 - wtZ0;

Modified: cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.hh
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.hh	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.hh	2012-12-13 19:10:06 UTC (rev 21143)
@@ -26,11 +26,11 @@
 #include "SpatialDB.hh" // ISA SpatialDB
 
 #include <string> // HASA std::string
-#include <iosfwd> // USES std::istream
 
 class spatialdata::spatialdb::SimpleGridDB : SpatialDB
 { // SimpleGridDB
   friend class TestSimpleGridDB; // unit testing
+  friend class SimpleGridAscii; // reader
  
  public :
   // PUBLIC ENUM ////////////////////////////////////////////////////////
@@ -52,7 +52,7 @@
  
   /** Set filename containing data.
    *
-   * @param dir Directory containing data files.
+   * @param value Name of data file.
    */
   void filename(const char* value);
  
@@ -101,22 +101,88 @@
 	    const int numDims,
 	    const spatialdata::geocoords::CoordSys* pCSQuery);
  
- 
-// PRIVATE METHODS //////////////////////////////////////////////////////
-private :
 
-  /** Read data file header.
+  /** Allocate room for data.
    *
-   * @param filein Input stream.
+   * @param numX Number of locations along x-axis.
+   * @param numY Number of locations along y-axis.
+   * @param numZ Number of locations along z-axis.
+   * @param numValues Number of values at each location.
+   * @param spaceDim Spatial dimension.
+   * @param dataDim Spatial dimension of topology.
    */
-  void _readHeader(std::istream& filein);
+  void allocate(const int numX,
+		const int numY,
+		const int numZ,
+		const int numValues,
+		const int spaceDim,
+		const int dataDim);
 
-  /** Read data values.
+  /** Set coordinates along x-axis;
    *
-   * @param filein Input stream.
+   * @param values Values along x-axis.
+   * @param size Number of values along x-axis.
    */
-  void _readData(std::istream& filein);
+  void x(const double* values,
+	 const int size);
+ 
+  /** Set coordinates along y-axis;
+   *
+   * @param values Values along y-axis.
+   * @param size Number of values along y-axis.
+   */
+  void y(const double* values,
+	 const int size);
+ 
+  /** Set coordinates along z-axis;
+   *
+   * @param values Values along z-axis.
+   * @param size Number of values along z-axis.
+   */
+  void z(const double* values,
+	 const int size);
+ 
+  /** Set data values.
+   *
+   * @param coords Coordinates of locations.
+   * @param numLocs Number of locations.
+   * @param spaceDim Coordinate dimension.
+   * @param values Data values.
+   * @param numLocs2 Number of locations.
+   * @param numValues Number of values per location.
+   */
+  void data(const double* coords,
+	    const int numLocs,
+	    const int spaceDim,
+	    const double* values,
+	    const int numLocs2,
+	    const int numValues);
 
+  /** Set names of data values.
+   *
+   * @param values Names of values.
+   * @param numValues Number of values.
+   */
+  void names(const char* const* values,
+	     const int numValues);
+ 
+  /** Set units of data values.
+   *
+   * @param values Units of values.
+   * @param numValues Number of values.
+   */
+  void units(const char* const* values,
+	     const int numValues);
+ 
+  /** Set filename containing data.
+   *
+   * @param dir Directory containing data files.
+   */
+  void coordsys(const geocoords::CoordSys& cs);
+ 
+// PRIVATE METHODS //////////////////////////////////////////////////////
+private :
+
   /// Check compatibility of spatial database parameters.
   void _checkCompatibility(void) const;
 

Modified: cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.icc
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.icc	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/spatialdb/SimpleGridDB.icc	2012-12-13 19:10:06 UTC (rev 21143)
@@ -18,6 +18,8 @@
 #error "SimpleGridDB.icc must only be included from SimpleGridDB.hh"
 #endif
 
+#include <cassert> // USES assert()
+
 // ----------------------------------------------------------------------
 // Get index into data array.
 inline

Modified: cs/spatialdata/trunk/libsrc/spatialdb/spatialdbfwd.hh
===================================================================
--- cs/spatialdata/trunk/libsrc/spatialdb/spatialdbfwd.hh	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/libsrc/spatialdb/spatialdbfwd.hh	2012-12-13 19:10:06 UTC (rev 21143)
@@ -37,6 +37,7 @@
     class SimpleIOAscii;
     class UniformDB;
     class SimpleGridDB;
+    class SimpleGridAscii;
     class CompositeDB;
     class SCECCVMH;
     class GocadVoxet;

Added: cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridAscii.i
===================================================================
--- cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridAscii.i	                        (rev 0)
+++ cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridAscii.i	2012-12-13 19:10:06 UTC (rev 21143)
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+//
+// ----------------------------------------------------------------------
+//
+// Brad T. Aagaard, U.S. Geological Survey
+//
+// This code was developed as part of the Computational Infrastructure
+// for Geodynamics (http://geodynamics.org).
+//
+// Copyright (c) 2010-2012 University of California, Davis
+//
+// See COPYING for license information.
+//
+// ----------------------------------------------------------------------
+//
+
+/** @file modulesrc/spatialdb/SimpleGridAscii.i
+ *
+ * @brief SWIG interface to C++ SimpleGridAscii object.
+ */
+
+namespace spatialdata {
+  namespace spatialdb {
+
+    class spatialdata::spatialdb::SimpleGridAscii
+    { // SimpleGridAscii
+      
+    public :
+      // PUBLIC METHODS /////////////////////////////////////////////////
+
+      // Using default constructor.
+      
+      // Using default destructor.
+      
+      // Using default copy constructor
+      
+      /** Read the database.
+       *
+       * @param db Spatial database.
+       */
+      static
+      void read(SimpleGridDB* db);
+      
+      /** Write the database.
+       *
+       * @param db Spatial database.
+       */
+      static
+      void write(const SimpleGridDB& db);
+
+    }; // class SimpleGridAscii
+
+  } // spatialdb
+} // spatialdata
+  
+
+// End of file 

Modified: cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridDB.i
===================================================================
--- cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridDB.i	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/modulesrc/spatialdb/SimpleGridDB.i	2012-12-13 19:10:06 UTC (rev 21143)
@@ -109,6 +109,121 @@
       %clear(double* vals, const int numVals);
       %clear(const double* coords, const int numDims);
       
+      /** Allocate room for data.
+       *
+       * @param numX Number of locations along x-axis.
+       * @param numY Number of locations along y-axis.
+       * @param numZ Number of locations along z-axis.
+       * @param numValues Number of values at each location.
+       * @param spaceDim Spatial dimension.
+       * @param dataDim Spatial dimension of topology.
+       */
+      void allocate(const int numX,
+		    const int numY,
+		    const int numZ,
+		    const int numValues,
+		    const int spaceDim,
+		    const int dataDim);
+      
+      /** Set coordinates along x-axis;
+       *
+       * @param values Values along x-axis.
+       * @param size Number of values along x-axis.
+       */
+      %apply(double* IN_ARRAY1, int DIM1) {
+	(const double* values,
+	 const int size)
+	  };
+      void x(const double* values,
+	     const int size);
+      %clear(double* values, const int size);
+      
+      /** Set coordinates along y-axis;
+       *
+       * @param values Values along y-axis.
+       * @param size Number of values along y-axis.
+       */
+      %apply(double* IN_ARRAY1, int DIM1) {
+	(const double* values,
+	 const int size)
+	  };
+      void y(const double* values,
+	     const int size);
+      %clear(double* values, const int size);
+      
+      /** Set coordinates along z-axis;
+       *
+       * @param values Values along z-axis.
+       * @param size Number of values along z-axis.
+       */
+      %apply(double* IN_ARRAY1, int DIM1) {
+	(const double* values,
+	 const int size)
+	  };
+      void z(const double* values,
+	     const int size);
+      %clear(double* values, const int size);
+      
+      /** Set data values.
+       *
+       * @param coords Coordinates of locations.
+       * @param numLocs Number of locations.
+       * @param spaceDim Coordinate dimension.
+       * @param values Data values.
+       * @param numLocs2 Number of locations.
+       * @param numValues Number of values per location.
+       */
+      %apply(double* IN_ARRAY2, int DIM1, int DIM2) {
+	(const double* coords,
+	 const int numLocs,
+	 const int spaceDim)
+	  };
+      %apply(double* IN_ARRAY2, int DIM1, int DIM2) {
+	(const double* values,
+	 const int numLocs2,
+	 const int numValues)
+	  };
+      void data(const double* coords,
+		const int numLocs,
+		const int spaceDim,
+		const double* values,
+		const int numLocs2,
+		const int numValues);
+      %clear(double* coords, const int size, const int spaceDim);
+      %clear(double* values, const int numLocs2, const int numValues);
+      
+      /** Set names of data values.
+       *
+       * @param values Names of values.
+       * @param numValues Number of values.
+       */
+      %apply(const char* const* string_list, const int list_len){
+	(const char* const* values,
+	 const int numValues)
+	  };
+      void names(const char* const* values,
+		 const int numValues);
+      %clear(const char* const* values, const int numValues);
+      
+      /** Set units of data values.
+       *
+       * @param values Units of values.
+       * @param numValues Number of values.
+       */
+      %apply(const char* const* string_list, const int list_len){
+	(const char* const* values,
+	 const int numValues)
+	  };
+      void units(const char* const* values,
+		 const int numValues);
+      %clear(const char* const* values, const int numValues);
+      
+      /** Set filename containing data.
+       *
+       * @param dir Directory containing data files.
+       */
+      void coordsys(const spatialdata::geocoords::CoordSys& cs);
+ 
     }; // class SimpleGridDB
     
   } // spatialdb

Modified: cs/spatialdata/trunk/modulesrc/spatialdb/spatialdb.i
===================================================================
--- cs/spatialdata/trunk/modulesrc/spatialdb/spatialdb.i	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/modulesrc/spatialdb/spatialdb.i	2012-12-13 19:10:06 UTC (rev 21143)
@@ -31,6 +31,7 @@
 #include "spatialdata/spatialdb/SimpleIOAscii.hh"
 #include "spatialdata/spatialdb/UniformDB.hh"
 #include "spatialdata/spatialdb/SimpleGridDB.hh"
+#include "spatialdata/spatialdb/SimpleGridAscii.hh"
 #include "spatialdata/spatialdb/CompositeDB.hh"
 #include "spatialdata/spatialdb/SCECCVMH.hh"
 #include "spatialdata/spatialdb/GravityField.hh"
@@ -69,6 +70,7 @@
 %include "SimpleIOAscii.i"
 %include "UniformDB.i"
 %include "SimpleGridDB.i"
+%include "SimpleGridAscii.i"
 %include "CompositeDB.i"
 %include "SCECCVMH.i"
 %include "GravityField.i"

Modified: cs/spatialdata/trunk/spatialdata/Makefile.am
===================================================================
--- cs/spatialdata/trunk/spatialdata/Makefile.am	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/spatialdata/Makefile.am	2012-12-13 19:10:06 UTC (rev 21143)
@@ -35,6 +35,7 @@
 	spatialdb/TimeHistoryIO.py \
 	spatialdb/UniformDB.py \
 	spatialdb/SimpleGridDB.py \
+	spatialdb/SimpleGridAscii.py \
 	spatialdb/__init__.py \
 	spatialdb/generator/Shaper.py \
 	spatialdb/generator/Shapers.py \

Added: cs/spatialdata/trunk/spatialdata/spatialdb/SimpleGridAscii.py
===================================================================
--- cs/spatialdata/trunk/spatialdata/spatialdb/SimpleGridAscii.py	                        (rev 0)
+++ cs/spatialdata/trunk/spatialdata/spatialdb/SimpleGridAscii.py	2012-12-13 19:10:06 UTC (rev 21143)
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+#
+# ----------------------------------------------------------------------
+#
+# Brad T. Aagaard, U.S. Geological Survey
+#
+# This code was developed as part of the Computational Infrastructure
+# for Geodynamics (http://geodynamics.org).
+#
+# Copyright (c) 2010-2012 University of California, Davis
+#
+# See COPYING for license information.
+#
+# ----------------------------------------------------------------------
+#
+
+## @file spatialdata/spatialdb/SimpleGridAscii.py
+##
+## @brief Python ascii I/O manager for simple gridd spatial database
+## (SimpleGridDB).
+##
+## Factory: simplegrid_io
+
+from pyre.components.Component import Component
+from spatialdb import SimpleGridAscii as ModuleSimpleGridAscii
+
+# Validator for filename
+def validateFilename(value):
+  """
+  Validate filename.
+  """
+  if 0 == len(value):
+    raise ValueError("Filename for spatial database not specified.")
+  return value
+
+
+# SimpleGridAscii class
+class SimpleGridAscii(Component, ModuleSimpleGridAscii):
+  """
+  Python ascii I/O manager for simple grid spatial database
+  (SimpleGridDB).
+
+  Factory: simplegrid_io
+  """
+
+  # INVENTORY //////////////////////////////////////////////////////////
+
+  class Inventory(Component.Inventory):
+    """
+    Python object for managing SimpleIO facilities and properties.
+    """
+
+    ## @class Inventory
+    ## Python object for managing SimpleIO facilities and properties.
+    ##
+    ## \b Properties
+    ## @li \b filename Name of database file
+    ##
+    ## \b Facilities
+    ## @li None
+
+    import pyre.inventory
+
+    filename = pyre.inventory.str("filename", default="", validator=validateFilename)
+    filename.meta['tip'] = "Name of database file."
+
+
+  # PUBLIC METHODS /////////////////////////////////////////////////////
+
+  def __init__(self, name="simpleioascii"):
+    """
+    Constructor.
+    """
+    Component.__init__(self, name, facility="simplegrid_io")
+    return
+
+
+  def write(self, data):
+    """
+    Write database to file.
+
+    @param data Dictionary of the following form:
+      data = {'points': 2-D array (numLocs, spaceDim),
+              'x': Array of x coordinates,
+              'y': Array of y coordinates,
+              'z': Array of z coordinates,
+              'coordsys': Coordinate system associated with locations,
+              'data_dim': Dimension of spatial distribution,
+              'values': [{'name': Name of value,
+                          'units': Units of value,
+                          'data': Data for value (numLocs)}]}
+    """
+    import numpy
+
+    (numLocs, spaceDim) = data['points'].shape
+    numValues = len(data['values'])    
+    names = []
+    units = []
+    values = numpy.zeros( (numLocs, numValues), dtype=numpy.float64)
+    i = 0
+    for value in data['values']:
+      names.append(value['name'])
+      units.append(value['units'])
+      values[:,i] = value['data'][:]
+      i += 1
+
+    numX = data['x'].shape[0]
+    numY = data['y'].shape[0]
+    numZ = data['z'].shape[0]
+    if (numLocs != numX*numY*numZ):
+      raise ValueError("Number of locations (%d) does not match coordinate dimensions (%d, %d, %d)." % (numLocs, numX, numY, numZ))
+
+    from SimpleGridDB import SimpleGridDB
+    db = SimpleGridDB()
+    db.inventory.label = "Temporary database for I/O"
+    db.inventory.filename = self.filename
+    db._configure()
+    db.coordsys(data['coordsys'])
+    db.allocate(numX, numY, numZ, numValues, spaceDim, data['data_dim'])
+    db.x(data['x'])
+    db.y(data['y'])
+    db.z(data['z'])
+    db.data(data['points'], values)
+    db.names(names)
+    db.units(units)
+
+    ModuleSimpleGridAscii.write(db)
+    return
+
+
+  # PRIVATE METHODS ////////////////////////////////////////////////////
+
+  def _configure(self):
+    """
+    Set members using inventory.
+    """
+    try:
+      Component._configure(self)
+      self.filename = self.inventory.filename
+    except ValueError, err:
+      aliases = ", ".join(self.aliases)
+      raise ValueError("Error while configuring spatial database reader "
+                       "(%s):\n%s" % (aliases, err.message))
+    return
+
+
+  def _createModuleObj(self):
+    """
+    Create Python module object.
+    """
+    ModuleSimpleGridAscii.__init__(self)
+    return
+
+
+# FACTORIES ////////////////////////////////////////////////////////////
+
+def simplegrid_io():
+  """
+  Factory associated with SimpleGridAscii.
+  """
+  return SimpleGridAscii()
+
+
+# End of file 

Modified: cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.cc
===================================================================
--- cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.cc	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.cc	2012-12-13 19:10:06 UTC (rev 21143)
@@ -19,6 +19,7 @@
 #include "TestSimpleGridDB.hh" // Implementation of class methods
 
 #include "spatialdata/spatialdb/SimpleGridDB.hh" // USES SimpleGridDB
+#include "spatialdata/spatialdb/SimpleGridAscii.hh" // USES SimpleGridAscii
 
 #include "data/SimpleGridDBTestData.hh" // USES SimpleGridDBTestData
 
@@ -214,7 +215,7 @@
 // Test read().
 void
 spatialdata::spatialdb::TestSimpleGridDB::testRead(void)
-{ // _testRead
+{ // testRead
   CPPUNIT_ASSERT(_data);
 
   SimpleGridDB db;
@@ -273,9 +274,120 @@
   for (int i=0; i < totalSize; ++i) {
     CPPUNIT_ASSERT_DOUBLES_EQUAL(_data->dbData[i], db._data[i], tolerance);
   } // for
-} // _testRead
+} // testRead
 
+
 // ----------------------------------------------------------------------
+// Test filename(), write(), read().
+void
+spatialdata::spatialdb::TestSimpleGridDB::testIO(void)
+{ // testIO
+  const int numX = 3;
+  const int numY = 2;
+  const int numZ = 3;
+  const int spaceDim = 3;
+  const int numVals = 2;
+  const int dataDim = 3;
+
+  const double x[numX] = { -2.0, 0.0, 3.0 };
+  const double y[numY] = { 0.0, 1.0 };
+  const double z[numZ] = { -2.0, -1.0, 2.0 };
+  
+  const double coords[numX*numY*numZ*spaceDim] = {
+    -2.0,  0.0, -2.0,
+    -2.0,  1.0, -2.0,
+    -2.0,  0.0, -1.0,
+    -2.0,  1.0, -1.0,
+    -2.0,  0.0,  2.0,
+    -2.0,  1.0,  2.0,
+     0.0,  0.0, -2.0,
+     0.0,  1.0, -2.0,
+     0.0,  0.0, -1.0,
+     0.0,  1.0, -1.0,
+     0.0,  0.0,  2.0,
+     0.0,  1.0,  2.0,
+     3.0,  0.0, -2.0,
+     3.0,  1.0, -2.0,
+     3.0,  0.0, -1.0,
+     3.0,  1.0, -1.0,
+     3.0,  0.0,  2.0,
+     3.0,  1.0,  2.0,
+  };
+  const double data[numX*numY*numZ*numVals] = {
+    6.6,  3.4,
+    5.5,  6.7,
+    2.3,  4.1,
+    5.7,  2.0,
+    6.3,  6.7,
+    3.4,  6.4,
+    7.2,  6.8,
+    5.7,  8.2,
+    3.4,  9.8,
+    5.7,  2.3,
+    9.4,  8.5,
+    7.2,  9.3,
+    4.8,  7.5,
+    9.2,  8.3,
+    5.8,  8.5,
+    4.7,  8.9,
+    7.8,  6.2,
+    2.9,  8.3,
+  };
+  const char* names[] = { "One", "Two" };
+  const char* units[] = { "m", "m" };
+
+  geocoords::CSCart csOut;
+  csOut.initialize();
+
+  SimpleGridDB dbOut;
+  dbOut.coordsys(csOut);
+  dbOut.allocate(numX, numY, numZ, numVals, spaceDim, dataDim);
+  dbOut.x(x, numX);
+  dbOut.y(y, numY);
+  dbOut.z(z, numZ);
+  dbOut.data(coords, numX*numY*numZ, spaceDim, data, numX*numY*numZ, numVals);
+  dbOut.names(names, numVals);
+  dbOut.units(units, numVals);
+
+  const char* filename = "data/grid.spatialdb";
+  dbOut.filename(filename);
+  SimpleGridAscii::write(dbOut);
+
+  SimpleGridDB dbIn;
+  dbIn.filename(filename);
+  dbIn.open();
+
+  CPPUNIT_ASSERT_EQUAL(numX, dbIn._numX);
+  CPPUNIT_ASSERT_EQUAL(numY, dbIn._numY);
+  CPPUNIT_ASSERT_EQUAL(numZ, dbIn._numZ);
+  CPPUNIT_ASSERT_EQUAL(numVals, dbIn._numValues);
+  CPPUNIT_ASSERT_EQUAL(dataDim, dbIn._dataDim);
+  CPPUNIT_ASSERT_EQUAL(spaceDim, dbIn._spaceDim);
+
+  CPPUNIT_ASSERT(dbIn._names);
+  CPPUNIT_ASSERT(dbIn._units);
+  for (int iVal=0; iVal < numVals; ++iVal) {
+    CPPUNIT_ASSERT_EQUAL(std::string(names[iVal]), dbIn._names[iVal]);
+    CPPUNIT_ASSERT_EQUAL(std::string(units[iVal]), dbIn._units[iVal]);
+  } // for
+
+  CPPUNIT_ASSERT(dbIn._data);
+  const double tolerance = 1.0e-06;
+  for (int iX=0, i=0; iX < numX; ++iX) {
+    for (int iZ=0; iZ < numZ; ++iZ) {
+      for (int iY=0; iY < numY; ++iY) {
+	const int iD = dbIn._dataIndex(iX, iY, iZ);
+	for (int iVal=0; iVal < numVals; ++iVal, ++i) {
+	  CPPUNIT_ASSERT_DOUBLES_EQUAL(dbIn._data[iD+iVal]/data[i], 1.0, tolerance);
+	} // for
+      } // for
+    } // for
+  } // for
+} // testIO
+
+
+
+// ----------------------------------------------------------------------
 // Populate database with data.
 void
 spatialdata::spatialdb::TestSimpleGridDB::_setupDB(SimpleGridDB* const db)

Modified: cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.hh
===================================================================
--- cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.hh	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/tests/libtests/spatialdb/TestSimpleGridDB.hh	2012-12-13 19:10:06 UTC (rev 21143)
@@ -50,6 +50,7 @@
   CPPUNIT_TEST( testQueryType );
   CPPUNIT_TEST( testSearch );
   CPPUNIT_TEST( testDataIndex );
+  CPPUNIT_TEST( testIO );
 
   CPPUNIT_TEST_SUITE_END();
 
@@ -80,6 +81,9 @@
   /// Test _dataIndex()
   void testDataIndex(void);
 
+  /// Test read(), write().
+  void testIO(void);
+
   // PUBLIC METHODS /////////////////////////////////////////////////////
 public :
 

Modified: cs/spatialdata/trunk/tests/libtests/spatialdb/data/Makefile.am
===================================================================
--- cs/spatialdata/trunk/tests/libtests/spatialdb/data/Makefile.am	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/tests/libtests/spatialdb/data/Makefile.am	2012-12-13 19:10:06 UTC (rev 21143)
@@ -28,7 +28,8 @@
 
 noinst_TMP = \
 	spatial.dat \
-	timehistory.dat
+	grid.spatialdb \
+	timehistory.data
 
 noinst_HEADERS = \
 	header.hh

Modified: cs/spatialdata/trunk/tests/pytests/spatialdb/TestSimpleGridDB.py
===================================================================
--- cs/spatialdata/trunk/tests/pytests/spatialdb/TestSimpleGridDB.py	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/tests/pytests/spatialdb/TestSimpleGridDB.py	2012-12-13 19:10:06 UTC (rev 21143)
@@ -18,11 +18,12 @@
 
 import numpy
 from spatialdata.geocoords.CSCart import CSCart
+from spatialdata.spatialdb.SimpleGridAscii import SimpleGridAscii
+from spatialdata.spatialdb.SimpleGridDB import SimpleGridDB
 
 class TestSimpleGridDB(unittest.TestCase):
 
   def setUp(self):
-    from spatialdata.spatialdb.SimpleGridDB import SimpleGridDB
     db = SimpleGridDB()
     db.inventory.label = "test"
     db.inventory.queryType = "nearest"
@@ -99,4 +100,92 @@
     return
 
 
+  def test_io(self):
+    from spatialdata.spatialdb.SimpleGridAscii import SimpleGridAscii
+
+    filename = "data/gridio.spatialdb"
+    x = numpy.array([-2.0, 0.0, 3.0], dtype=numpy.float64)
+    y = numpy.array([0.0, 1.0], dtype=numpy.float64)
+    z = numpy.array([-2.0, -1.0, 2.0], dtype=numpy.float64)
+
+    points = numpy.array([
+        [-2.0,  0.0, -2.0],
+        [-2.0,  1.0, -2.0],
+        [-2.0,  0.0, -1.0],
+        [-2.0,  1.0, -1.0],
+        [-2.0,  0.0,  2.0],
+        [-2.0,  1.0,  2.0],
+        [ 0.0,  0.0, -2.0],
+        [ 0.0,  1.0, -2.0], # query (5.7, 8.2)
+        [ 0.0,  0.0, -1.0],
+        [ 0.0,  1.0, -1.0],
+        [ 0.0,  0.0,  2.0],
+        [ 0.0,  1.0,  2.0],
+        [ 3.0,  0.0, -2.0],
+        [ 3.0,  1.0, -2.0],
+        [ 3.0,  0.0, -1.0],
+        [ 3.0,  1.0, -1.0],
+        [ 3.0,  0.0,  2.0],
+        [ 3.0,  1.0,  2.0],
+        ], dtype=numpy.float64)
+    one = numpy.array([6.6, 5.5, 2.3, 5.7, 6.3, 3.4, 7.2, 5.7, 3.4, 5.7, 9.4, 7.2, 4.8, 9.2, 5.8, 4.7, 7.8, 2.9], dtype=numpy.float64)
+    two = numpy.array([3.4, 6.7, 4.1, 2.0, 6.7, 6.4, 6.8, 8.2, 9.8, 2.3, 8.5, 9.3, 7.5, 8.3, 8.5, 8.9, 6.2, 8.3], dtype=numpy.float64)
+
+    cs = CSCart()
+    cs.initialize()
+
+    writer = SimpleGridAscii()
+    writer.inventory.filename = filename
+    writer._configure()
+    writer.write({'points': points,
+                  'x': x,
+                  'y': y,
+                  'z': z,
+                  'coordsys': cs,
+                  'data_dim': 3,
+                  'values': [{'name': "one",
+                              'units': "m",
+                              'data': one},
+                             {'name': "two",
+                              'units': "m",
+                              'data': two},
+                             ]})
+
+    db = SimpleGridDB()
+    db.inventory.label = "test"
+    db.inventory.queryType = "nearest"
+    db.inventory.filename = filename
+    db._configure()
+    self._db = db
+
+    locs = numpy.array( [[0.1, 0.95, -1.8]], numpy.float64)
+    cs = CSCart()
+    cs._configure()
+    queryVals = ["two", "one"]
+    dataE = numpy.array( [[8.2, 5.7]], numpy.float64)
+    errE = [0]
+
+    db = self._db
+    db.open()
+    db.queryVals(queryVals)
+    data = numpy.zeros(dataE.shape, dtype=numpy.float64)
+    err = []
+    nlocs = locs.shape[0]
+    for i in xrange(nlocs):
+      e = db.query(data[i,:], locs[i,:], cs)
+      err.append(e)
+    db.close()    
+
+    self.assertEqual(len(errE), len(err))
+    for vE, v in zip(errE, err):
+      self.assertEqual(vE, v)
+
+    self.assertEqual(len(dataE.shape), len(data.shape))
+    for dE, d in zip(dataE.shape, data.shape):
+      self.assertEqual(dE, d)
+    for vE, v in zip(numpy.reshape(dataE, -1), numpy.reshape(data, -1)):
+      self.assertAlmostEqual(vE, v, 6)
+
+    return
+
 # End of file 

Modified: cs/spatialdata/trunk/tests/pytests/spatialdb/data/Makefile.am
===================================================================
--- cs/spatialdata/trunk/tests/pytests/spatialdb/data/Makefile.am	2012-12-13 16:13:02 UTC (rev 21142)
+++ cs/spatialdata/trunk/tests/pytests/spatialdb/data/Makefile.am	2012-12-13 19:10:06 UTC (rev 21143)
@@ -29,7 +29,8 @@
 data_CLEAN = \
 	test.spatialdb \
 	test.timedb \
-	gen1Din2D.spatialdb
+	gen1Din2D.spatialdb \
+	gridio.spatialdb
 
 noinst_HEADERS = \
 	$(data_DATA)



More information about the CIG-COMMITS mailing list