Esempio n. 1
0
eavlField*
eavlNetCDFImporter::GetField(const string &name, const string &mesh, int)
{
    for (unsigned int v=0; v<vars.size(); v++)
    {
        NcVar *var = vars[v];
        if (name != var->name())
            continue;

        if (debugoutput) cerr << "reading var "<<v+1<<" / "<<vars.size()<<endl;
        eavlFloatArray *arr = new eavlFloatArray(var->name(), 1);
        arr->SetNumberOfTuples(var->num_vals());
        NcValues *vals = var->values();
        int n = var->num_vals();
        for (int i=0; i<n; i++)
        {
            arr->SetComponentFromDouble(i,0, vals->as_double(i));
        }

        eavlField *field = new eavlField(1, arr, eavlField::ASSOC_POINTS);
        return field;
    }

    return NULL;
}
Esempio n. 2
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;
}
Esempio n. 3
0
void DumpableNcFile::dumpvars( void )
{
    int n;
    static const char* types[] =
      {"","byte","char","short","long","float","double"};
    NcVar* vp;

    for(n = 0; vp = get_var(n); n++) {
	cout << "\t" << types[vp->type()] << " " << vp->name() ;

	if (vp->num_dims() > 0) {
	    cout << "(";
	    for (int d = 0; d < vp->num_dims(); d++) {
		NcDim* dim = vp->get_dim(d);
		cout << dim->name();
		if (d < vp->num_dims()-1)
		  cout << ", ";		  
	    }
	    cout << ")";
	}
	cout << " ;\n";
	// now dump each of this variable's attributes
	dumpatts(*vp);
    }
}
Esempio n. 4
0
void NetCdfConfigureDialog::setVariableSelect()
{
    for (int i=0; i<(_currentFile->num_vars()); i++)
    {
        NcVar *focusedVar = _currentFile->get_var(i);
        if (focusedVar->num_dims() > 0) comboBoxVariable->addItem(focusedVar->name());
    }
}
Esempio n. 5
0
void DumpableNcFile::dumpdata( )
{
    NcVar* vp;
    for (int n = 0; vp = get_var(n); n++) {
	cout << " " << vp->name() << " = ";
	NcValues* vals = vp->values();
	cout << *vals << " ;" << endl ;
	delete vals;
    }
}
Esempio n. 6
0
vector<string>
eavlNetCDFImporter::GetFieldList(const string &mesh)
{
    vector<string> retval;
    for (unsigned int v=0; v<vars.size(); v++)
    {
        NcVar *var = vars[v];
        retval.push_back(var->name());
    }
    return retval;
}
Esempio n. 7
0
void dumpatts(NcVar& var)
{
    NcToken vname = var.name();
    NcAtt* ap;
    for(int n = 0; ap = var.get_att(n); n++) {
	cout << "\t\t" << vname << ":" << ap->name() << " = " ;
	NcValues* vals = ap->values();
	cout << *vals << " ;" << endl ;
	delete ap;
	delete vals;
    }
}
Esempio n. 8
0
Kst::Object::UpdateType NetcdfSource::internalDataSourceUpdate() {
  //TODO port
  /*
  if (KstObject::checkUpdateCounter(u)) {
    return lastUpdateResult();
  }
  */

  _ncfile->sync();

  bool updated = false;
  /* Update member variables _ncfile, _maxFrameCount, and _frameCounts
     and indicate that an update is needed */
  int nb_vars = _ncfile->num_vars();
  for (int j = 0; j < nb_vars; j++) {
    NcVar *var = _ncfile->get_var(j);
    int fc = var->num_vals() / var->rec_size();
    _maxFrameCount = qMax(_maxFrameCount, fc);
    updated = updated || (_frameCounts[var->name()] != fc);
    _frameCounts[var->name()] = fc;
  }
  return updated ? Object::Updated : Object::NoChange;
}
void CopyNcVar(
	NcFile & ncIn,
	NcFile & ncOut,
	const std::string & strVarName,
	bool fCopyAttributes,
	bool fCopyData
) {
	if (!ncIn.is_valid()) {
		_EXCEPTIONT("Invalid input file specified");
	}
	if (!ncOut.is_valid()) {
		_EXCEPTIONT("Invalid output file specified");
	}
	NcVar * var = ncIn.get_var(strVarName.c_str());
	if (var == NULL) {
		_EXCEPTION1("NetCDF file does not contain variable \"%s\"",
			strVarName.c_str());
	}

	NcVar * varOut;

	std::vector<NcDim *> dimOut;
	dimOut.resize(var->num_dims());

	std::vector<long> counts;
	counts.resize(var->num_dims());

	long nDataSize = 1;

	for (int d = 0; d < var->num_dims(); d++) {
		NcDim * dimA = var->get_dim(d);

		dimOut[d] = ncOut.get_dim(dimA->name());

		if (dimOut[d] == NULL) {
			if (dimA->is_unlimited()) {
				dimOut[d] = ncOut.add_dim(dimA->name());
			} else {
				dimOut[d] = ncOut.add_dim(dimA->name(), dimA->size());
			}

			if (dimOut[d] == NULL) {
				_EXCEPTION2("Failed to add dimension \"%s\" (%i) to file",
					dimA->name(), dimA->size());
			}
		}
		if (dimOut[d]->size() != dimA->size()) {
			if (dimA->is_unlimited() && !dimOut[d]->is_unlimited()) {
				_EXCEPTION2("Mismatch between input file dimension \"%s\" and "
					"output file dimension (UNLIMITED / %i)",
					dimA->name(), dimOut[d]->size());
			} else if (!dimA->is_unlimited() && dimOut[d]->is_unlimited()) {
				_EXCEPTION2("Mismatch between input file dimension \"%s\" and "
					"output file dimension (%i / UNLIMITED)",
					dimA->name(), dimA->size());
			} else if (!dimA->is_unlimited() && !dimOut[d]->is_unlimited()) {
				_EXCEPTION3("Mismatch between input file dimension \"%s\" and "
					"output file dimension (%i / %i)",
					dimA->name(), dimA->size(), dimOut[d]->size());
			}
		}

		counts[d] = dimA->size();
		nDataSize *= counts[d];
	}

	// ncByte / ncChar type
	if ((var->type() == ncByte) || (var->type() == ncChar)) {
		DataVector<char> data;
		data.Initialize(nDataSize);

		varOut =
			ncOut.add_var(
				var->name(), var->type(),
				dimOut.size(), (const NcDim**)&(dimOut[0]));

		if (varOut == NULL) {
			_EXCEPTION1("Cannot create variable \"%s\"", var->name());
		}

		var->get(&(data[0]), &(counts[0]));
		varOut->put(&(data[0]), &(counts[0]));
	}

	// ncShort type
	if (var->type() == ncShort) {
		DataVector<short> data;
		data.Initialize(nDataSize);

		varOut =
			ncOut.add_var(
				var->name(), var->type(),
				dimOut.size(), (const NcDim**)&(dimOut[0]));

		if (varOut == NULL) {
			_EXCEPTION1("Cannot create variable \"%s\"", var->name());
		}

		if (fCopyData) {
			var->get(&(data[0]), &(counts[0]));
			varOut->put(&(data[0]), &(counts[0]));
		}
	}

	// ncInt type
	if (var->type() == ncInt) {
		DataVector<int> data;
		data.Initialize(nDataSize);

		varOut =
			ncOut.add_var(
				var->name(), var->type(),
				dimOut.size(), (const NcDim**)&(dimOut[0]));

		if (varOut == NULL) {
			_EXCEPTION1("Cannot create variable \"%s\"", var->name());
		}

		if (fCopyData) {
			var->get(&(data[0]), &(counts[0]));
			varOut->put(&(data[0]), &(counts[0]));
		}
	}

	// ncFloat type
	if (var->type() == ncFloat) {
		DataVector<float> data;
		data.Initialize(nDataSize);

		varOut =
			ncOut.add_var(
				var->name(), var->type(),
				dimOut.size(), (const NcDim**)&(dimOut[0]));

		if (varOut == NULL) {
			_EXCEPTION1("Cannot create variable \"%s\"", var->name());
		}

		if (fCopyData) {
			var->get(&(data[0]), &(counts[0]));
			varOut->put(&(data[0]), &(counts[0]));
		}
	}

	// ncDouble type
	if (var->type() == ncDouble) {
		DataVector<double> data;
		data.Initialize(nDataSize);

		varOut =
			ncOut.add_var(
				var->name(), var->type(),
				dimOut.size(), (const NcDim**)&(dimOut[0]));

		if (varOut == NULL) {
			_EXCEPTION1("Cannot create variable \"%s\"", var->name());
		}

		if (fCopyData) {
			var->get(&(data[0]), &(counts[0]));
			varOut->put(&(data[0]), &(counts[0]));
		}
	}

	// ncInt64 type
	if (var->type() == ncInt64) {
		DataVector<ncint64> data;
		data.Initialize(nDataSize);

		varOut =
			ncOut.add_var(
				var->name(), var->type(),
				dimOut.size(), (const NcDim**)&(dimOut[0]));

		if (varOut == NULL) {
			_EXCEPTION1("Cannot create variable \"%s\"", var->name());
		}

		if (fCopyData) {
			var->get(&(data[0]), &(counts[0]));
			varOut->put(&(data[0]), &(counts[0]));
		}
	}

	// Check output variable exists
	if (varOut == NULL) {
		_EXCEPTION1("Unable to create output variable \"%s\"",
			var->name());
	}

	// Copy attributes
	if (fCopyAttributes) {
		CopyNcVarAttributes(var, varOut);
	}
}
Esempio n. 10
0
int main(int argc, char** argv)
{
    if (!cmdline(argc, argv))
    {
        printhelp();
        return EXIT_FAILURE;
    }

    NcFile infile(infilename.c_str(), NcFile::ReadOnly);
    if (!infile.is_valid())
    {
        std::cerr << "Error: invalid input file -- '" << infilename << "'" << std::endl;
        infile.close();
        return EXIT_FAILURE;
    }

    NcFile outfile(outfilename.c_str(), NcFile::Replace);
    if (!outfile.is_valid())
    {
        std::cerr << "Error: cannot open output file -- '" << outfilename << "'" << std::endl;
        outfile.close();
        return EXIT_FAILURE;
    }

    if (varstrings.size() == 0)
    {
        std::cerr << "Warning: no variables specified" << std::endl;
    }

    std::vector<NcVar*> invars;
    for (std::vector<std::string>::const_iterator it = varstrings.begin();
         it != varstrings.end(); ++it)
    {
        NcVar* var = infile.get_var((*it).c_str());
        if (var == NULL)
        {
            std::cerr << "Error: " << *it << ": no such variable" << std::endl;
            infile.close();
            outfile.close();
            return EXIT_FAILURE;
        }
        invars.push_back(var);
    }

    // extract the distinct set of dims
    std::map<std::string, NcDim*> indims;
    for (std::vector<NcVar*>::const_iterator it = invars.begin();
         it != invars.end(); ++it)
    {
        NcVar* var = *it;
        for (int i = 0; i < var->num_dims(); ++i)
        {
            NcDim* dim = var->get_dim(i);
            indims[dim->name()] = dim;
        }
    }

    // add dims to outfile
    std::map<std::string, NcDim*> outdims;
    for (std::map<std::string, NcDim*>::const_iterator it = indims.begin();
         it != indims.end(); ++it)
    {
        NcDim* dim = (*it).second;
        NcDim* outdim = NULL;
        if (dim->is_unlimited())
        {
            outdim = outfile.add_dim(dim->name());
        }
        else
        {
            outdim = outfile.add_dim(dim->name(), dim->size());
        }

        if (outdim != NULL)
        {
            outdims[outdim->name()] = outdim;
        }
    }

    // create variables
    for (std::vector<NcVar*>::const_iterator it = invars.begin();
         it != invars.end(); ++it)
    {
        NcVar* var = *it;
        std::vector<const NcDim*> dims(var->num_dims());
        for (int i = 0; i < var->num_dims(); ++i)
        {
            dims[i] = outdims[var->get_dim(i)->name()];
        }
        NcVar* outvar = outfile.add_var(var->name(), var->type(), var->num_dims(), &dims[0]);

        // identify largest dim, if dim (nearly) exceeds main memory, split along that dim
        int maxdim = -1;
        long maxdimsize = 0;
        long totallen = 1;
        for (int i = 0; i < var->num_dims(); ++i)
        {
            NcDim* dim = var->get_dim(i);
            if (dim->size() > maxdimsize)
            {
                maxdim = i;
                maxdimsize = dim->size();
            }
            totallen *= dim->size();
        }

        // TODO: support other data types
        totallen *= sizeof(float);

        // TODO: configurable page size
        const unsigned long pagesize = 1000000000;
#ifdef __linux__
        struct sysinfo info;
        sysinfo(&info);
        if (pagesize >= info.freeram)
        {
            std::cerr << "Warning: page size exceeds free memory" << std::endl;
        }
#endif

        int numpages = 1;
        long pagesizedim = var->get_dim(maxdim)->size();
        if (totallen < pagesize)
        {
        }
        else
        {
            long mul = 1;
            for (int i = 0; i < var->num_dims(); ++i)
            {
                if (i != maxdim)
                {
                    NcDim* dim = var->get_dim(i);
                    mul *= dim->size();
                }
            }
            // TODO: support other data types
            mul *= sizeof(float);

            pagesizedim = pagesize / mul;
            numpages = var->get_dim(maxdim)->size() / pagesizedim;
            if (var->get_dim(maxdim)->size() % pagesizedim > 0)
            {
                ++numpages;
            }
        }

        std::vector< std::vector<long> > curvec;
        std::vector< std::vector<long> > countsvec;
        std::vector<long> lengths;

        int pages = numpages > 0 ? numpages : 1;
        for (int p = 0; p < pages; ++p)
        {
            long len = 1;
            std::vector<long> cur;
            std::vector<long> counts;
            for (int i = 0; i < var->num_dims(); ++i)
            {
                NcDim* dim = var->get_dim(i);
                long current = 0;
                long count = dim->size();
                if (i == maxdim)
                {
                    current = pagesizedim * p;
                    count = pagesizedim;
                    if (p == pages -1)
                    {
                        if (dim->size() % pagesizedim != 0)
                        {
                            count = dim->size() % pagesizedim;
                        }
                    }
                }
                cur.push_back(current);
                counts.push_back(count);
                len *= count;
            }
            curvec.push_back(cur);
            countsvec.push_back(counts);
            lengths.push_back(len);
        }

        std::vector< std::vector<long> >::const_iterator it1;
        std::vector< std::vector<long> >::const_iterator it2;
        std::vector<long>::const_iterator it3;

        for (it1 = curvec.begin(), it2 = countsvec.begin(), it3 = lengths.begin();
             it1 != curvec.end() && it2 != countsvec.end() && it3 != lengths.end(); ++it1, ++it2, ++it3)
        {
            std::vector<long> cur = *it1;
            std::vector<long> counts = *it2;
            long len = *it3;

            var->set_cur(&cur[0]);
            outvar->set_cur(&cur[0]);
            switch (outvar->type())
            {
            case ncByte:
            {
                ncbyte* barr = new ncbyte[len];
                var->get(barr, &counts[0]);
                outvar->put(barr, &counts[0]);
                delete[] barr;
                break;
            }
            case ncChar:
            {
                char* carr = new char[len];
                var->get(carr, &counts[0]);
                outvar->put(carr, &counts[0]);
                delete[] carr;
                break;
            }
            case ncShort:
            {
                short* sarr = new short[len];
                var->get(sarr, &counts[0]);
                outvar->put(sarr, &counts[0]);
                delete[] sarr;
                break;
            }
            case ncInt:
            {
                long* larr = new long[len];
                var->get(larr, &counts[0]);
                outvar->put(larr, &counts[0]);
                delete[] larr;
                break;
            }
            case ncFloat:
            {
                float* farr = new float[len];
                var->get(farr, &counts[0]);
                outvar->put(farr, &counts[0]);
                delete[] farr;
                break;
            }
            case ncDouble:
            {
                double* darr = new double[len];
                var->get(darr, &counts[0]);
                outvar->put(darr, &counts[0]);
                delete[] darr;
                break;
            }
            default:
                break;
            }
        }
    }

    infile.close();
    outfile.close();
    return 0;
}
Esempio n. 11
0
 const std::string name( void ) const
 {
     return( m_var->name() );
 }
Esempio n. 12
0
eavlNetCDFImporter::eavlNetCDFImporter(const string &filename)
{
    file = new NcFile(filename.c_str(), NcFile::ReadOnly);
     
    if (!file->is_valid())
    {
        THROW(eavlException,"Couldn't open file!\n");
    }

    if (debugoutput) cerr << "num_dims="<<file->num_dims()<<endl;
    if (debugoutput) cerr << "num_vars="<<file->num_vars()<<endl;
    if (debugoutput) cerr << "num_atts="<<file->num_atts()<<endl;

    for (int i=0; i<file->num_dims(); i++)
    {
        NcDim *d = file->get_dim(i);
        if (debugoutput) cerr << "  dim["<<i<<"]: name="<<d->name()<<" size="<<d->size()<<endl;
    }

    for (int i=0; i<file->num_atts(); i++)
    {
        NcAtt *a = file->get_att(i);
        if (debugoutput) cerr << "  att["<<i<<"]: name="<<a->name()<<" numvals="<<a->num_vals()<<endl;
    }

    bool found_grid = false;

    for (int i=0; i<file->num_vars(); i++)
    {
        NcVar *v = file->get_var(i);
        if (debugoutput) 
        {
            cerr << "  var["<<i<<"]: name="<<v->name();
            cerr << "  ndims="<<v->num_dims();
            cerr << "  dims = ";
            for (int j=0; j<v->num_dims(); j++)
            {
                cerr << v->get_dim(j)->name();
                if (j<v->num_dims()-1)
                    cerr << "*";
            }
            cerr << endl;
        }

        // Here's the condition for what we're going to use;
        // we only support one mesh for the moment, so we're picking one.
        // Also, the netcdf files we have have the time dim size as "1"
        if (v->num_dims() == 4 && string(v->get_dim(0)->name())=="time")
        {
            if (!found_grid)
            {
                dims.push_back(v->get_dim(1));
                dims.push_back(v->get_dim(2));
                dims.push_back(v->get_dim(3));
                found_grid = true;
                vars.push_back(v);
                if (debugoutput) cerr << "     * using as first real var\n";
            }
            else
            {
                if (string(v->get_dim(1)->name()) == dims[0]->name() &&
                    string(v->get_dim(2)->name()) == dims[1]->name() &&
                    string(v->get_dim(3)->name()) == dims[2]->name())
                {
                    vars.push_back(v);
                    if (debugoutput) cerr << "     * using as another var; matches the first real one's dims\n";
                }
            }
        }

    }
}
bool EpidemicDataSet::loadNetCdfFile(const char * filename)
{
#if USE_NETCDF // TODO: should handle this differently
    // change netcdf library error behavior
    NcError err(NcError::verbose_nonfatal);

    // open the netcdf file
    NcFile ncFile(filename, NcFile::ReadOnly);

    if(!ncFile.is_valid())
    {
        put_flog(LOG_FATAL, "invalid file %s", filename);
        return false;
    }

    // get dimensions
    NcDim * timeDim = ncFile.get_dim("time");
    NcDim * nodesDim = ncFile.get_dim("nodes");
    NcDim * stratificationsDim = ncFile.get_dim("stratifications");

    if(timeDim == NULL || nodesDim == NULL || stratificationsDim == NULL)
    {
        put_flog(LOG_FATAL, "could not find a required dimension");
        return false;
    }

    numTimes_ = timeDim->size();

    // make sure we have the expected number of nodes
    if(nodesDim->size() != numNodes_)
    {
        put_flog(LOG_FATAL, "got %i nodes, expected %i", nodesDim->size(), numNodes_);
        return false;
    }

    put_flog(LOG_DEBUG, "file contains %i timesteps, %i nodes", numTimes_, numNodes_);

    // make sure number of stratifications matches our expectation...
    int numExpectedStratifications = 1;

    for(unsigned int i=0; i<NUM_STRATIFICATION_DIMENSIONS; i++)
    {
        numExpectedStratifications *= stratifications_[i].size();
    }

    if(stratificationsDim->size() != numExpectedStratifications)
    {
        put_flog(LOG_FATAL, "got %i stratifications, expected %i", stratificationsDim->size(), numExpectedStratifications);
        return false;
    }

    // get all float variables with dimensions (time, nodes, stratifications)
    for(int i=0; i<ncFile.num_vars(); i++)
    {
        NcVar * ncVar = ncFile.get_var(i);

        if(ncVar->num_dims() == 3 && ncVar->type() == ncFloat && strcmp(ncVar->get_dim(0)->name(), "time") == 0 && strcmp(ncVar->get_dim(1)->name(), "nodes") == 0 && strcmp(ncVar->get_dim(2)->name(), "stratifications") == 0)
        {
            put_flog(LOG_INFO, "found variable: %s", ncVar->name());

            // full shape
            blitz::TinyVector<int, 2+NUM_STRATIFICATION_DIMENSIONS> shape;
            shape(0) = numTimes_;
            shape(1) = numNodes_;

            for(int j=0; j<NUM_STRATIFICATION_DIMENSIONS; j++)
            {
                shape(2 + j) = stratifications_[j].size();
            }

            blitz::Array<float, 2+NUM_STRATIFICATION_DIMENSIONS> var((float *)ncVar->values()->base(), shape, blitz::duplicateData);

            variables_[std::string(ncVar->name())].reference(var);
        }
    }
#endif
    return true;
}
Esempio n. 14
0
bool
NetworkObject::loadNetCDF(QString flnm)
{
  m_fileName = flnm;

  NcError err(NcError::verbose_nonfatal);

  NcFile ncfFile(flnm.toLatin1().data(), NcFile::ReadOnly);
  NcAtt *att;
  NcVar *var;

  // ---- get gridsize -----
  att = ncfFile.get_att("gridsize");
  m_nX = att->as_int(0);
  m_nY = att->as_int(1);
  m_nZ = att->as_int(2);
  //------------------------

  // ---- get vertex centers -----
  var = ncfFile.get_var("vertex_centers");
  if (!var)
    var = ncfFile.get_var("vertex_center");
  if (!var)
    var = ncfFile.get_var("vertex_centres");
  if (!var)
    var = ncfFile.get_var("vertex_centre");
  
  int nv = var->get_dim(0)->size();
  float *vc = new float [3*nv];
  var->get(vc, nv, 3);
  m_vertexCenters.resize(nv);
  for(int i=0; i<nv; i++)
    m_vertexCenters[i] = Vec(vc[3*i+0], vc[3*i+1], vc[3*i+2]);
  delete [] vc;
  //------------------------


  // ---- get edges -----
  var = ncfFile.get_var("edge_neighbours");
  int ne = var->get_dim(0)->size();
  int *ed = new int [2*ne];
  var->get(ed, ne, 2);
  m_edgeNeighbours.resize(ne);
  for(int i=0; i<ne; i++)
    m_edgeNeighbours[i] = qMakePair(ed[2*i], ed[2*i+1]);
  delete [] ed;
  //------------------------


  Vec bmin = m_vertexCenters[0];
  Vec bmax = m_vertexCenters[0];
  for(int i=0; i<m_vertexCenters.count(); i++)
    {
      bmin = StaticFunctions::minVec(bmin, m_vertexCenters[i]);
      bmax = StaticFunctions::maxVec(bmax, m_vertexCenters[i]);
    }
  m_centroid = (bmin + bmax)/2;
  
  m_enclosingBox[0] = Vec(bmin.x, bmin.y, bmin.z);
  m_enclosingBox[1] = Vec(bmax.x, bmin.y, bmin.z);
  m_enclosingBox[2] = Vec(bmax.x, bmax.y, bmin.z);
  m_enclosingBox[3] = Vec(bmin.x, bmax.y, bmin.z);
  m_enclosingBox[4] = Vec(bmin.x, bmin.y, bmax.z);
  m_enclosingBox[5] = Vec(bmax.x, bmin.y, bmax.z);
  m_enclosingBox[6] = Vec(bmax.x, bmax.y, bmax.z);
  m_enclosingBox[7] = Vec(bmin.x, bmax.y, bmax.z);
    


//  QStringList vatt, eatt;
  int nvars = ncfFile.num_vars();
//  for (int i=0; i < nvars; i++)
//    {
//      var = ncfFile.get_var(i);      
//      QString attname = var->name();
//      attname.toLower();
//      if (attname.contains("vertex_") &&
//	  ( attname != "vertex_centers" ||
//	    attname != "vertex_centres"))
//	vatt.append(attname);
//      else if (attname.contains("edge_") &&
//	       attname != "edge_neighbours")
//	eatt.append(attname);
//    }

  m_vertexAttribute.clear();
  m_edgeAttribute.clear();

  m_vertexRadiusAttribute = -1;
  m_edgeRadiusAttribute = -1;

  int vri = 0;
  int eri = 0;
  for (int i=0; i < nvars; i++)
    {
      var = ncfFile.get_var(i);      
      QString attname = var->name();
      attname.toLower();

      if (attname.contains("vertex_") &&
	  attname != "vertex_center" &&
	  attname != "vertex_centre" &&
	  attname != "vertex_centers" &&
	  attname != "vertex_centres")
	{
	  if (attname == "vertex_radius")
	    m_vertexRadiusAttribute = vri;
	  vri++;

	  QVector<float> val;
	  val.clear();

	  if (var->type() == ncByte || var->type() == ncChar)
	    {
	      uchar *v = new uchar[nv];
	      var->get((ncbyte *)v, nv);
	      for(int j=0; j<nv; j++)
		val.append(v[j]);
	      delete [] v;
	    }
	  else if (var->type() == ncShort)
	    {
	      short *v = new short[nv];
	      var->get((short *)v, nv);
	      for(int j=0; j<nv; j++)
		val.append(v[j]);
	      delete [] v;
	    }
	  else if (var->type() == ncInt)
	    {
	      int *v = new int[nv];
	      var->get((int *)v, nv);
	      for(int j=0; j<nv; j++)
		val.append(v[j]);
	      delete [] v;
	    }
	  else if (var->type() == ncFloat)
	    {
	      float *v = new float[nv];
	      var->get((float *)v, nv);
	      for(int j=0; j<nv; j++)
		val.append(v[j]);
	      delete [] v;
	    }

	  if (val.count() > 0)
	    m_vertexAttribute.append(qMakePair(attname, val));
	}
      else if (attname.contains("edge_") &&
	       attname != "edge_neighbours")
	{
	  if (attname == "edge_radius")
	    m_edgeRadiusAttribute = eri;
	  eri++;

	  QVector<float> val;
	  val.clear();

	  if (var->type() == ncByte || var->type() == ncChar)
	    {
	      uchar *v = new uchar[ne];
	      var->get((ncbyte *)v, ne);
	      for(int j=0; j<ne; j++)
		val.append(v[j]);
	      delete [] v;
	    }
	  else if (var->type() == ncShort)
	    {
	      short *v = new short[ne];
	      var->get((short *)v, ne);
	      for(int j=0; j<ne; j++)
		val.append(v[j]);
	      delete [] v;
	    }
	  else if (var->type() == ncInt)
	    {
	      int *v = new int[ne];
	      var->get((int *)v, ne);
	      for(int j=0; j<ne; j++)
		val.append(v[j]);
	      delete [] v;
	    }
	  else if (var->type() == ncFloat)
	    {
	      float *v = new float[ne];
	      var->get((float *)v, ne);
	      for(int j=0; j<ne; j++)
		val.append(v[j]);
	      delete [] v;
	    }

	  if (val.count() > 0)
	    m_edgeAttribute.append(qMakePair(attname, val));
	}
    }

  ncfFile.close();
  
  if (!Global::batchMode())
    {
      QString str;
      str = QString("Grid Size : %1 %2 %3\n").arg(m_nX).arg(m_nY).arg(m_nZ);
      str += QString("Vertices : %1\n").arg(m_vertexCenters.count());
      str += QString("Edges : %1\n").arg(m_edgeNeighbours.count());
      str += QString("\n");
      str += QString("Vertex Attributes : %1\n").arg(m_vertexAttribute.count());
      for(int i=0; i<m_vertexAttribute.count(); i++)
	str += QString(" %1\n").arg(m_vertexAttribute[i].first);
      str += QString("\n");
      str += QString("Edge Attributes : %1\n").arg(m_edgeAttribute.count());
      for(int i=0; i<m_edgeAttribute.count(); i++)
	str += QString(" %1\n").arg(m_edgeAttribute[i].first);
      
      QMessageBox::information(0, "Network loaded", str);
    }

  m_Vatt = 0;
  m_Eatt = 0;
  m_Vminmax.clear();
  m_Eminmax.clear();
  m_userVminmax.clear();
  m_userEminmax.clear();

  for(int i=0; i<m_vertexAttribute.count(); i++)
    {
      float vmin = m_vertexAttribute[i].second[0];
      float vmax = m_vertexAttribute[i].second[0];
      for(int j=1; j<m_vertexAttribute[i].second.count(); j++)
	{
	  vmin = qMin((float)m_vertexAttribute[i].second[j], vmin);
	  vmax = qMax((float)m_vertexAttribute[i].second[j], vmax);
	}
      m_Vminmax.append(qMakePair(vmin, vmax));
      m_userVminmax.append(qMakePair((vmin+vmax)/2, vmax));
    }


  for(int i=0; i<m_edgeAttribute.count(); i++)
    {
      float emin = m_edgeAttribute[i].second[0];
      float emax = m_edgeAttribute[i].second[0];
      for(int j=1; j<m_edgeAttribute[i].second.count(); j++)
	{
	  emin = qMin((float)m_edgeAttribute[i].second[j], emin);
	  emax = qMax((float)m_edgeAttribute[i].second[j], emax);
	}
      m_Eminmax.append(qMakePair(emin, emax));
      m_userEminmax.append(qMakePair((emin+emax)/2, emax));
    }

  return true;
}
vtkDataArray *
avtS3DFileFormat::GetVar(int timeState, int domain, const char *varname)
{
    debug5 << "avtS3DFileFormat::GetVar( timeState=" << timeState << ", domain="
        << domain << ", varname=" << varname << ")" << endl;

    // Calculate the timestep directory that the data lives in.
    char *pathcopy = strdup(mainFilename);
    string dir = parse_dirname(pathcopy);
    string timestepDir = CreateStringFromDouble(fileTimes[timeState]);
    debug4 << "Timestep directory is <" << timestepDir <<  ">" << endl;
    
    // Figure out how big this piece is.
    CalculateSubpiece(domain);

    // Open up the NetCDF file.
    char path[256];
    SNPRINTF(path,256,"%s%s%s%sfield.%05d",dir.c_str(),VISIT_SLASH_STRING, timestepDir.c_str(), VISIT_SLASH_STRING, domain);
    debug5 << "avtS3DFileFormat::GetVar: Full path to data file is " << path << endl;

    NcFile nf(path);
    if (!nf.is_valid())
    {
        debug1 << nc_strerror(NcError().get_err()) << endl;
        EXCEPTION1(InvalidFilesException, path);
    }
    debug5 << "avtS3DFileFormat::GetVar: Got valid file." << endl;

    // Pull out the appropriate variable.
    NcVar *v = nf.get_var(varname);
    if (!v)
    {
        debug1 << nc_strerror(NcError().get_err()) << endl;
        EXCEPTION1(InvalidVariableException, varname);
    }

    // Check if it fits the size of the mesh.  Always node-centered, remember.
    int ntuples = localDims[0] * localDims[1] * localDims[2];
    debug5 << "ntuples:" << ntuples << endl;
    int nvals = v->num_vals();
    if (ntuples != nvals)
    {
        debug1 << "The variable " << v->name() <<
                  " does not conform to its mesh (" << nvals << " != " << 
                  ntuples << ")" << endl;
        EXCEPTION1(InvalidVariableException, v->name());
    }

    // Set up the VTK dataset.
    vtkFloatArray *rv = vtkFloatArray::New();
    rv->SetNumberOfTuples(ntuples);
    float *p = (float*)rv->GetVoidPointer(0);
    NcValues *input = v->values();
    if (!input)
    {
        debug1 << nc_strerror(NcError().get_err()) << endl;
        EXCEPTION1(InvalidVariableException, v->name());
    }

    // Get the scaling factor.
    NcAtt *scaling = v->get_att(NcToken("scale_factor"));
    float scaling_factor = 1;
    if (scaling)
    {
        scaling_factor = scaling->as_float(0);
        debug5 << "avtS3DFileFormat::GetVar: Set the scaling factor as " << scaling_factor << endl;
    }

    // Process the variable into the returned data.
    float *base = (float*)input->base();
    for(int i=0;i<ntuples;i++)
    {
        p[i] = *(base + i) * scaling_factor;
    }

    return rv;
}
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
}