Commit ff37ccf5 authored by Uwe Schulzweida's avatar Uwe Schulzweida
Browse files

Added support for netCDF CF time attribute: climatology

parent 9e72feb6
2013-09-26 Uwe Schulzweida <Uwe.Schulzweida@zmaw.de>
2013-11-12 Uwe Schulzweida <Uwe.Schulzweida@zmaw.de>
* Version 1.6.2 released
* using CGRIBEX library version 1.6.2
2013-10-22 Uwe Schulzweida <Uwe.Schulzweida@zmaw.de>
* Added support for netCDF CF time attribute: climatology [Feature #4092]
2013-10-17 Uwe Schulzweida <Uwe.Schulzweida@zmaw.de>
* stream_cdf::isLatAxis() and isLonAxis(): added support for stdname latitude and longitude
......
CDI NEWS
--------
Version 1.6.2 (26 September 2013):
Version 1.6.2 (12 November 2013):
New features:
* Added support for netCDF CF time attribute: climatology [Feature #4092]
* made gridtype GRID_REFERENCE part of GRID_UNSTRUCTED
* GRIB2: added support for level type Lake Bottom (grib level type 162)
* GRIB2: added support for level type Bottom Of Sediment Layer (grib level type 163)
......@@ -11,7 +12,7 @@ Version 1.6.2 (26 September 2013):
* GRIB2: added support for level type Bottom Of Sediment Layer Penetrated By Thermal Wave (grib level type 165)
* GRIB2: added support for level type Mixing Layer (grib level type 166)
Fixed bugs:
* netCDF: wrong result if type of data and type of attribute valid_range differ [Bug #3727]
* netCDF: wrong result if type of data and type of attribute valid_range differ [Bug #3727]
Version 1.6.1 (18 June 2013):
......
......@@ -66,6 +66,7 @@ typedef struct {
int param;
int code;
int tabnum;
int climatology;
int bounds;
int gridID;
int zaxisID;
......@@ -849,13 +850,26 @@ void cdfDefTime(stream_t *streamptr)
if ( nc_inq_dimid(fileID, "nb2", &dims[1]) != NC_NOERR )
cdf_def_dim(fileID, "nb2", 2, &dims[1]);
strcpy(tmpstr, taxis_name);
strcat(tmpstr, "_bnds");
cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
if ( taxis->climatology )
{
strcpy(tmpstr, "climatology");
strcat(tmpstr, "_bnds");
cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
streamptr->basetime.ncvarboundsid = time_bndsid;
cdf_put_att_text(fileID, time_varid, "climatology", strlen(tmpstr), tmpstr);
}
else
{
strcpy(tmpstr, taxis_name);
strcat(tmpstr, "_bnds");
cdf_def_var(fileID, tmpstr, NC_DOUBLE, 2, dims, &time_bndsid);
streamptr->basetime.ncvarboundsid = time_bndsid;
streamptr->basetime.ncvarboundsid = time_bndsid;
cdf_put_att_text(fileID, time_varid, "bounds", strlen(tmpstr), tmpstr);
cdf_put_att_text(fileID, time_varid, "bounds", strlen(tmpstr), tmpstr);
}
}
unitstr[0] = 0;
......@@ -897,11 +911,12 @@ void cdfDefTime(stream_t *streamptr)
len = strlen(unitstr);
if ( len )
cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
{
cdf_put_att_text(fileID, time_varid, "units", len, unitstr);
if ( taxis->has_bounds )
if ( len )
cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
if ( taxis->has_bounds )
cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr);
}
if ( taxis->calendar != -1 )
{
......@@ -4229,6 +4244,7 @@ void init_ncvars(long nvars, ncvar_t *ncvars)
ncvars[ncvarid].code = UNDEFID;
ncvars[ncvarid].tabnum = 0;
ncvars[ncvarid].calendar = FALSE;
ncvars[ncvarid].climatology = FALSE;
ncvars[ncvarid].bounds = UNDEFID;
ncvars[ncvarid].gridID = UNDEFID;
ncvars[ncvarid].zaxisID = UNDEFID;
......@@ -4801,6 +4817,24 @@ void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims,
*/
/* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */
}
else if ( strcmp(attname, "climatology") == 0 && atttype == NC_CHAR )
{
int status, ncboundsid;
cdfGetAttText(ncid, ncvarid, attname, attstringlen-1, attstring);
status = nc_inq_varid(ncid, attstring, &ncboundsid);
if ( status == NC_NOERR )
{
ncvars[ncvarid].climatology = TRUE;
ncvars[ncvarid].bounds = ncboundsid;
cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE);
cdfSetVar(ncvars, ncvarid, FALSE);
}
else
Warning("%s - %s", nc_strerror(status), attstring);
}
else if ( strcmp(attname, "bounds") == 0 && atttype == NC_CHAR )
{
int status, ncboundsid;
......@@ -6534,8 +6568,8 @@ void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID,
}
static
void scan_global_attributtes(int fileID, int vlistID, stream_t *streamptr, int ngatts,
int *instID, int *modelID, int *ucla_les, char *uuidOfHGrid, char *gridfile, int *number_of_grid_used)
void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts,
int *instID, int *modelID, int *ucla_les, char *uuidOfHGrid, char *gridfile, int *number_of_grid_used)
{
nc_type xtype;
size_t attlen;
......@@ -6654,8 +6688,9 @@ int cdfInqContents(stream_t *streamptr)
int *varids;
int nvarids;
const int attstringlen = 8192; char attstring[8192];
int timehasunits = FALSE;
int time_has_units = FALSE;
int time_has_bounds = FALSE;
int time_climatology = FALSE;
size_t len;
int nvars_data;
int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID;
......@@ -6746,8 +6781,8 @@ int cdfInqContents(stream_t *streamptr)
return (CDI_EUFSTRUCT);
}
/* scan global attributtes */
scan_global_attributtes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, uuidOfHGrid, gridfile, &number_of_grid_used);
/* scan global attributes */
scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, uuidOfHGrid, gridfile, &number_of_grid_used);
/* find time dim */
if ( unlimdimid >= 0 )
......@@ -6866,7 +6901,7 @@ int cdfInqContents(stream_t *streamptr)
else if ( streamptr->basetime.lwrf == FALSE )
{
if ( ncvars[ncvarid].units[0] != 0 )
timehasunits = TRUE;
time_has_units = TRUE;
if ( ncvars[ncvarid].bounds != UNDEFID )
{
......@@ -6876,8 +6911,10 @@ int cdfInqContents(stream_t *streamptr)
len = ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len;
if ( (int)len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] )
{
time_has_bounds = TRUE;
streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds;
if ( ncvars[ncvarid].climatology ) time_climatology = TRUE;
}
}
}
......@@ -7098,7 +7135,7 @@ int cdfInqContents(stream_t *streamptr)
/* time varID */
ncvarid = streamptr->basetime.ncvarid;
if ( timehasunits )
if ( time_has_units )
{
taxis_t *taxis;
taxis = &streamptr->tsteps[0].taxis;
......@@ -7109,7 +7146,10 @@ int cdfInqContents(stream_t *streamptr)
}
if ( time_has_bounds )
streamptr->tsteps[0].taxis.has_bounds = TRUE;
{
streamptr->tsteps[0].taxis.has_bounds = TRUE;
if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = TRUE;
}
if ( ncvarid != -1 )
{
......@@ -7151,7 +7191,7 @@ int cdfInqContents(stream_t *streamptr)
else
{
taxisID = taxisCreate(TAXIS_ABSOLUTE);
if ( !timehasunits )
if ( !time_has_units )
{
taxisDefTunit(taxisID, TUNIT_DAY);
streamptr->tsteps[0].taxis.unit = TUNIT_DAY;
......
......@@ -110,6 +110,7 @@ void taxisDefaultValue ( taxis_t *taxisptr )
taxisptr->calendar = cdiDefaultCalendar;
taxisptr->unit = DefaultTimeUnit;
taxisptr->numavg = 0;
taxisptr->climatology = FALSE;
taxisptr->has_bounds = FALSE;
taxisptr->vdate_lb = 0;
taxisptr->vtime_lb = 0;
......@@ -653,7 +654,7 @@ int taxisInqVtime(int taxisID)
void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
{
taxis_t *taxisptr;
taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
taxis_check_ptr(__func__, taxisptr);
......@@ -679,7 +680,7 @@ void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub)
taxisptr->vtime_lb = vtime_lb;
taxisptr->vtime_ub = vtime_ub;
taxisptr->has_bounds = TRUE;
}
......@@ -1202,20 +1203,21 @@ void ptaxisCopy(taxis_t *dest, taxis_t *source)
reshLock ();
/* memcpy(dest, source, sizeof(taxis_t)); */
dest->used = source->used;
dest->type = source->type;
dest->vdate = source->vdate;
dest->vtime = source->vtime;
dest->rdate = source->rdate;
dest->rtime = source->rtime;
dest->calendar = source->calendar;
dest->unit = source->unit;
dest->numavg = source->numavg;
dest->has_bounds = source->has_bounds;
dest->vdate_lb = source->vdate_lb;
dest->vtime_lb = source->vtime_lb;
dest->vdate_ub = source->vdate_ub;
dest->vtime_ub = source->vtime_ub;
dest->used = source->used;
dest->type = source->type;
dest->vdate = source->vdate;
dest->vtime = source->vtime;
dest->rdate = source->rdate;
dest->rtime = source->rtime;
dest->calendar = source->calendar;
dest->unit = source->unit;
dest->numavg = source->numavg;
dest->climatology = source->climatology;
dest->has_bounds = source->has_bounds;
dest->vdate_lb = source->vdate_lb;
dest->vtime_lb = source->vtime_lb;
dest->vdate_ub = source->vdate_ub;
dest->vtime_ub = source->vtime_ub;
reshUnlock ();
}
......@@ -1234,21 +1236,22 @@ void taxisPrintKernel ( taxis_t * taxisptr, FILE * fp )
fprintf ( fp, "#\n");
fprintf ( fp, "# taxisID %d\n", taxisptr->self);
fprintf ( fp, "#\n");
fprintf ( fp, "self = %d\n", taxisptr->self );
fprintf ( fp, "used = %d\n", taxisptr->used );
fprintf ( fp, "type = %d\n", taxisptr->type );
fprintf ( fp, "vdate = %d\n", taxisptr->vdate );
fprintf ( fp, "vtime = %d\n", taxisptr->vtime );
fprintf ( fp, "rdate = %d\n", taxisptr->rdate );
fprintf ( fp, "rtime = %d\n", taxisptr->rtime );
fprintf ( fp, "calendar = %d\n", taxisptr->calendar );
fprintf ( fp, "unit = %d\n", taxisptr->unit );
fprintf ( fp, "numavg = %d\n", taxisptr->numavg );
fprintf ( fp, "has_bounds = %d\n", taxisptr->has_bounds );
fprintf ( fp, "vdate_lb = %d\n", vdate_lb );
fprintf ( fp, "vtime_lb = %d\n", vtime_lb );
fprintf ( fp, "vdate_ub = %d\n", vdate_ub );
fprintf ( fp, "vtime_ub = %d\n", vtime_ub );
fprintf ( fp, "self = %d\n", taxisptr->self );
fprintf ( fp, "used = %d\n", taxisptr->used );
fprintf ( fp, "type = %d\n", taxisptr->type );
fprintf ( fp, "vdate = %d\n", taxisptr->vdate );
fprintf ( fp, "vtime = %d\n", taxisptr->vtime );
fprintf ( fp, "rdate = %d\n", taxisptr->rdate );
fprintf ( fp, "rtime = %d\n", taxisptr->rtime );
fprintf ( fp, "calendar = %d\n", taxisptr->calendar );
fprintf ( fp, "unit = %d\n", taxisptr->unit );
fprintf ( fp, "numavg = %d\n", taxisptr->numavg );
fprintf ( fp, "climatology = %d\n", taxisptr->climatology );
fprintf ( fp, "has_bounds = %d\n", taxisptr->has_bounds );
fprintf ( fp, "vdate_lb = %d\n", vdate_lb );
fprintf ( fp, "vtime_lb = %d\n", vtime_lb );
fprintf ( fp, "vdate_ub = %d\n", vdate_ub );
fprintf ( fp, "vtime_ub = %d\n", vtime_ub );
fprintf ( fp, "\n");
}
......@@ -1275,20 +1278,21 @@ int taxisCompareP ( void * taxisptr1, void * taxisptr2 )
xassert ( t1 );
xassert ( t2 );
return ! ( t1->used == t2->used &&
t1->type == t2->type &&
t1->vdate == t2->vdate &&
t1->vtime == t2->vtime &&
t1->rdate == t2->rdate &&
t1->rtime == t2->rtime &&
t1->calendar == t2->calendar &&
t1->unit == t2->unit &&
t1->numavg == t2->numavg &&
t1->has_bounds == t2->has_bounds &&
t1->vdate_lb == t2->vdate_lb &&
t1->vtime_lb == t2->vtime_lb &&
t1->vdate_ub == t2->vdate_ub &&
t1->vtime_ub == t2->vtime_ub );
return ! ( t1->used == t2->used &&
t1->type == t2->type &&
t1->vdate == t2->vdate &&
t1->vtime == t2->vtime &&
t1->rdate == t2->rdate &&
t1->rtime == t2->rtime &&
t1->calendar == t2->calendar &&
t1->unit == t2->unit &&
t1->numavg == t2->numavg &&
t1->climatology == t2->climatology &&
t1->has_bounds == t2->has_bounds &&
t1->vdate_lb == t2->vdate_lb &&
t1->vtime_lb == t2->vtime_lb &&
t1->vdate_ub == t2->vdate_ub &&
t1->vtime_ub == t2->vtime_ub );
}
......@@ -1298,7 +1302,7 @@ taxisTxCode ( void )
return TAXIS;
}
enum { taxisNint = 15 };
enum { taxisNint = 16 };
static int
taxisGetPackSize(void * voidP, void *context)
......@@ -1331,20 +1335,21 @@ taxisUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos,
xassert(namespaceAdaptKey(intBuffer[0], nspTarget) == taxisP->self);
taxisP->used = intBuffer[1];
taxisP->type = intBuffer[2];
taxisP->vdate = intBuffer[3];
taxisP->vtime = intBuffer[4];
taxisP->rdate = intBuffer[5];
taxisP->rtime = intBuffer[6];
taxisP->calendar = intBuffer[7];
taxisP->unit = intBuffer[8];
taxisP->numavg = intBuffer[9];
taxisP->has_bounds = intBuffer[10];
taxisP->vdate_lb = intBuffer[11];
taxisP->vtime_lb = intBuffer[12];
taxisP->vdate_ub = intBuffer[13];
taxisP->vtime_ub = intBuffer[14];
taxisP->used = intBuffer[1];
taxisP->type = intBuffer[2];
taxisP->vdate = intBuffer[3];
taxisP->vtime = intBuffer[4];
taxisP->rdate = intBuffer[5];
taxisP->rtime = intBuffer[6];
taxisP->calendar = intBuffer[7];
taxisP->unit = intBuffer[8];
taxisP->numavg = intBuffer[9];
taxisP->climatology = intBuffer[10];
taxisP->has_bounds = intBuffer[11];
taxisP->vdate_lb = intBuffer[12];
taxisP->vtime_lb = intBuffer[13];
taxisP->vdate_ub = intBuffer[14];
taxisP->vtime_ub = intBuffer[15];
}
......@@ -1366,11 +1371,12 @@ taxisPack(void * voidP, void * packBuffer, int packBufferSize, int * packBufferP
intBuffer[7] = taxisP->calendar;
intBuffer[8] = taxisP->unit;
intBuffer[9] = taxisP->numavg;
intBuffer[10] = taxisP->has_bounds;
intBuffer[11] = taxisP->vdate_lb;
intBuffer[12] = taxisP->vtime_lb;
intBuffer[13] = taxisP->vdate_ub;
intBuffer[14] = taxisP->vtime_ub;
intBuffer[10] = taxisP->climatology;
intBuffer[11] = taxisP->has_bounds;
intBuffer[12] = taxisP->vdate_lb;
intBuffer[13] = taxisP->vtime_lb;
intBuffer[14] = taxisP->vdate_ub;
intBuffer[15] = taxisP->vtime_ub;
serializePack(intBuffer, taxisNint, DATATYPE_INT,
packBuffer, packBufferSize, packBufferPos, context);
......
......@@ -15,6 +15,7 @@ typedef struct {
int calendar;
int unit; /* time unit */
int numavg;
int climatology;
int has_bounds;
int vdate_lb; /* lower bounds of vdate */
int vtime_lb; /* lower bounds of vtime */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment