ncdf4a13/cxx/nctst.cpp

Go to the documentation of this file.
00001 /*********************************************************************
00002  * Copyright 2005, UCAR/Unidata See COPYRIGHT file for copying and
00003  * redistribution conditions.
00004  * 
00005  * This runs the C++ tests for netCDF.
00006  * 
00007  * $Id: nctst.cpp,v 1.9 2006/01/28 20:01:19 ed Exp $
00008  *********************************************************************/
00009 
00010 #include "config.h"
00011 #include <iostream>
00012 using namespace std;
00013 
00014 #include <string.h>
00015 #include "netcdfcpp.h"
00016 
00017 void gen(const char* path, NcFile::FileFormat format)           // Generate a netCDF file
00018 {
00019 
00020     NcFile nc(path, NcFile::Replace, NULL, 0, format); // Create, leave in define mode
00021 
00022     // Check if the file was opened successfully
00023     if (! nc.is_valid()) {
00024         cerr << "can't create netCDF file " << path << "\n";
00025         return;
00026     }
00027 
00028     // Create dimensions
00029     const int NLATS = 4;
00030     const int NLONS = 3;
00031     const int NFRTIMES = 2;
00032     const int TIMESTRINGLEN = 20;
00033     NcDim* latd = nc.add_dim("lat", NLATS);
00034     NcDim* lond = nc.add_dim("lon", NLONS);
00035     NcDim* frtimed = nc.add_dim("frtime"); // unlimited dimension
00036     NcDim* timelend = nc.add_dim("timelen", TIMESTRINGLEN); 
00037 
00038     // Create variables and their attributes
00039     NcVar* P = nc.add_var("P", ncFloat, frtimed, latd, lond);
00040     P->add_att("long_name", "pressure at maximum wind");
00041     P->add_att("units", "hectopascals");
00042     static float range[] = {0., 1500.};
00043     P->add_att("valid_range", 2, range);
00044     P->add_att("_FillValue", -9999.0f);
00045 
00046     NcVar* lat = nc.add_var("lat", ncFloat, latd);
00047     lat->add_att("long_name", "latitude");
00048     lat->add_att("units", "degrees_north");
00049 
00050     NcVar* lon = nc.add_var("lon", ncFloat, lond);
00051     lon->add_att("long_name", "longitude");
00052     lon->add_att("units", "degrees_east");
00053 
00054     NcVar* frtime = nc.add_var("frtime", ncLong, frtimed);
00055     frtime->add_att("long_name", "forecast time");
00056     frtime->add_att("units", "hours");
00057 
00058     NcVar* reftime = nc.add_var("reftime",ncChar,timelend);
00059     reftime->add_att("long_name", "reference time");
00060     reftime->add_att("units", "text_time");
00061 
00062     NcVar* scalar = nc.add_var("scalarv", ncInt);
00063     scalar->add_att("scalar_att", 1);
00064 
00065     // Global attributes
00066     nc.add_att("history", "created by Unidata LDM from NPS broadcast");
00067     nc.add_att("title", "NMC Global Product Set: Pressure at Maximum Wind");
00068 
00069     // Start writing data, implictly leaves define mode
00070 
00071     static float lats[NLATS] = {-90, -87.5, -85, -82.5};
00072     lat->put(lats, NLATS);
00073 
00074     static float lons[NLONS] = {-180, -175, -170};
00075     lon->put(lons, NLONS);
00076 
00077     static int frtimes[NFRTIMES] = {12, 18};
00078     frtime->put(frtimes, NFRTIMES);
00079 
00080     static const char* s = "1992-3-21 12:00" ;
00081     reftime->put(s, strlen(s));
00082 
00083     static float P_data[2][4][3] = {
00084         {{950, 951, 952}, {953, 954, 955}, {956, 957, 958}, {959, 960, 961}},
00085         {{962, 963, 964}, {965, 966, 967}, {968, 969, 970}, {971, 972, 973}}
00086       };
00087     // We could write all P data at once with P->put(&P_data[0][0][0], P->edges()),
00088     // but instead we write one record at a time, to show use of setcur().
00089     long rec = 0;                                      // start at zero-th
00090     const long nrecs = 1;                              // # records to write
00091     P->put(&P_data[0][0][0], nrecs, NLATS, NLONS);           // write zero-th record
00092     P->set_cur(++rec);                                 // set to next record
00093     P->put(&P_data[1][0][0], nrecs, NLATS, NLONS); // write next record
00094 
00095     // close of nc takes place in destructor
00096 }
00097 
00098 
00099 /*
00100  * Convert pathname of netcdf file into name for CDL, by taking last component
00101  * of path and stripping off any extension.  The returned string is in static
00102  * storage, so copy it if you need to keep it.
00103  */
00104 static char* 
00105 cdl_name(const char* path)
00106 {
00107     const char* cp = path + strlen(path);
00108     while (*(cp-1) != '/' && cp != path) // assumes UNIX path separator
00109         cp--;
00110 
00111     static char np[MAX_NC_NAME];
00112     strncpy(&np[0], cp, MAX_NC_NAME);
00113 
00114     char* ep = np + strlen(np);
00115     while (*ep != '.' && ep != np)
00116         ep--;
00117     if (*ep == '.')
00118       *ep = '\0';
00119     return np;
00120 }
00121 
00122 // A derived class, just like NcFile except knows how to "dump" its
00123 // dimensions, variables, global attributes, and data in ASCII form.
00124 class DumpableNcFile : public NcFile
00125 {
00126   public:
00127     DumpableNcFile(const char* path, NcFile::FileMode mode = ReadOnly)
00128         : NcFile(path, mode) {} ;
00129     void dumpdims( void );
00130     void dumpvars( void );
00131     void dumpgatts( void );
00132     void dumpdata( void );
00133 };
00134 
00135 void DumpableNcFile::dumpdims( void )
00136 {
00137 
00138     for (int n=0; n < num_dims(); n++) {
00139         NcDim* dim = get_dim(n);
00140         cout << "\t" << dim->name() << " = " ;
00141         if (dim->is_unlimited())
00142           cout << "UNLIMITED" << " ;\t " << "// " << dim->size() <<
00143             " currently\n";
00144         else
00145           cout << dim->size() << " ;\n";
00146     }
00147 }
00148 
00149 void dumpatts(NcVar& var)
00150 {
00151     NcToken vname = var.name();
00152     NcAtt* ap;
00153     for(int n = 0; ap = var.get_att(n); n++) {
00154         cout << "\t\t" << vname << ":" << ap->name() << " = " ;
00155         NcValues* vals = ap->values();
00156         cout << *vals << " ;" << endl ;
00157         delete ap;
00158         delete vals;
00159     }
00160 }
00161 
00162 void DumpableNcFile::dumpvars( void )
00163 {
00164     int n;
00165     static const char* types[] =
00166       {"","byte","char","short","long","float","double"};
00167     NcVar* vp;
00168 
00169     for(n = 0; vp = get_var(n); n++) {
00170         cout << "\t" << types[vp->type()] << " " << vp->name() ;
00171 
00172         if (vp->num_dims() > 0) {
00173             cout << "(";
00174             for (int d = 0; d < vp->num_dims(); d++) {
00175                 NcDim* dim = vp->get_dim(d);
00176                 cout << dim->name();
00177                 if (d < vp->num_dims()-1)
00178                   cout << ", ";           
00179             }
00180             cout << ")";
00181         }
00182         cout << " ;\n";
00183         // now dump each of this variable's attributes
00184         dumpatts(*vp);
00185     }
00186 }
00187 
00188 void DumpableNcFile::dumpgatts( void )
00189 {
00190     NcAtt* ap;
00191     for(int n = 0; ap = get_att(n); n++) {
00192         cout << "\t\t" << ":" << ap->name() << " = " ;
00193         NcValues* vals = ap->values();
00194         cout << *vals << " ;" << endl ;
00195         delete vals;
00196         delete ap;
00197     }
00198 }
00199 
00200 void DumpableNcFile::dumpdata( )
00201 {
00202     NcVar* vp;
00203     for (int n = 0; vp = get_var(n); n++) {
00204         cout << " " << vp->name() << " = ";
00205         NcValues* vals = vp->values();
00206         cout << *vals << " ;" << endl ;
00207         delete vals;
00208     }
00209 }
00210 
00211 void dump(const char* path)
00212 {
00213     DumpableNcFile nc(path);    // default is open in read-only mode
00214 
00215     cout << "netcdf " << cdl_name(path) << " {" << endl <<
00216             "dimensions:" << endl ;
00217 
00218     nc.dumpdims();
00219 
00220     cout << "variables:" << endl;
00221 
00222     nc.dumpvars();
00223 
00224     if (nc.num_atts() > 0)
00225       cout << "// global attributes" << endl ;
00226 
00227     nc.dumpgatts();
00228 
00229     cout << "data:" << endl;
00230 
00231     nc.dumpdata();
00232 
00233     cout << "}" << endl;
00234 }
00235 
00236 
00237 int
00238 main( void )    // test new netCDF interface
00239 {
00240     cout << "Creating netCDF classic file with C++ API...";
00241     gen("nctst_classic.nc", NcFile::Classic);           // create a netCDF file
00242     cout << "ok\n";
00243 
00244     cout << "Creating netCDF 64-bit offset file with C++ API...";
00245     gen("nctst_64bit_offset.nc", NcFile::Offset64Bits); // create a netCDF file
00246     cout << "ok\n";
00247 
00248 #ifdef USE_NETCDF4
00249 // Uncomment the following line to get lots of feedback from the library.
00250 //    nc_set_log_level(5);
00251 
00252 //     cout << "Creating netCDF4 file with C++ API...";
00253 //     gen("nctst_netcdf4.nc", NcFile::Netcdf4);        // create a netCDF file
00254 //     cout << "ok\n";
00255 //     nc_set_log_level(0);
00256 
00257 //     cout << "Creating netCDF4 classic file with C++ API...";
00258 //     gen("nctst_netcdf4_classic.nc", NcFile::Netcdf4Classic); // create a netCDF file
00259 //     cout << "ok\n";
00260 #endif
00261 
00262     return 0;
00263 }

Generated on Thu Mar 16 18:10:07 2006 for nco by  doxygen 1.4.4