[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Help with ncgen and _FillValue attribute



> Organization: NOAA/FSL
> Keywords: 199410201923.AA18899 version ncgen fill values

Hi Linda,

> I have two questions.  First is, how can you determine which
> version of netcdf is installed on a machine?  I think it is 
> version 2.3.2, but I am not sure.

If the source directory from which netCDF was built and installed is still
available, you can look at the file named VERSION in the top-level netcdf
source directory, which should contain a single line with the version
number, "2.3.2" for the current version.  It's also in the second line of
the README file in the same directory.

If you only have an installed version, on a UNIX system you can run the
command

    strings `which ncgen` | grep Header

and if the date in the resulting version control line is later than April
1993, you are running version 2.3 or later.  Version 2.3.2 was released in
June 1993, so if your executables were built more recently than that, there
is a good chance they are version 2.3.2.  There have been a couple of
official patches releases since 2.3.2, mostly to correct bugs found in
ncdump and ncgen.  These have resulted in the current 2.3.2pl2 patch-level
release.

> Second is,  when I run the following cdl file through ncgen:
> 
> netcdf lw3 {
> 
>     dimensions:
>         record = unlimited,
>         z = 22,
>       x = 61,
>       y = 61;
>               
>     variables:
>         //    u wind component
> 
>       float                                  
>             u(record,z,y,x);
>             u:_FillValue= 1.e+37;
>                               
>         //    inventory variables
> 
>         short
>             u_fcinv(record, z);
>             u_fcinv:_FillValue= 0;
>                       
> }
> 
> *********************************************
> I get the following output:
> 
> 
> #include "netcdf.h"
> 
> int
> main() {                      /* create lw3 */
> 
>    int  ncid;                 /* netCDF id */
> 
>    /* dimension ids */
>    int  record_dim, z_dim, x_dim, y_dim;
> 
>    /* variable ids */
>    int  u_id, u_fcinv_id;
> 
>    /* variable shapes */
>    int dims[4];
> 
>    /* containers for scalar attributes */
>    long  long_val;
>    double  double_val;
> 
>    /* enter define mode */
>    ncid = nccreate("lw3", NC_CLOBBER);
> 
>    /* define dimensions */
>    record_dim = ncdimdef(ncid, "record", NC_UNLIMITED);
>    z_dim = ncdimdef(ncid, "z", 22L);
>    x_dim = ncdimdef(ncid, "x", 61L);
>    y_dim = ncdimdef(ncid, "y", 61L);
> 
>    /* define variables */
> 
>    dims[0] = record_dim;
>    dims[1] = z_dim;
>    dims[2] = y_dim;
>    dims[3] = x_dim;
>    u_id = ncvardef (ncid, "u", NC_FLOAT, 4, dims);
> 
>    dims[0] = record_dim;
>    dims[1] = z_dim;
>    u_fcinv_id = ncvardef (ncid, "u_fcinv", NC_SHORT, 2, dims);
> 
>    /* assign attributes */
>    double_val = 1e+37;
>    ncattput (ncid, u_id, "_FillValue", NC_DOUBLE, 1,(void *) &double_val);
>    long_val = 0;
>    ncattput (ncid, u_fcinv_id, "_FillValue", NC_LONG, 1,(void *) &long_val);
> 
>    /* leave define mode */
>    ncendef (ncid);
>    ncclose (ncid);
>    return 0;
> }

I get the same, so this indicates you are using the current version.

> *****************************************
> The problem I am having is with the _FillValue attributes.
> Variable u is declared as float, with a fillValue of 1.e+37.
> IEEE specs for a float on a 32 bit machine allow 8 bits for
> the exponent, which is more than capable of storing the 
> number 37.  Ncgen sets up the _FillValue attribute as a
> double, and tries to assign a double_val to the float variable.  

It uses a double, because the type of an attribute specified in a CDL file
is implied by the way its value is specified, not from the type of variable
the attribute is attached to.  If you want the _FillValue to be of type
float (which it should be for a floating-point variable), you must append
"f" to the value, just as you would in C to specify a float rather than a
double for a floating-point constant:

        u:_FillValue= 1.e+37f;

> When ncendef is executed, there is a "FillValue mis-match" 
> error returned.  Similarly, variable u_fcinv is declared as a 
> short, and ncgen sets up code to fill _FillValue with a long.

Similarly to specify a short integer constant, you need to append "s" to the
constant, as in:

        u_fcinv:_FillValue= 0s;

> Any ideas on what's going on, and how to fix it?  I use the
> command ncgen -g "cdlfile" > "outfile" to generate the 
  [I assume you meant you use the "-c" flag]
> c code now, but will be running ncgen through a system call
> to generate c code on the fly.  Thus I won't be able to
> adjust the output code, as I have been.

I think if you make the above changes to your CDL file, things will work OK.

The documentation for the syntax for CDL constants is in the netCDF User's
Guide under the section "CDL Notation for Data Constants".

If you're using a system() call, are you sure you don't want to just
generate the netCDF file specified by the CDL file directly, by using "ncgen
-b cdlfile > netcdffile" instead of producing C code and compiling it?  The
latter takes a *lot* longer, and won't work for files that have so much data
that the generated C chokes the C compiler.

--
Russ Rew                                                UCAR Unidata Program
address@hidden                                          P.O. Box 3000
http://www.unidata.ucar.edu/                          Boulder, CO 80307-3000