int TestSuite::testExamples() { #define FILE_NAME "pres_temp_4D.nc" // We are writing 4D data, a 2 x 6 x 12 lvl-lat-lon grid, with 2 // timesteps of data. #define NDIMS 4 #define NLVL 2 #define NLAT 6 #define NLON 12 #define NREC 2 // Names of things. #define LVL_NAME "level" #define LAT_NAME "latitude" #define LON_NAME "longitude" #define REC_NAME "time" #define PRES_NAME "pressure" #define TEMP_NAME "temperature" #define MAX_ATT_LEN 80 // These are used to construct some example data. #define SAMPLE_PRESSURE 900 #define SAMPLE_TEMP 9.0 #define START_LAT 25.0 #define START_LON -125.0 string UNITS = "units"; string DEGREES_EAST = "degrees_east"; string DEGREES_NORTH = "degrees_north"; // For the units attributes. string PRES_UNITS = "hPa"; string TEMP_UNITS = "celsius"; string LAT_UNITS = "degrees_north"; string LON_UNITS = "degrees_east"; // Return this code to the OS in case of failure. #define NC_ERR 2 // We will write latitude and longitude fields. float lats[NLAT],lons[NLON]; // Program variables to hold the data we will write out. We will // only need enough space to hold one timestep of data; one record. float pres_out[NLVL][NLAT][NLON]; float temp_out[NLVL][NLAT][NLON]; int i=0; //used in the data generation loop // create some pretend data. If this wasn't an example program, we // would have some real data to write for example, model output. for (int lat = 0; lat < NLAT; lat++) lats[lat] = START_LAT + 5. * lat; for (int lon = 0; lon < NLON; lon++) lons[lon] = START_LON + 5. * lon; for (int lvl = 0; lvl < NLVL; lvl++) for (int lat = 0; lat < NLAT; lat++) for (int lon = 0; lon < NLON; lon++) { pres_out[lvl][lat][lon] = SAMPLE_PRESSURE + i; temp_out[lvl][lat][lon] = SAMPLE_TEMP + i++; } try { // Create the file. NcFile test(FILE_NAME, NcFile::Replace); // Define the dimensions. NetCDF will hand back an ncDim object for // each. NcDim* lvlDim = test.addDim(LVL_NAME, NLVL); NcDim* latDim = test.addDim(LAT_NAME, NLAT); NcDim* lonDim = test.addDim(LON_NAME, NLON); NcDim* recDim = test.addDim(REC_NAME); //adds an unlimited dimension // Define the coordinate variables. NcVar* latVar = test.addVar(LAT_NAME, ncFloat, latDim); NcVar* lonVar = test.addVar(LON_NAME, ncFloat, lonDim); // Define units attributes for coordinate vars. This attaches a // text attribute to each of the coordinate variables, containing // the units. latVar->addAtt(UNITS,ncChar, DEGREES_NORTH); lonVar->addAtt(UNITS,ncChar, DEGREES_EAST); // Define the netCDF variables for the pressure and temperature // data. NcVar* pressVar = test.addVar(PRES_NAME, ncFloat, recDim, lvlDim, latDim, lonDim); NcVar* tempVar = test.addVar(TEMP_NAME, ncFloat, recDim, lvlDim, latDim, lonDim); // Define units attributes for coordinate vars. This attaches a // text attribute to each of the coordinate variables, containing // the units. pressVar->addAtt(UNITS,ncChar, PRES_UNITS); tempVar->addAtt(UNITS,ncChar ,TEMP_UNITS); // Write the coordinate variable data to the file. latVar->put(lats, NLAT); lonVar->put(lons, NLON); // Write the pretend data. This will write our surface pressure and // surface temperature data. The arrays only hold one timestep // worth of data. We will just rewrite the same data for each // timestep. In a real application, the data would change between // timesteps. for (int rec = 0; rec < NREC; rec++) { pressVar->putRec(&pres_out[0][0][0], rec); tempVar->putRec(&temp_out[0][0][0], rec); } //NcValues * pressVals = pressVar->getValues(); //pressVals->print(cout); // The file is automatically closed by the destructor. This frees // up any internal netCDF resources associated with the file, and // flushes any buffers. cout << "*** SUCCESS writing example file " << FILE_NAME << "!" << endl; } catch(NcException e) { e.what(); return 1; } return 0; }
int TestSuite::testFile(string fName, NcFile::FileMode fMode) { string UNITS = "UNITS:"; cout<<"*** Testing tst_file in tst_suite "; int NLAT = 6; int NLON = 12; int NDIMS = 4; int NLVL = 2; int NREC = 2; /* These are used to construct some example data. */ int SAMPLE_PRESSURE = 900; float SAMPLE_TEMP = 9.0; float START_LAT = 25.0; float START_LON = -125.0; /* We will write surface temperature and pressure fields. */ float pres_out[NLAT][NLON]; float pres_in[NLAT][NLON]; float temp_out[NLAT][NLON]; float temp_in[NLAT][NLON]; float lats[NLAT], lons[NLON],lats_in[NLAT],lons_in[NLON]; std::string chararray []={"I"," hope"," this"," is"," stored "," properly" }; std::string chararray_in[NLAT]; int outInts[NLAT],outInts_in[NLAT]; /* It's good practice for each netCDF variable to carry a "units" * attribute. */ char pres_units[] = "hPa"; char temp_units[] = "celsius"; /* Loop indexes. */ int lat, lon; /* Create some pretend data. If this wasn't an example program, we * would have some real data to write, for example, model * output. */ for (lat = 0; lat < NLAT; lat++) { lats[lat] = START_LAT + 5.*lat; } for(lat = 0; lat < NLAT; lat++) { outInts[lat]= 450; } for (lon = 0; lon < NLON; lon++) { lons[lon] = START_LON + 5.*lon; } for (lat = 0; lat < NLAT; lat++) { for (lon = 0; lon < NLON; lon++) { pres_out[lat][lon] = SAMPLE_PRESSURE + (lon * NLAT + lat); temp_out[lat][lon] = SAMPLE_TEMP + .25 * (lon * NLAT + lat); } } // nc_set_log_level(3); try { NcFile f("tst_file.nc",NcFile::Replace); NcGroup *root = f.getRootGroup(); NcDim *latDim = root->addDim(string("lat"),NLAT); NcDim *lonDim = root->addDim(string("lon"),NLON); NcVar *latVar = root->addVar(string("latVar"),ncDouble,latDim); NcVar *lonVar = root->addVar(string("lonVar"),ncFloat,lonDim); NcVar *outIntsVar = root->addVar(string("outintsVar"),ncInt,latDim); NcVar *charArrVar = root->addVar(string("CharArray"),ncString,latDim); latVar->addAtt(string(UNITS),ncChar,string("degrees_north")); lonVar->addAtt(string(UNITS),ncChar,string("degrees_south")); outIntsVar->put(&outInts[0],NLAT,0,0,0,0); charArrVar->put(&chararray[0],NLAT,0,0,0,0); latVar->put(&lats[0],NLAT,0,0,0,0); lonVar->put(&lons[0],NLON,0,0,0,0); NcVar *presVar = root->addVar(string("press"),ncFloat,latDim,lonDim); NcVar *tempVar = root->addVar(string("temp"),ncFloat,latDim,lonDim); presVar->addAtt(string("UNITS:"),ncChar,string(pres_units)); tempVar->addAtt(string("UNITS:"),ncChar,string(temp_units)); presVar->put(&pres_out[0][0],NLAT,NLON,0,0,0); tempVar->put(&temp_out[0][0],NLAT,NLON,0,0,0); //NcValues *ncvalues = presVar->getValues(); { //another scope for variables NcGroup::varIterator variableItr; variableItr = root->beginVar(); while(variableItr != root->endVar()) { variableItr++; } NcVar::attIterator varAttItr; varAttItr = latVar->beginAtt(); while(varAttItr != latVar->endAtt()) { varAttItr++; } } } catch(NcException e) { cout<<"FAILURE***"<<endl; e.what(); return 1; } try { NcFile f1("tst_file.nc",NcFile::ReadOnly); NcGroup * root =f1.getRootGroup(); NcGroup::dimIterator dimItr; //get an iterator to move over the dimensions dimItr = root->beginDim(); //created in the file while(dimItr != root->endDim()) dimItr++; NcGroup::attIterator attItr; attItr= root->beginAtt(); while(attItr !=root->endAtt()) attItr++; NcGroup::varIterator variableItr; NcVar::attIterator varAttItr; variableItr = root->beginVar(); while(variableItr != root->endVar()) { varAttItr = variableItr->beginAtt(); while(varAttItr != variableItr->endAtt()) varAttItr++; variableItr++; } } catch(NcException e) { cout<<"FAILURE***"<<endl; e.what(); return 1; } cout<<" OK***"<<endl; return 0; }
int TestSuite::testVar() { try { string FILE_NAME = "tst_vars.nc"; int NDIMS = 4; int NLAT = 6; int NLON = 12; // Names of things. string LAT_NAME = "latitude"; string LON_NAME = "longitude"; int MAX_ATT_LEN = 80; // These are used to construct some example data. float START_LAT = 25.0; float START_LON = -125.0; string UNITS = "units"; string DEGREES_EAST = "degrees_east"; string DEGREES_NORTH = "degrees_north"; // For the units attributes. string LAT_UNITS = "degrees_north"; string LON_UNITS = "degrees_east"; // Return this code to the OS in case of failure. #define NC_ERR 2 // We will write latitude and longitude fields. float lats[NLAT],lons[NLON]; // create some pretend data. If this wasn't an example program, we // would have some real data to write for example, model output. for (int lat = 0; lat < NLAT; lat++) lats[lat] = START_LAT + 5. * lat; for (int lon = 0; lon < NLON; lon++) lons[lon] = START_LON + 5. * lon; // Create the file. NcFile test(FILE_NAME, NcFile::Replace); // Define the dimensions. NetCDF will hand back an ncDim object for // each. NcDim* latDim = test.addDim(LAT_NAME, NLAT); NcDim* lonDim = test.addDim(LON_NAME, NLON); // Define the coordinate variables. NcVar* latVar = test.addVar(LAT_NAME, ncFloat, latDim); NcVar* lonVar = test.addVar(LON_NAME, ncFloat, lonDim); // Define units attributes for coordinate vars. This attaches a // text attribute to each of the coordinate variables, containing // the units. latVar->addAtt(UNITS,ncString, DEGREES_NORTH); lonVar->addAtt(UNITS,ncString, DEGREES_EAST); // Write the coordinate variable data to the file. latVar->put(lats, NLAT); lonVar->put(lons, NLON); NcValues *latVals = latVar->getValues(); cout<<"toString returns lats: "<<latVals->toString()<<endl; cout<<"toChar returns "<<latVals->toChar(1)<<endl; cout<<"toShort returns "<<latVals->toShort(1)<<endl; cout<<"toInt returns "<<latVals->toInt(1)<<endl; cout<<"toLong returns "<<latVals->toLong(1)<<endl; latVals->print(cout); NcValues *lonVals = lonVar->getValues(); cout<<"toString returns lats: "<<lonVals->toString()<<endl; lonVals->print(cout); cout<<"no segmentation fault thus far"<<endl; //test varaibles here } catch(NcException e) { e.what(); return 1; } try { cout<<"should test adding a variable with more than 5 dimensions here"<<endl; // test creating a variable with more than 5 dimensions } catch (NcException e) { e.what(); return 1; } try //write the file with float's b/c that's all NcValues can handle at the moment { int NX = 6; int NY = 12; float dataOut[NX][NY]; // Create some pretend data. If this wasn't an example program, we // would have some real data to write, for example, model output. for(int i = 0; i < NX; i++) for(int j = 0; j < NY; j++) dataOut[i][j] = i * NY + j; // The default behavior of the C++ API is to throw an exception i // an error occurs. A try catch block in necessary. // Create the file. The Replace parameter tells netCDF to overwrite // this file, if it already exists. string filename ="simples_xy.nc"; NcFile dataFile(filename, NcFile::Replace); // When we create netCDF dimensions, we get back a pointer to an // NcDim for each one. NcDim* xDim = dataFile.addDim("x", NX); NcDim* yDim = dataFile.addDim("y", NY); // Define the variable. The type of the variable in this case is // ncInt (32-bit integer). NcVar *data = dataFile.addVar("data", ncFloat, xDim, yDim); // Write the pretend data to the file. Although netCDF supports // reading and writing subsets of data, in this case we write all // the data in one operation. data->put(&dataOut[0][0], NX, NY,0,0,0); // The file will be automatically close when the NcFile object goes // out of scope. This frees up any internal netCDF resources // associated with the file, and flushes any buffers. cout << "*** SUCCESS writing example file simples_xy.nc!" << endl; } catch(std::exception e) {e.what();} try { int NX = 6; int NY = 12; // Return this in event of a problem. // int NC_ERR = 2; // This is the array we will read. float dataIn[NX][NY]; // Open the file. The ReadOnly parameter tells netCDF we want // read-only access to the file. NcFile dataFile("simples_xy.nc", NcFile::ReadOnly); // Retrieve the variable named "data" NcVar *data = dataFile.getVar("data"); //call getType on data // Read all the values from the "data" variable into memory. data->get(&dataIn[0][0], NX, NY); // Check the values. for (int i = 0; i < NX; i++) for (int j = 0; j < NY; j++) if (dataIn[i][j] != i * NY + j) return 1; NcValues* dataVar= data->getValues(); cout<<dataVar->toString()<<endl;; dataVar->print(cout); } catch(NcException e) { e.what(); return 1; } cout<<"***************** Testing Variables was successful *****************"<<endl; return 0; }
int main(void) { // We will write surface temperature and pressure fields. float presOut[NLAT][NLON]; float tempOut[NLAT][NLON]; float lats[NLAT]; float lons[NLON]; // In addition to the latitude and longitude dimensions, we will // also create latitude and longitude netCDF variables which will // hold the actual latitudes and longitudes. Since they hold data // about the coordinate system, the netCDF term for these is: // "coordinate variables." for(int lat = 0;lat < NLAT; lat++) lats[lat] = START_LAT + 5.*lat; for(int lon = 0; lon < NLON; lon++) lons[lon] = START_LON + 5.*lon; // Create some pretend data. If this wasn't an example program, we // would have some real data to write, for example, model // output. for (int lat = 0; lat < NLAT; lat++) for(int lon = 0;lon < NLON; lon++) { presOut[lat][lon] = SAMPLE_PRESSURE + (lon * NLAT + lat); tempOut[lat][lon] = SAMPLE_TEMP + .25 * (lon * NLAT +lat); } try { // Create the file. The Replace parameter tells netCDF to overwrite // this file, if it already exists. NcFile sfc(FILE_NAME, NcFile::Replace); // Define the dimensions. NetCDF will hand back an ncDim object for // each. NcDim* latDim = sfc.addDim(LAT_NAME, NLAT); NcDim* lonDim = sfc.addDim(LON_NAME, NLON); // Define coordinate netCDF variables. They will hold the // coordinate information, that is, the latitudes and // longitudes. An pointer to a NcVar object is returned for // each. NcVar *latVar = sfc.addVar(LAT_NAME, ncFloat, latDim);//creates variable NcVar *lonVar = sfc.addVar(LON_NAME, ncFloat, lonDim); // Write the coordinate variable data. This will put the latitudes // and longitudes of our data grid into the netCDF file. latVar->put(&lats[0], NLAT, 0, 0, 0, 0); lonVar->put(&lons[0], NLON, 0, 0, 0, 0); // Define units attributes for coordinate vars. This attaches a // text attribute to each of the coordinate variables, containing // the units. Note that we are not writing a trailing NULL, just // "units", because the reading program may be fortran which does // not use null-terminated strings. In general it is up to the // reading C program to ensure that it puts null-terminators on // strings where necessary. lonVar->addAtt(UNITS,ncChar, DEGREES_EAST); latVar->addAtt(UNITS,ncChar ,DEGREES_NORTH); // Define the netCDF data variables. NcVar *presVar = sfc.addVar(PRES_NAME, ncFloat, latDim, lonDim); NcVar *tempVar = sfc.addVar(TEMP_NAME, ncFloat, latDim, lonDim); // Define units attributes for vars. presVar->addAtt(UNITS,ncString, string("hPa")); tempVar->addAtt(UNITS,ncString ,string("celsius")); // Write the pretend data. This will write our surface pressure and // surface temperature data. The arrays of data are the same size // as the netCDF variables we have defined. presVar->put(&presOut[0][0], NLAT, NLON, 0, 0, 0); tempVar->put(&tempOut[0][0], NLAT, NLON, 0, 0, 0); // The file is automatically closed by the destructor. This frees // up any internal netCDF resources associated with the file, and // flushes any buffers. cout << "*** SUCCESS writing example file " << FILE_NAME << "!" << endl; } catch(NcException e) { e.what(); } return 0; }