1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
#include <iostream.h>
#include <string.h>
#include "netcdf.hh"
void gen(const char *path) // Generate a netCDF file
{
NcNewFile nc (path, NcNewFile::Clobber); // Create, leave in define mode
// Check if the file was opened successfully
if (! nc.is_valid()) {
cerr << "can't create netCDF file " << path << "\n";
return;
}
// Create dimensions
const int NLATS = 4;
const int NLONS = 3;
const int NFRTIMES = 2;
const int TIMELEN = 20;
NcDim* latd = nc.add_dim("lat", NLATS);
NcDim* lond = nc.add_dim("lon", NLONS);
NcDim* frtimed = nc.add_dim("frtime"); // unlimited dimension
NcDim* timelend = nc.add_dim("timelen", TIMELEN);
// Create variables and their attributes
NcVar* P = nc.add_var("P", ncFloat, frtimed, latd, lond);
P->add_att("long_name", "pressure at maximum wind");
P->add_att("units", "hectopascals");
static float range[] = {0., 1500.};
P->add_att("valid_range", 2, range);
P->add_att("_FillValue", -9999.0f);
NcVar* lat = nc.add_var("lat", ncFloat, latd);
lat->add_att("long_name", "latitude");
lat->add_att("units", "degrees_north");
NcVar* lon = nc.add_var("lon", ncFloat, lond);
lon->add_att("long_name", "longitude");
lon->add_att("units", "degrees_east");
NcVar* frtime = nc.add_var("frtime", ncLong, frtimed);
frtime->add_att("long_name", "forecast time");
frtime->add_att("units", "hours");
NcVar* reftime = nc.add_var("reftime",ncChar,timelend);
reftime->add_att("long_name", "reference time");
reftime->add_att("units", "text_time");
NcVar* scalar = nc.add_var("scalarv", ncLong);
scalar->add_att("scalar_att", 1);
// Global attributes
nc.add_att("history", "created by Unidata LDM from NPS broadcast");
nc.add_att("title", "NMC Global Product Set: Pressure at Maximum Wind");
// Start writing data, implictly leaves define mode
float lats[NLATS] = {-90, -87.5, -85, -82.5};
lat->put(lats, NLATS);
float lons[NLONS] = {-180, -175, -170};
lon->put(lons, NLONS);
static long frtimes[NFRTIMES] = {12, 18};
frtime->put(frtimes, NFRTIMES);
static char* s = "1992-3-21 12:00" ;
reftime->put(s, strlen(s));
static float P_data[] = {
950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961,
962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973
};
// We could write all P data at once with P->put(P_data, P->edges()),
// but instead we write one record at a time, to show use of setcur().
long rec = 0; // start at zero-th
const long nrecs = 1; // # records to write
P->put(&P_data[0], nrecs, NLATS, NLONS); // write zero-th record
P->set_cur(++rec); // set to next record
P->put(&P_data[NLATS*NLONS], nrecs, NLATS, NLONS); // write next record
// close of nc takes place in destructor
}
/*
* Convert pathname of netcdf file into name for CDL, by taking last component
* of path and stripping off any extension. The returned string is in static
* storage, so copy it if you need to keep it.
*/
static char *
cdl_name(const char *path)
{
static char np[MAX_NC_NAME];
char *cp = strrchr(path, '/'); // assumes Unix pathnames
if (cp)
strncpy(&np[0], ++cp, MAX_NC_NAME);
else
strncpy(&np[0], path, MAX_NC_NAME);
if (cp = strrchr(np, '.'))
*cp = '\0';
return np;
}
// A derived class, just like NcOldFile except knows how to "dump" its
// dimensions, variables, global attributes, and data in ASCII form.
class DumpableNcFile : public NcOldFile
{
public:
DumpableNcFile(const char* path) : NcOldFile(path) {} ;
void dumpdims( void );
void dumpvars( void );
void dumpgatts( void );
void dumpdata( void );
};
void DumpableNcFile::dumpdims( void )
{
for (int n=0; n < num_dims(); n++) {
NcDim* dim = get_dim(n);
cout << "\t" << dim->name() << " = " ;
if (dim->is_unlimited())
cout << "UNLIMITED" << " ;\t " << "// " << dim->size() <<
" currently\n";
else
cout << dim->size() << " ;\n";
}
}
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;
}
}
void DumpableNcFile::dumpvars( void )
{
static char *typename[] =
{"","byte","char","short","long","float","double"};
NcVar *vp;
for(int n = 0; vp = get_var(n); n++) {
cout << "\t" << typename[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);
}
}
void DumpableNcFile::dumpgatts( void )
{
NcAtt *ap;
for(int n = 0; ap = get_att(n); n++) {
cout << "\t\t" << ":" << ap->name() << " = " ;
NcValues *vals = ap->values();
cout << *vals << " ;" << endl ;
delete vals;
delete ap;
}
}
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;
}
}
void dump(const char *path)
{
DumpableNcFile nc(path); // opens in read-only mode
cout << "netcdf " << cdl_name(path) << " {" << endl <<
"dimensions:" << endl ;
nc.dumpdims();
cout << "variables:" << endl;
nc.dumpvars();
if (nc.num_atts() > 0)
cout << "// global attributes" << endl ;
nc.dumpgatts();
cout << "data:" << endl;
nc.dumpdata();
cout << "}" << endl;
}
int
main( void ) // test new netCDF interface
{
const char* path = "example.nc";
gen(path); // create a netCDF file
dump(path); // print what's in it
return 0;
}
|