mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-21 03:13:42 +08:00
Finish handling bounds variables with ncdump -t (NCF-70). Fix bug with permitted dimension sizes in netCDF classic files (NCF-117).
This commit is contained in:
parent
616aadc321
commit
b658836a6e
@ -120,11 +120,10 @@ NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
|
||||
if ((retval = nc4_check_name(name, norm_name)))
|
||||
return retval;
|
||||
|
||||
/* For classic model, stick with the classic format restriction:
|
||||
* dim length has to fit in a 32-bit signed int. For 64-bit offset,
|
||||
* it has to fit in a 32-bit unsigned int. */
|
||||
/* For classic model: dim length has to fit in a 32-bit unsigned
|
||||
* int, as permitted for 64-bit offset format. */
|
||||
if (h5->cmode & NC_CLASSIC_MODEL)
|
||||
if((unsigned long) len > X_INT_MAX) /* Backward compat */
|
||||
if(len > X_UINT_MAX) /* Backward compat */
|
||||
return NC_EDIMSIZE;
|
||||
|
||||
/* Make sure the name is not already in use. */
|
||||
|
@ -630,16 +630,90 @@ calendar_type(int ncid, int varid) {
|
||||
return ctype;
|
||||
}
|
||||
|
||||
/* Return true only if this is a "bounds" attribute */
|
||||
static boolean
|
||||
is_bounds_att(ncatt_t *attp) {
|
||||
if(attp->type == NC_CHAR && attp->valgp && STREQ((char *)attp->name, "bounds")) {
|
||||
return true;
|
||||
}
|
||||
#ifdef USE_NETCDF4
|
||||
if(attp->type == NC_STRING && attp->valgp && STREQ((char *)attp->name, "bounds")) {
|
||||
return true;
|
||||
}
|
||||
#endif /* USE_NETCDF4 */
|
||||
return false;
|
||||
}
|
||||
|
||||
struct bounds_node{
|
||||
int ncid; /* group (or file) in which variable with associated
|
||||
* bounds variable resides */
|
||||
int varid; /* has "bounds" attribute naming its bounds variable */
|
||||
char *bounds_name; /* the named variable, which stores bounds for varid */
|
||||
struct bounds_node *next; /* next node on list or NULL ifn last list node */
|
||||
};
|
||||
|
||||
typedef struct bounds_node bounds_node_t;
|
||||
|
||||
static struct {
|
||||
size_t nbnds; /* number of bounds variables */
|
||||
bounds_node_t *first;
|
||||
} bounds_list;
|
||||
|
||||
void
|
||||
bounds_add(char *bounds_name, int ncid, int varid) {
|
||||
bounds_node_t *bnode = emalloc(sizeof(bounds_node_t) + 1);
|
||||
bounds_list.nbnds++;
|
||||
bnode->ncid = ncid;
|
||||
bnode->varid = varid;
|
||||
bnode->bounds_name = strdup(bounds_name);
|
||||
bnode->next = bounds_list.first;
|
||||
bounds_list.first = bnode;
|
||||
}
|
||||
|
||||
/* Insert info about a bounds attribute into bounds list, so we can
|
||||
* later determine which variables are bounds variables for which
|
||||
* other variables. att must be a variable "bounds" attribute. */
|
||||
void
|
||||
insert_bounds_info(int ncid, int varid, ncatt_t att) {
|
||||
static boolean uninitialized = true;
|
||||
if(uninitialized) {
|
||||
bounds_list.nbnds = 0;
|
||||
bounds_list.first = NULL;
|
||||
}
|
||||
assert(is_bounds_att(&att));
|
||||
bounds_add(att.valgp, ncid, varid);
|
||||
}
|
||||
|
||||
static boolean
|
||||
is_bounds_var(char *varname, int *pargrpidp, int *parvaridp) {
|
||||
bounds_node_t *bp = bounds_list.first;
|
||||
for(; bp; bp = bp->next) {
|
||||
if(STREQ(bp->bounds_name, varname)) {
|
||||
*pargrpidp = bp->ncid;
|
||||
*parvaridp = bp->varid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
get_timeinfo(int ncid, int varid, ncvar_t *vp) {
|
||||
get_timeinfo(int ncid1, int varid1, ncvar_t *vp) {
|
||||
ncatt_t uatt; /* units attribute */
|
||||
int nc_status; /* return from netcdf calls */
|
||||
char *units;
|
||||
|
||||
int ncid = ncid1;
|
||||
int varid = varid1;
|
||||
|
||||
vp->has_timeval = false; /* by default, turn on if criteria met */
|
||||
vp->timeinfo = 0;
|
||||
|
||||
/* time variables must have appropriate units attribute */
|
||||
vp->is_bounds_var = false;
|
||||
/* for timeinfo, treat a bounds variable like its "parent" time variable */
|
||||
if(is_bounds_var(vp->name, &ncid, &varid)) {
|
||||
vp->is_bounds_var = true;
|
||||
}
|
||||
|
||||
/* time variables must have appropriate units attribute or be a bounds variable */
|
||||
nc_status = nc_inq_att(ncid, varid, "units", &uatt.type, &uatt.len);
|
||||
if(nc_status == NC_NOERR && uatt.type == NC_CHAR) { /* TODO: NC_STRING? */
|
||||
units = emalloc(uatt.len + 1);
|
||||
@ -838,6 +912,9 @@ pr_att(
|
||||
* Prints nothing if not qualified for time interpretation.
|
||||
* Will include line breaks for longer lists. */
|
||||
print_att_times(ncid, varid, att);
|
||||
if(is_bounds_att(&att)) {
|
||||
insert_bounds_info(ncid, varid, att);
|
||||
}
|
||||
}
|
||||
#ifdef USE_NETCDF4
|
||||
/* If NC_STRING, need to free all the strings also */
|
||||
|
@ -80,6 +80,7 @@ typedef struct ncvar_t { /* variable */
|
||||
void* fillvalp; /* pointer to the fill value, if any */
|
||||
boolean has_timeval; /* has date-time values, for -t output option */
|
||||
struct timeinfo_t *timeinfo; /* if time values, units, calendar, and origin */
|
||||
boolean is_bounds_var; /* cell bounds variable, inherits timeinfo */
|
||||
const char *fmt; /* overriding variable-specific format for
|
||||
printing values or base values, if any */
|
||||
int locid; /* group id */
|
||||
|
@ -1,6 +1,8 @@
|
||||
netcdf tst_times {
|
||||
dimensions:
|
||||
time = 1 ;
|
||||
bnds = 2 ;
|
||||
t3 = UNLIMITED ; // (3 currently)
|
||||
variables:
|
||||
double t1_days(time) ;
|
||||
t1_days:units = "days since 1500-1-1" ;
|
||||
@ -63,6 +65,23 @@ variables:
|
||||
double t2_jl_days(time) ;
|
||||
t2_jl_days:calendar = "julian" ;
|
||||
t2_jl_days:units = "days since 2000-06-15 12:00:00" ;
|
||||
int t3(t3) ;
|
||||
t3:units = "days since 1804-1-1" ;
|
||||
t3:calendar = "gregorian" ;
|
||||
t3:bounds = "t3_bnds" ;
|
||||
t3:time1 = 1 ; // "1804-01-02"
|
||||
t3:time2 = 5, 6 ; // "1804-01-06", "1804-01-07"
|
||||
t3:time3 = 7.125f, 8.75f ; // "1804-01-08 03", "1804-01-09 18"
|
||||
t3:time4 = 58.5, 59.5, 60.5 ;
|
||||
// "1804-02-28 12", "1804-02-29 12", "1804-03-01 12"
|
||||
t3:time5 = 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 ;
|
||||
// "1804-04-10", "1804-04-11", "1804-04-12", "1804-04-13",
|
||||
// "1804-04-14", "1804-04-15", "1804-04-16", "1804-04-17",
|
||||
// "1804-04-18", "1804-04-19", "1804-04-20", "1804-04-21",
|
||||
// "1804-04-22", "1804-04-23", "1804-04-24", "1804-04-25",
|
||||
// "1804-04-26", "1804-04-27", "1804-04-28", "1804-04-29",
|
||||
// "1804-04-30"
|
||||
double t3_bnds(t3, bnds) ;
|
||||
data:
|
||||
|
||||
t1_days = "2009-01-01" ;
|
||||
@ -106,4 +125,11 @@ data:
|
||||
t2_360_days = "2009-01-01" ;
|
||||
|
||||
t2_jl_days = "2009-01-01" ;
|
||||
|
||||
t3 = "1804-01-11", "1804-01-12", "1804-01-13" ;
|
||||
|
||||
t3_bnds =
|
||||
"1804-01-10 12", "1804-01-11 12",
|
||||
"1804-01-11 12", "1804-01-12 12",
|
||||
"1804-01-12 12", "1804-01-13 12" ;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
netcdf tst_calendars { // test climate calendars and CDL time with -t option
|
||||
dimensions:
|
||||
time = 1;
|
||||
bnds = 2 ; // for cell bounds on t3 time coordinate variable
|
||||
t3 = unlimited ;
|
||||
variables:
|
||||
double t1_days(time);
|
||||
t1_days:units = "days since 1500-1-1";
|
||||
@ -72,6 +74,18 @@ variables:
|
||||
// t2_none_days:calendar = "none" ;
|
||||
// t2_none_days:units = "days since 2000-06-15 12:00:00";
|
||||
|
||||
// test -t option on numeric attributes of a time-valued variable
|
||||
int t3(t3) ;
|
||||
t3:units = "days since 1804-1-1" ;
|
||||
t3:calendar = "gregorian" ;
|
||||
t3:bounds = "t3_bnds" ;
|
||||
t3:time1 = 1 ;
|
||||
t3:time2 = 5, 6 ;
|
||||
t3:time3 = 7.125f, 8.75f ;
|
||||
t3:time4 = 58.5, 59.5, 60.5 ;
|
||||
t3:time5 = 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120 ;
|
||||
double t3_bnds(t3, bnds) ; // no attributes, since a cell bounds variable
|
||||
|
||||
data:
|
||||
// Should all represent 2009-01-01 00:00:00
|
||||
t1_days = 185900;
|
||||
@ -100,5 +114,8 @@ data:
|
||||
// Not sure what these should represent yet ...
|
||||
// t1_none_days = 185900;
|
||||
// t2_none_days = 3121.5;
|
||||
|
||||
t3 = 10, 11, 12;
|
||||
t3_bnds = 9.5, 10.5, 10.5, 11.5, 11.5, 12.5 ;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ echo ""
|
||||
echo "*** Testing ncdump -t output for times with CF calendar attribute"
|
||||
echo "*** creating netcdf file tst_calendars.nc from tst_calendars.cdl..."
|
||||
../ncgen/ncgen -b -o tst_calendars.nc $srcdir/tst_calendars.cdl
|
||||
echo "*** creating tst_isotimes.cdl from tst_calendars.nc..."
|
||||
echo "*** creating tst_times.cdl from tst_calendars.nc with ncdump -t ..."
|
||||
./ncdump -n tst_times -t tst_calendars.nc > tst_times.cdl
|
||||
echo "*** comparing tst_times.cdl with ref_times.cdl..."
|
||||
diff tst_times.cdl $srcdir/ref_times.cdl
|
||||
|
Loading…
Reference in New Issue
Block a user