Example #1
0
bool NetcdfSource::initFile() {
  _ncfile = new NcFile(_filename.toUtf8().data(), NcFile::ReadOnly);
  if (!_ncfile->is_valid()) {
      qDebug() << _filename << ": failed to open in initFile()" << endl;
      return false;
    }

  KST_DBG qDebug() << _filename << ": building field list" << endl;
  _fieldList.clear();
  _fieldList += "INDEX";

  int nb_vars = _ncfile->num_vars();
  KST_DBG qDebug() << nb_vars << " vars found in total" << endl;

  _maxFrameCount = 0;

  for (int i = 0; i < nb_vars; i++) {
    NcVar *var = _ncfile->get_var(i);
    if (var->num_dims() == 0) {
      _scalarList += var->name();
    } else if (var->num_dims() == 1) {
      _fieldList += var->name();
      int fc = var->num_vals() / var->rec_size();
      _maxFrameCount = qMax(_maxFrameCount, fc);
      _frameCounts[var->name()] = fc;
    } else if (var->num_dims() == 2) {
      _matrixList += var->name();
    }
  }

  // Get strings
  int globalAttributesNb = _ncfile->num_atts();
  for (int i = 0; i < globalAttributesNb; ++i) {
    // Get only first value, should be enough for a start especially as strings are complete
    NcAtt *att = _ncfile->get_att(i);
    if (att) {
      QString attrName = QString(att->name());
      char *attString = att->as_string(0);
      QString attrValue = QString(att->as_string(0));
      delete[] attString;
      //TODO port
      //KstString *ms = new KstString(KstObjectTag(attrName, tag()), this, attrValue);
      _stringList += attrName;
    }
    delete att;
  }

  // TODO update(); // necessary?  slows down initial loading
  return true;
}
Example #2
0
int NetcdfSource::readString(QString *stringValue, const QString& stringName)
{
  // TODO more error handling?
  NcAtt *att = _ncfile->get_att((NcToken) stringName.toLatin1().data());
  if (att) {
    *stringValue = QString(att->as_string(0));
    return 1;
  }
  delete att;
  return 0;
}
string GrabAttribute(const NcVar* dataVar, const int attIndex)
{
    if (NULL == dataVar)
    {
        cerr << "ERROR: Invalid NcVar!\n";
        return("");
    }

    NcAtt* dataAttrib = dataVar->get_att(attIndex);

    if (NULL == dataAttrib)
    {
        cerr << "ERROR: Could not obtain data attribute: index #" << attIndex << endl;
        return("");
    }

    const string returnVal = dataAttrib->as_string(0);

    delete dataAttrib;

    return(returnVal);
}
RadarData_t ReadRadarFile(const string &filename,
                          const float latmin, const float latmax,
                          const float lonmin, const float lonmax)
{
    RadarData_t inputData;

    // Sets the internal netcdf error handling to nonfatal for this scope
    NcError error_handler(NcError::verbose_nonfatal);

    NcFile radarFile(filename.c_str());

    if (!radarFile.is_valid())
    {
        cerr << "ERROR: Could not open radar file: " << filename << " for reading.\n";

        // Error is indicated by the lack of initialization of
        // the filename member of the struct.
        return(inputData);
    }

    NcVar* latVar = radarFile.get_var("lat");

    if (NULL == latVar)
    {
        cerr << "ERROR: invalid data file.  No variable called 'lat'!\n";
        radarFile.close();
        return(inputData);
    }

    long latCnt = latVar->num_vals();
    double* latVals = new double[latCnt];
    latVar->get(latVals, latCnt);
    inputData.latUnits = GrabAttribute(latVar, 0);
    inputData.latSpacing = strtod(GrabAttribute(latVar, 1).c_str(), NULL);

    const long minLatIndex = lower_bound(latVals, latmin, latCnt);
    const long maxLatIndex = upper_bound(latVals, latmax, latCnt);

    delete latVals;
    latCnt = (maxLatIndex - minLatIndex) + 1;
    latVar->set_cur(minLatIndex);
    inputData.latVals = new double[latCnt];
    latVar->get(inputData.latVals, latCnt);


    NcVar* lonVar = radarFile.get_var("lon");

    if (NULL == lonVar)
    {
        cerr << "ERROR: invalid data file.  No variable called 'lon'!\n";
        radarFile.close();
        return(inputData);
    }

    long lonCnt = lonVar->num_vals();
    double* lonVals = new double[lonCnt];
    lonVar->get(lonVals, lonCnt);
    inputData.lonUnits = GrabAttribute(lonVar, 0);
    inputData.lonSpacing = strtod(GrabAttribute(lonVar, 1).c_str(), NULL);

    const long minLonIndex = lower_bound(lonVals, lonmin, lonCnt);
    const long maxLonIndex = upper_bound(lonVals, lonmax, lonCnt);

    delete lonVals;
    lonCnt = (maxLonIndex - minLonIndex) + 1;
    lonVar->set_cur(minLonIndex);
    inputData.lonVals = new double[lonCnt];
    lonVar->get(inputData.lonVals, lonCnt);

    NcVar* reflectVar = NULL;
    reflectVar = radarFile.get_var("value");

    if ( reflectVar == NULL )
    {
        // Try this variable name
        reflectVar = radarFile.get_var("Reflectivity");
    }

    if (reflectVar == NULL)
    {
        cerr << "ERROR: invalid data file.  No variable called 'value'!\n";
        radarFile.close();
        return(inputData);
    }


    inputData.dataEdges = reflectVar->edges();	// [0] - time, [1] - lat, [2] - lon
    inputData.dataEdges[1] = latCnt;
    inputData.dataEdges[2] = lonCnt;
    inputData.dataVals = new double[inputData.dataEdges[0] * inputData.dataEdges[1] * inputData.dataEdges[2]];
    reflectVar->set_cur(0, minLatIndex, minLonIndex);
    reflectVar->get(inputData.dataVals, inputData.dataEdges);

    inputData.var_LongName = GrabAttribute(reflectVar, 0);
    inputData.var_Units = "dBZ";//GrabAttribute(reflectVar, 1);


    NcVar* timeVar = radarFile.get_var("time");

    if (NULL == timeVar)
    {
        cerr << "ERROR: invalid data file.  No variable called 'time'!\n";
        radarFile.close();
        return(inputData);
    }

    inputData.scanTime = timeVar->as_long(0);
    inputData.timeUnits = GrabAttribute(timeVar, 0);

    NcAtt* titleAttrib = radarFile.get_att("title");

    inputData.fileTitle = (NULL == titleAttrib ? "" : titleAttrib->as_string(0));

    delete titleAttrib;

    radarFile.close();

    // Success!
    inputData.inputFilename = filename;


    return(inputData);
}
void ReadCFTimeDataFromNcFile(
	NcFile * ncfile,
	const std::string & strFilename,
	std::vector<Time> & vecTimes,
	bool fWarnOnMissingCalendar
) {
	// Empty existing Time vector
	vecTimes.clear();

	// Get time dimension
	NcDim * dimTime = ncfile->get_dim("time");
	if (dimTime == NULL) {
		_EXCEPTION1("Dimension \"time\" not found in file \"%s\"",
			strFilename.c_str());
	}

	// Get time variable
	NcVar * varTime = ncfile->get_var("time");
	if (varTime == NULL) {
		_EXCEPTION1("Variable \"time\" not found in file \"%s\"",
			strFilename.c_str());
	}
	if (varTime->num_dims() != 1) {
		_EXCEPTION1("Variable \"time\" has more than one dimension in file \"%s\"",
			strFilename.c_str());
	}
	if (strcmp(varTime->get_dim(0)->name(), "time") != 0) {
		_EXCEPTION1("Variable \"time\" does not have dimension \"time\" in file \"%s\"",
			strFilename.c_str());
	}

	// Calendar attribute
	NcAtt * attTimeCal = varTime->get_att("calendar");
	std::string strCalendar;
	if (attTimeCal == NULL) {
		if (fWarnOnMissingCalendar) {
			Announce("WARNING: Variable \"time\" is missing \"calendar\" attribute; assuming \"standard\"");
		}
		strCalendar = "standard";
	} else {
		strCalendar = attTimeCal->as_string(0);
	}
	Time::CalendarType eCalendarType =
		Time::CalendarTypeFromString(strCalendar);

	// Units attribute
	NcAtt * attTimeUnits = varTime->get_att("units");
	if (attTimeUnits == NULL) {
		_EXCEPTION1("Variable \"time\" is missing \"units\" attribute in file \"%s\"",
			strFilename.c_str());
	}
	std::string strTimeUnits = attTimeUnits->as_string(0);

	// Load in time data
	DataVector<int> vecTimeInt;
	DataVector<float> vecTimeFloat;
	DataVector<double> vecTimeDouble;
	DataVector<ncint64> vecTimeInt64;

	if (varTime->type() == ncInt) {
		vecTimeInt.Initialize(dimTime->size());
		varTime->set_cur((long)0);
		varTime->get(&(vecTimeInt[0]), dimTime->size());

	} else if (varTime->type() == ncFloat) {
		vecTimeFloat.Initialize(dimTime->size());
		varTime->set_cur((long)0);
		varTime->get(&(vecTimeFloat[0]), dimTime->size());

	} else if (varTime->type() == ncDouble) {
		vecTimeDouble.Initialize(dimTime->size());
		varTime->set_cur((long)0);
		varTime->get(&(vecTimeDouble[0]), dimTime->size());

	} else if (varTime->type() == ncInt64) {
		vecTimeInt64.Initialize(dimTime->size());
		varTime->set_cur((long)0);
		varTime->get(&(vecTimeInt64[0]), dimTime->size());

	} else {
		_EXCEPTION1("Variable \"time\" has invalid type "
			"(expected \"int\", \"int64\", \"float\" or \"double\")"
			" in file \"%s\"", strFilename.c_str());
	}

	for (int t = 0; t < dimTime->size(); t++) {
		Time time(eCalendarType);
		if (varTime->type() == ncInt) {
			time.FromCFCompliantUnitsOffsetInt(
				strTimeUnits,
				vecTimeInt[t]);

		} else if (varTime->type() == ncFloat) {
			time.FromCFCompliantUnitsOffsetDouble(
				strTimeUnits,
				static_cast<double>(vecTimeFloat[t]));

		} else if (varTime->type() == ncDouble) {
			time.FromCFCompliantUnitsOffsetDouble(
				strTimeUnits,
				vecTimeDouble[t]);

		} else if (varTime->type() == ncInt64) {
			time.FromCFCompliantUnitsOffsetInt(
				strTimeUnits,
				(int)(vecTimeInt64[t]));

		}

		vecTimes.push_back(time);
	}
}
int main(void)
{
   // These will hold our pressure and temperature data.
   float presIn[NLAT][NLON];
   float tempIn[NLAT][NLON];

   // These will hold our latitudes and longitudes.
   float latsIn[NLAT];
   float lonsIn[NLON];
  
   // Change the error behavior of the netCDF C++ API by creating an
   // NcError object. Until it is destroyed, this NcError object will
   // ensure that the netCDF C++ API silently returns error codes on
   // any failure, and leaves any other error handling to the calling
   // program. In the case of this example, we just exit with an
   // NC_ERR error code.
   NcError err(NcError::silent_nonfatal);

   // Open the file and check to make sure it's valid.
   NcFile dataFile("sfc_pres_temp.nc", NcFile::ReadOnly);
   if(!dataFile.is_valid())
      return NC_ERR;
  
   // There are a number of inquiry functions in netCDF which can be
   // used to learn about an unknown netCDF file. In this case we know
   // that there are 2 netCDF dimensions, 4 netCDF variables, no
   // global attributes, and no unlimited dimension.
   if (dataFile.num_dims() != 2 || dataFile.num_vars() != 4 || 
       dataFile.num_atts() != 0 || dataFile.rec_dim() != 0)  
      return NC_ERR;
     
   // We get back a pointer to each NcVar we request. Get the
   // latitude and longitude coordinate variables.
   NcVar *latVar, *lonVar;
   if (!(latVar = dataFile.get_var("latitude")))
      return NC_ERR;
   if (!(lonVar = dataFile.get_var("longitude")))
      return NC_ERR;
       
   // Read the latitude and longitude coordinate variables into arrays
   // latsIn and lonsIn.
   if (!latVar->get(latsIn, NLAT))
      return NC_ERR;
   if (!lonVar->get(lonsIn, NLON))
      return NC_ERR;
       
   // Check the coordinate variable data. 
   for(int lat = 0; lat < NLAT; lat++)
      if (latsIn[lat] != START_LAT + 5. * lat)
	 return NC_ERR;
   
   // Check longitude values.
   for (int lon = 0; lon < NLON; lon++)
      if (lonsIn[lon] != START_LON + 5. * lon)
	 return NC_ERR;
   
   // We get back a pointer to each NcVar we request. 
   NcVar *presVar, *tempVar;
   if (!(presVar = dataFile.get_var("pressure")))
      return NC_ERR;
   if (!(tempVar = dataFile.get_var("temperature")))
      return NC_ERR;
       
   // Read the data. Since we know the contents of the file we know
   // that the data arrays in this program are the correct size to
   // hold all the data.
   if (!presVar->get(&presIn[0][0], NLAT, NLON))
      return NC_ERR;
   if (!tempVar->get(&tempIn[0][0], NLAT, NLON))
      return NC_ERR;
       
   // Check the data. 
   for (int lat = 0; lat < NLAT; lat++)
      for (int lon = 0; lon < NLON; lon++)
	 if (presIn[lat][lon] != SAMPLE_PRESSURE + (lon * NLAT + lat)
	     || tempIn[lat][lon] != SAMPLE_TEMP + .25 * (lon * NLAT + lat))
	    return NC_ERR;
   
   // Each of the netCDF variables has a "units" attribute. Let's read
   // them and check them.
   NcAtt *att;
   char *units;
   
   if (!(att = latVar->get_att("units")))
      return NC_ERR;
   units = att->as_string(0);
   if (strncmp(units, "degrees_north", strlen("degrees_north")))
      return NC_ERR;
   // Attributes and attribute values should be deleted by the caller
   // when no longer needed, to prevent memory leaks.
   delete units;
   delete att;

   if (!(att = lonVar->get_att("units")))
      return NC_ERR;
   units = att->as_string(0);
   if (strncmp(units, "degrees_east", strlen("degrees_east")))
      return NC_ERR;
   delete units;
   delete att;
   
   if (!(att = presVar->get_att("units")))
      return NC_ERR;
   units = att->as_string(0);
   if (strncmp(units, "hPa", strlen("hPa")))
      return NC_ERR;
   delete units;
   delete att;
   
   if (!(att = tempVar->get_att("units")))
      return NC_ERR;
   units = att->as_string(0);
   if (strncmp(units, "celsius", strlen("celsius")))
      return NC_ERR;
   delete units;
   delete att;

   // The file will be automatically closed by the destructor. This
   // frees up any internal netCDF resources associated with the file,
   // and flushes any buffers.
   cout << "*** SUCCESS reading example file sfc_pres_temp.nc!" << endl;

   return 0;
}
int main(int argc, char** argv) {

	NcError error(NcError::silent_nonfatal);

try {
	// Input filename
	std::string strInputFile;

	// Output mesh filename
	std::string strOutputFile;

	// Polynomial degree per element
	int nP = 2;

	// Parse the command line
	BeginCommandLine()
		CommandLineString(strInputFile, "in", "");
		CommandLineString(strOutputFile, "out", "");
		//CommandLineInt(nP, "np", 2);
		//CommandLineBool(fCGLL, "cgll");

		ParseCommandLine(argc, argv);
	EndCommandLine(argv)

	// Check file names
	if (strInputFile == "") {
		std::cout << "ERROR: No input file specified" << std::endl;
		return (-1);
	}
	if (strOutputFile == "") {
		std::cout << "ERROR: No output file specified" << std::endl;
		return (-1);
	}
	if (nP < 1) {
		std::cout << "ERROR: --np must be >= 2" << std::endl;
		return (-1);
	}

	AnnounceBanner();

	// Load input mesh
	AnnounceStartBlock("Loading input mesh");

	Mesh meshIn(strInputFile);
	meshIn.RemoveZeroEdges();

	AnnounceEndBlock("Done");

	// Construct edge map
	AnnounceStartBlock("Constructing edge map");

	meshIn.ConstructEdgeMap();

	AnnounceEndBlock("Done");

	// Build connectivity vector using edge map
	AnnounceStartBlock("Constructing connectivity");

    std::vector< std::set<int> > vecConnectivity;
    int err = GenerateConnectivityData(meshIn, vecConnectivity);
    if (err) return err;

	AnnounceEndBlock("Done");

	// Open output file
	AnnounceStartBlock("Writing connectivity file");

	NcFile ncmesh(strInputFile.c_str(), NcFile::ReadOnly);

	NcVar * varLat = ncmesh.get_var("grid_center_lat");
	NcVar * varLon = ncmesh.get_var("grid_center_lon");

	// Check if center latitudes and longitudes are already available
	DataArray1D<double> dAllLats;
	DataArray1D<double> dAllLons;

	bool fConvertLatToDegrees = true;
	bool fConvertLonToDegrees = true;

	if ((varLat == NULL) || (varLon == NULL)) {
		Announce("grid_center_lat not found, recalculating face centers");
	} else {
		Announce("grid_center_lat found in file, loading values");

		if (varLat->get_dim(0)->size() != vecConnectivity.size()) {
			_EXCEPTIONT("grid_center_lat dimension mismatch");
		}
		if (varLon->get_dim(0)->size() != vecConnectivity.size()) {
			_EXCEPTIONT("grid_center_lon dimension mismatch");
		}

		dAllLats.Allocate(vecConnectivity.size());
		varLat->set_cur((long)0);
		varLat->get(dAllLats, vecConnectivity.size());

		NcAtt * attLatUnits = varLat->get_att("units");
		std::string strLatUnits = attLatUnits->as_string(0);
		if (strLatUnits == "degrees") {
			fConvertLatToDegrees = false;
		}

		dAllLons.Allocate(vecConnectivity.size());
		varLon->set_cur((long)0);
		varLon->get(dAllLons, vecConnectivity.size());

		NcAtt * attLonUnits = varLon->get_att("units");
		std::string strLonUnits = attLonUnits->as_string(0);
		if (strLonUnits == "degrees") {
			fConvertLonToDegrees = false;
		}

	}

	// Write connectiivty file
	FILE * fp = fopen(strOutputFile.c_str(), "w");
	fprintf(fp, "%lu\n", vecConnectivity.size());
	for (size_t f = 0; f < vecConnectivity.size(); f++) {
		double dLon;
		double dLat;

		if ((varLat == NULL) || (varLon == NULL)) {
			Node nodeCentroid;
			for (int i = 0; i < meshIn.faces[f].edges.size(); i++) {
				nodeCentroid.x += meshIn.nodes[meshIn.faces[f][i]].x;
				nodeCentroid.y += meshIn.nodes[meshIn.faces[f][i]].y;
				nodeCentroid.z += meshIn.nodes[meshIn.faces[f][i]].z;
			}
			double dMagnitude = nodeCentroid.Magnitude();

			nodeCentroid.x /= dMagnitude;
			nodeCentroid.y /= dMagnitude;
			nodeCentroid.z /= dMagnitude;

			dLon = atan2(nodeCentroid.y, nodeCentroid.x);
			dLat = asin(nodeCentroid.z);

			if (dLon < 0.0) {
				dLon += 2.0 * M_PI;
			}

		} else {
			dLon = dAllLons[f];
			dLat = dAllLats[f];
		}

		if (fConvertLonToDegrees) {
			dLon *= 180.0 / M_PI;
		}
		if (fConvertLatToDegrees) {
			dLat *= 180.0 / M_PI;
		}

		fprintf(fp, "%1.14f,", dLon);
		fprintf(fp, "%1.14f,", dLat);
		fprintf(fp, "%lu", vecConnectivity[f].size());

		std::set<int>::const_iterator iter = vecConnectivity[f].begin();
		for (; iter != vecConnectivity[f].end(); iter++) {
			fprintf(fp, ",%i", *iter);
		}
		if (f != vecConnectivity.size()-1) {
			fprintf(fp,"\n");
		}
	}
	fclose(fp);

	AnnounceEndBlock("Done");

	// Announce
	AnnounceBanner();

	return (0);

} catch(Exception & e) {
	Announce(e.ToString().c_str());
	return (-1);

} catch(...) {
	return (-2);
}
}
bool
RemapWidget::getVolumeInfo(QString volfile,
			   int &skipheaderbytes,
			   uchar &voxelType,
			   int &voxelUnit,
			   float &vx, float &vy, float &vz,
			   QString &description,
			   QList<float> &rawMap,
			   QList<uchar> &pvlMap,
			   int &depth,
			   int &width,
			   int &height)
{
  NcError err(NcError::verbose_nonfatal);

  NcFile pvlFile(volfile.toAscii().data(), NcFile::ReadOnly);

  if (!pvlFile.is_valid())
    {
      QMessageBox::information(0, "Error",
       QString("%1 is not a valid preprocessed volume file").arg(volfile));
      return false;
    }

  int i;
  NcAtt *att;
  char *attval;
  QString pvalue;

  att = pvlFile.get_att("description");
  if (att)
    {
      attval = att->as_string(0);
      description = attval;
      delete [] attval;
    }

  att = pvlFile.get_att("voxeltype");
  if (att)
    {
      attval = att->as_string(0);
      pvalue = attval;
      if (pvalue == "unsigned char")
	voxelType = Raw2Pvl::_UChar;
      if (pvalue == "char")
	voxelType = Raw2Pvl::_Char;
      if (pvalue == "unsigned short")
	voxelType = Raw2Pvl::_UShort;
      if (pvalue == "short")
	voxelType = Raw2Pvl::_Short;
      if (pvalue == "int")
	voxelType = Raw2Pvl::_Int;
      if (pvalue == "float")
	voxelType = Raw2Pvl::_Float;
      delete [] attval;
    }


  att = pvlFile.get_att("voxelunit");
  if (att)
    { 
      attval = att->as_string(0);
      pvalue = attval;
      voxelUnit = Raw2Pvl::_Nounit;
      if (pvalue == "angstrom")
	voxelUnit = Raw2Pvl::_Angstrom;
      else if (pvalue == "nanometer")
	voxelUnit = Raw2Pvl::_Nanometer;
      else if (pvalue == "micron")
	voxelUnit = Raw2Pvl::_Micron;
      else if (pvalue == "millimeter")
	voxelUnit = Raw2Pvl::_Millimeter;
      else if (pvalue == "centimeter")
	voxelUnit = Raw2Pvl::_Centimeter;
      else if (pvalue == "meter")
	voxelUnit = Raw2Pvl::_Meter;
      else if (pvalue == "kilometer")
	voxelUnit = Raw2Pvl::_Kilometer;
      else if (pvalue == "parsec")
	voxelUnit = Raw2Pvl::_Parsec;
      else if (pvalue == "kiloparsec")
	voxelUnit = Raw2Pvl::_Kiloparsec;
      delete [] attval;
    }
  
  
  att = pvlFile.get_att("gridsize");
  if (att)
    {
      depth = att->as_int(0);
      width = att->as_int(1);
      height = att->as_int(2);
    }

  att = pvlFile.get_att("voxelsize");
  if (att)
    {
      vx = att->as_float(0);
      vy = att->as_float(1);
      vz = att->as_float(2);
    }

  att = pvlFile.get_att("skipheaderbytes");
  if (att)
    skipheaderbytes = att->as_int(0);
  
  att = pvlFile.get_att("mapraw");
  if (att)
    {
      for(i=0; i<att->num_vals(); i++)
	rawMap.append(att->as_float(i));
  
      att = pvlFile.get_att("mappvl");
      for(i=0; i<att->num_vals(); i++)
	pvlMap.append(att->as_ncbyte(i));
    }

  pvlFile.close();
  return true;
}
void
avtS3DFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md,
                                           int timeState)
{
    debug5 << "avtS3DFileFormat::PopulateDatabaseMetaData" << endl;
    // Get the metadata from the log file first.
    OpenLogFile();

    // Mesh
    avtMeshMetaData *mesh = new avtMeshMetaData;
    mesh->name = "mesh";
    mesh->meshType = AVT_RECTILINEAR_MESH;
    mesh->numBlocks = procs[0] * procs[1] * procs[2];
    mesh->blockOrigin = 1;
    mesh->cellOrigin = 0;
    mesh->spatialDimension = 3;
    mesh->topologicalDimension = 3;
    mesh->blockTitle = "blocks";
    mesh->blockPieceName = "block";
    mesh->hasSpatialExtents = false;
    mesh->xUnits = "mm";
    mesh->yUnits = "mm";
    mesh->zUnits = "mm";
    md->Add(mesh);

    //
    // Look in the NetCDF file for the first block for the list of variables.
    //

    // Calculate the timestep directory that the data lives in.
    char *pathcopy = strdup(mainFilename);
    string dir = parse_dirname(pathcopy);
    string timestepDir = CreateStringFromDouble(fileTimes[timeState]);

    char path[256];
    SNPRINTF(path,256,"%s%s%s%sfield.00000",dir.c_str(),VISIT_SLASH_STRING, timestepDir.c_str(), VISIT_SLASH_STRING);

    NcError err(NcError::verbose_nonfatal);
 
    NcFile nf(path);
    if (!nf.is_valid())
    {
        EXCEPTION1(InvalidFilesException, path);
    }
    debug5 << "avtS3DFileFormat::PopulateDatabaseMetaData: Got valid file" << endl;

    int nvars = nf.num_vars();
    debug5 << "avtS3DFileFormat::PopulateDatabaseMetaData: Found " << nvars << " variables" << endl;
    for (int i=0 ; i<nvars; i++)
    {
        NcVar *v = nf.get_var(i);
        if (!v)
            continue;
        debug4 << "Found variable " << v->name() << endl;

        // Check dimensionality
        int nvals = v->num_vals();
        if (nvals != 1) // Single scalars are useless.
        {
            avtScalarMetaData *scalar = new avtScalarMetaData();
            scalar->name = v->name();
            scalar->meshName = "mesh";
            scalar->centering = AVT_NODECENT;
            scalar->hasDataExtents = false;
            scalar->treatAsASCII = false;

            NcAtt *units = v->get_att(NcToken("units"));
            if (units)
            {
                long nv = units->num_vals();
                if (nv == 0)
                {
                    scalar->hasUnits = false;
                } else {
                    char *unitString = units->as_string(0);
                    scalar->units = unitString;
                    scalar->hasUnits = true;
                }
            } else
                scalar->hasUnits = false;

            md->Add(scalar);
        } else {
            debug4 << "Unable to process variable " << v->name() <<
                      " since it is a single scalar" << endl;

        }
    }

#if 0
    // Expressions
    Expression tempGradient_expr;
    tempGradient_expr.SetName("Temperature_gradient");
    tempGradient_expr.SetDefinition("gradient(Temperature)");
    tempGradient_expr.SetType(Expression::VectorMeshVar);
    tempGradient_expr.SetHidden(true);
    md->AddExpression(&tempGradient_expr);

    Expression tempUnit_expr;
    tempUnit_expr.SetName("Temperature_grad_unit");
    //tempUnit_expr.SetDefinition("(Temperature_gradient + {1e-6,0,0})/(magnitude(Temperature_gradient) + 1e-6)");
    //tempUnit_expr.SetDefinition("Temperature_gradient/(magnitude(Temperature_gradient) + 1e-6)");
    tempUnit_expr.SetDefinition("normalize(Temperature_gradient)");
    tempUnit_expr.SetType(Expression::VectorMeshVar);
    tempUnit_expr.SetHidden(true);
    md->AddExpression(&tempUnit_expr);

    Expression tempCurv_expr;
    tempCurv_expr.SetName("Temperature_curvature");
    tempCurv_expr.SetDefinition("divergence(Temperature_grad_unit)");
    tempCurv_expr.SetType(Expression::ScalarMeshVar);
    tempUnit_expr.SetHidden(false);
    md->AddExpression(&tempCurv_expr);
#endif
}