Chapter 10: CONVERTING TO NetCDF

Ch10 Sec1. OVERVIEW

The Network Common Data Format (NetCDF) is an interface to a library of data access routines for storing and retrieving scientific data. NetCDF allows the creation of data sets that are self-describing and network-transparent. NetCDF was created under contract with the Division of Atmospheric Sciences of the National Scientific Foundation and is available from the Unidata Program Center in Boulder, Colorado (on Internet: unidata.ucar.edu).

This chapter provides directions for creating NetCDF data files. In addition to the documentation provided here, refer to the NetCDF User's Guide, published by Unidata Program Center, for further guidance. A user who uses and creates NetCDF files within the Ferret environment needs no additional software.

NetCDF is a very flexible standard. In most cases there are multiple styles or profiles that could be used to encode data into NetCDF. To resolve the ambiguities inherent in this multiplicity communities of users have banded together to develop profiles—documents that provide more detail on how data should be encoded into NetCDF. Ferret adheres to the COARDS standard. The full standard is available through the Ferret home page on the World Wide Web,

http://www.ferret.noaa.gov/noaa_coop/coop_cdf_profile.html


Ch10 Sec2. SIMPLE CONVERSIONS USING FERRET

In straightforward conversion operations where ASCII or unformatted binary data files are already readable by Ferret, the conversion to direct access, self-describing NetCDF formatted data can be accomplished by Ferret itself. The following set of examples illustrates these procedures:

Example 1

Consider an ASCII file uv.data, with two variables, u and v, defined on a grid 360 by 180. The following set of commands will properly read in u and v and convert them to a NetCDF formatted data set:

yes? DEFINE AXIS/x=1:360:1/units=degrees xaxis
yes? DEFINE AXIS/y=1:180:1/units=degrees yaxis
yes? DEFINE GRID/x=xaxis/y=yaxis uv_grid
yes? FILE/GRID=uv_grid/BAD=-999/VAR="u,v"  uv.data
yes? SET VARIABLE/TITLE="zonal velocity" u
yes? SAVE/FILE=uv.cdf u,v

See command DEFINE AXIS in the Commands Reference (p. 288). See the chapter "Grids and Regions" (p. 117) for setting up formatted latitude, longitude and time axes.

Example 2

Consider now two separate ASCII files, u.data and v.data, defined on a grid 360 by 180. The following set of commands will properly read in u and v and convert them to a single NetCDF formatted data set:

yes? DEF AXIS/x=1:360:1/units=degrees xaxis
yes? DEF AXIS/y=1:180:1/units=degrees yaxis
yes? DEF GRID/x=xaxis/y=yaxis uv_grid
yes? FILE/GRID=uv_grid/BAD=-999/VAR=u u.data
yes? FILE/GRID=uv_grid/BAD=-999/VAR=v v.data
yes? SAVE/FILE=uv2.cdf u[D=1]
yes? SAVE/APPEND/FILE=uv2.cdf v[D=2]

Example 3—multiple time steps

Consider 12 ASCII files, uv.data1 to uv.data12, each defined on the same grid as above but each representing a successive time step. The following set of commands illustrates how to save these data into a single NetCDF data set (time series):

yes? DEF AXIS/x=1:360:1 xaxis
yes? DEF AXIS/y=1:180:1 yaxis
yes? DEF AXIS/t=1:1:1 taxis1
yes? DEF GRID/x=xaxis/y=yaxis/t=taxis1 uv_grid1
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v" uv.data1
yes? SAVE/FILE=uv1_12t.cdf u,v
yes? CANCEL DATA uv.data1
yes? DEF AXIS/t=2:2:1 taxis1
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v" uv.data2
yes? SAVE/APPEND/FILE=uv1_12t.cdf u,v
. . .

and so on, redefining the time axis to be 3:3:1, 4:4:1, ... each time a new file is set.

Example 4—multiple slabs

The procedure used in example 3, above, is possible because NetCDF files can be extended along the time axis. In order to append multiple levels (Z axis), the NetCDF file must first be created including all of its vertical levels (the levels initially are filled with a missing data flag).

Consider 5 ASCII files, uv.data1 to uv.data5, each defined on the same grid as above but each representing a successive vertical level. The following set of commands illustrates how to save these data into a single NetCDF data set:

yes? DEF AXIS/x=1:360:1  xaxis
yes? DEF AXIS/y=1:180:1  yaxis
yes? DEF AXIS/Z=0:100:25/DEPTH  zaxis
yes? DEF GRID/X=xaxis/Y=yaxis/Z=zaxis uv_grid
yes? DEF AXIS/Z=0:0:1  zaxis1
yes? DEF GRID/LIKE=uv_grid/Z=zaxis1  uv_grid1

yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v"  uv.data1
yes? LET/TITLE="My U data"  u1 = u[G=uv_grid]
yes? LET/TITLE="My V data"  v1 = v[G=uv_grid]
yes? SAVE/FILE=uv1_5z.cdf/
KLIMITS=1:5/K=1  u1, v1

yes? CANCEL DATA uv.data1
yes? DEF AXIS/Z=25:25:1  zaxis1
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v"  uv.data2
yes? SAVE/FILE=uv1_5z.cdf/K=2/APPEND  u1,v1
. . .

yes? CANCEL DATA/ALL  ! Cancel definitions before using new file

yes? CANCEL VAR/ALL

yes? USE uv1_5z.cdf

The NetCDF utilities  "ncdump" and "ncgen" can also be combined with a text editor to make final refinements to the NetCDF files created by SAVE. (These utilities are not provided with the Ferret distribution; they can be obtained from unidata.ucar.edu.)  Here is a simple example that removes all "history" attributes from a NetCDF file using pipes and the Unix "grep" utility:

% ncdump old_file.cdf | grep -v history | ncgen -o new_file.cdf



Ch10 Sec3. WRITING A CONVERSION PROGRAM

There are three steps required to convert data to NetCDF if your data is not already readable by Ferret:

1.    Create a CDL (the ASCII NetCDF Description Language) file that describes the axes, grids, and variables of the desired output data set. Note: Ferret itself often provides the simplest way to create the CDL file (see the following section).

2.    Convert this CDL file into a NetCDF file with the ncgen utility.

3.    Create a program that will read your particular data and insert them into the NetCDF file.  The ncgen utility will create most of the FORTRAN or C code needed for this task.

The file converting_to_netcdf.f which is located in the Ferret documentation directory ($FER_DIR/doc) contains a complete description and example of these three steps. The remainder of this section provides further details.


Ch10 Sec3.1. Creating a CDL file with Ferret

Suppose that we wish to create a CDL file to describe a data set entitled "My Global Data" which contains variables u and v in cm/sec on a 5×5 degree global lat/long grid. The following commands would achieve the goal with Ferret doing the majority of the work:

•  From Ferret issue the commands

DEFINE AXIS/X=2.5E:2.5W:5/UNITS=degrees xlong
DEFINE AXIS/Y=87.5S:87.5N:5/UNITS=degrees ylat
DEFINE GRID/X=xlong/Y=ylat my_grid
LET shape_2d =  x[G=my_grid]+y[G=my_grid]
LET U = 1/0*SHAPE_2D
LET V = 1/0*SHAPE_2D
SET VARIABLE/TITLE="Zonal Velocity"/UNITS="cm/sec" u
SET VARIABLE/TITLE="Meridional Velocity"/UNITS="cm/sec" v
SAVE/FILE=my_file.cdf/TITLE="My Global Data" u,v
QUIT

•  From Unix issue the command

ncdump -c my_file.cdf > my_file.cdl

The resulting file my_file.cdl is ready to use or to make final modifications to with an editor.


Ch10 Sec3.2. The CDL file

A CDL file consists of three sections: Dimensions, Variables, and Data. All of the following text in small Courier  font constitutes a real CDL file; it can be copied verbatim and used to generate a NetCDF file. The full text of this file is included with the Ferret distribution as $FER_DIR/doc/converting_to_netcdf.basic.

netcdf converting_to_netcdf.basic {



Ch10 Sec3.2.1. Dimensions

In this section, the sizes of the grid dimensions are specified. One of these dimensions can be of "unlimited" size (i.e., it can grow).

Dimensions:

    lon   = 160 ;      //  longitude
    lat   = 100 ;      //  latitude
    depth = 27 ;       //  depth
    time  = unlimited ;

These are essentially parameter statements that assign certain numbers that will be used in the Variables section to define axes and variable dimensions. The "//" is the CDL comment syntax.

The dimension variables are available to you in Ferret commands as pseudo-variables.  For example, to use the "depth" dimension variable from the above example, you can say:

yes? let valz = z[gz=depth]
yes? let offset = valz + a

See the next section (p. 230 ) about axes for more on dimension variables.


Ch10 Sec3.2.2. Variables

Variables, variable attributes, axes, axis attributes, and global attributes are specified.

variables:

    float temp(time, depth, lat, lon) ;
          temp: long_name = "TEMPERATURE" ;
          temp: units     = "deg. C" ;
          temp: _FillValue = 1E34 ;
    float salt(time, depth, lat, lon) ;
          salt: long_name = "(SALINITY(ppt) - 35) /1000" ;
          salt: units     = "frac. by wt. less .035" ;
          salt: _FillValue = -999. ;

The declaration "float" indicates that the variable is to be stored as single precision, floating point (32-bit IEEE representation). The declarations "long" (32-bit integer), "short" (16-bit integer), "byte" (8-bit integer) and "double" (64-bit IEEE floating point) are also supported by Ferret. Note that although these data types may result in smaller files, they will not affect Ferret's memory usage, as all variables are converted to "float" internally as they are read by Ferret.

Variable names in NetCDF files should follow the same guidelines as Ferret variable names. .:

See p. 54 for how to handle invalid variable names that are already in a NetCDF file.

The _FillValue attribute informs Ferret that any data value matching this value is a missing (invalid) data point. For example, an ocean data set may label land locations with a value such as 1E34. By identifying 1E34 as a fill value, Ferret knows to ignore points matching this  value.  The attribute "missing_value" is similar to "_FillValue" when reading data; but "_FillValue" also specifies a value to be inserted into unspecified regions during file creation. You may specify two distinct flags for invalid data in the same variable by using "_FillValue" and "missing_value" together.

Ferret variables may have from 1 to 4 dimensions. If any of the axes have the special interpretations of: 1) latitude, 2) longitude, 3) depth, or 4) time (date), then the relative order of those axes in the CDL variable declaration must be T, then Z, then Y, and then X, as above. Any of these special axes can be omitted and other axes (for example, an axis called "distance") may be inserted between them.

axis definitions:

    double lon(lon) ;
           lon: units = "degrees";
    double lat(lat) ;
           lat: units = "degrees";
    double depth(depth) ;
           depth: units = "meters";
    double time(time) ;
           time: units = "seconds since 1972-01-01";

Axes are distinguished from other 1-dimensional NetCDF variables by their variable names being identical to their dimension names. Special axis interpretations are inferred by Ferret through a variety of "clues."

Date/time axes are inferred by units of "years," "days," "hours," "minutes," or "seconds," or by axis names "time," "date," or "t" (case-insensitive). Calendar date formatting requires the "units" attribute to be formatted with both a valid time unit and "since yyyy-mm-dd".

Vertical axes are identified by axis names containing the strings "depth", "elev", or "z", or by units of "millibars." Depth axes are positive downward by default. The attribute positive= "down" can also be used to create a downward-pointing axis.

Latitude axes are inferred by units of "degrees" or "latitude" with axis names containing the strings "lat" or "y". Longitude axes are inferred by units of "degrees" or "longitude" with axis names containing the strings "lon" or "x".

Axes are either netCDF coordinate variables or are synthesized (as simple indices 1, 2, 3, ...) if coordinate definitions are missing for a variable.  The axes of a variable are available as "pseudo-variables" using the syntax X[g=var], where "var" is the name of the netCDF variable, and similarly for the Y,Z, and T axes. When the data set is cancelled the associated axes are cancelled, too. The exception is that axes will be retained if they are in use in a DEFINE GRID definition -- and they will be erased from memory at the time all grids using them are cancelled.

Some files contain axis definitions (coordinate variables) without associated variables. Like all axes they are visible with the SHOW AXIS command.  To obtain the values of those coordinate variables as Ferret pseudo-variables use the syntax  X[gx=axname], where axname is the name of the coordinate variable (also the netCDF dimension name) and likewise for Y,Z, and T axes.  Note that when the data set is cancelled, axis definitions of this variety are retained -- unlike axes that are used in variables.

Global attributes, or attributes that apply to the entire data set, can be specified as well.

global attributes:
    :title = "NetCDF Example";
    :message =   "This message will be displayed when the CDF file is
                  opened by Ferret";
    :history =   "Documentation on the origins and evolution of this data
                  set or variable";



Ch10 Sec3.2.3. Data

In this section, values are assigned to grid coordinates and to the variables of the file. Below are 100 latitude coordinates entered (in degrees) into the variable axis "lat", 160 longitude coordinates in "lon", and 27 depth coordinates (in meters) in "depth". Longitude coordinates must be specified with 0 at Greenwich, continuous across the dateline, with positive eastward (modulo 360).

Data:

lat=
-28.8360729218,-26.5299491882,-24.2880744934,-22.1501560211,-20.151357650,
-18.3207626343,-16.6801033020,-15.2428140640,-14.0134353638,-12.987424850,
-12.1513509750,-11.4834814072,-10.9547319412,-10.5299386978,-10.169393539,
-9.8333206177,-9.4999876022,-9.1666536331,-8.8333196640,-8.4999856949,
-8.1666526794,-7.8333187103,-7.4999847412,-7.1666512489,-6.8333182335,
-6.4999852180,-6.1666517258,-5.8333182335,-5.4999852180,-5.1666517258,
-4.8333187103,-4.4999852180,-4.1666517258,-3.8333187103,-3.4999852180,
-3.1666517258,-2.8333184719,-2.4999852180,-2.1666519642,-1.8333185911,
-1.4999852180,-1.1666518450,-0.8333183527,-0.4999849498,-0.1666515470,
0.1666818559,0.5000152588,0.8333486915,1.1666821241,1.5000154972,
1.8333489895,2.1666824818,2.5000159740,2.8333494663,3.1666829586,
3.5000162125,3.8333497047,4.1666831970,4.5000162125,4.8333497047,
5.1666831970,5.5000162125,5.8333497047,6.1666827202,6.5000162125,
6.8333497047,7.1666827202,7.5000166893,7.8333501816,8.1666841507,
8.5000181198,8.8333511353,9.1666851044,9.5000190735,9.8333530426,
10.1679363251,10.5137376785,10.8892869949,11.3138961792,11.8060989380,
12.3833675385,13.0618314743,13.8560228348,14.7786512375,15.8403968811,
17.0497493744,18.4128704071,19.9334945679,21.6128730774,23.4497566223,
25.4404067993,27.5786647797,29.8560409546,32.2618522644,34.7833900452,
37.4061241150,40.1139259338,42.8893203735,45.7137718201,48.5679702759;
lon=
130.5,131.5,132.5,133.5,134.5,135.5,136.5,137.5,138.5,139.5,140.5,141.5,142.5,143.5,144.5,145.5,146.5,147.5,148.5,149.5,150.5,151.5,152.5,153.5,154.5,155.5,156.5,157.5,158.5,159.5,160.5,161.5,162.5,163.5,164.5,165.5,166.5,167.5,168.5,169.5,170.5,171.5,172.5,173.5,174.5,175.5,176.5,177.5,178.5,179.5,180.5,181.5,182.5,183.5,184.5,185.5,186.5,187.5,188.5,189.5,190.5,191.5,192.5,193.5,194.5,195.5,196.5,197.5,198.5,199.5,200.5,201.5,202.5,203.5,204.5,205.5,206.5,207.5,208.5,209.5,210.5,211.5,212.5,213.5,214.5,215.5,216.5,217.5,218.5,219.5,220.5,221.5,222.5,223.5,224.5,225.5,226.5,227.5,228.5,229.5,230.5,231.5,232.5,233.5,234.5,235.5,236.5,237.5,238.5,239.5,240.5,241.5,242.5,243.5,244.5,245.5,246.5,247.5,248.5,249.5,250.5,251.5,252.5,253.5,254.5,255.5,256.5,257.5,258.5,259.5,260.5,261.5,262.5,263.5,264.5,265.5,266.5,267.5,268.5,269.5,270.5,271.5,272.5,273.5,274.5,275.5,276.5,277.5,278.5,279.5,280.5,281.5,282.5,283.5,284.5,285.5,286.5,287.5,288.5,289.5;
depth=
5.0,15.0,25.0,35.0,45.0,55.0,65.0,75.0,85.0,95.0,106.25,120.0,136.25,155.0,177.5,205.0,240.0,288.5,362.5,483.5,680.0,979.5,1395.5,1916.0,2524.0,3174.0,3824.0;  }

To use this CDL file type:

% ncgen -o my_data.cdf converting_to_netcdf.basic

This will create a file called "my_data.cdf" to which data can be directed (see next section).

Another NetCDF command, "ncdump", can be used to generate a CDL file from an existing NetCDF file. The command

% ncdump -h my_data.cdf

will list the CDL representation of a preexisting my_data.cdf without the Data section, while

% ncdump my_data.cdf

will list the CDL file with the Data section. The command

% ncdump -c my_data.cdf

will create a CDL file in which only coordinate variables are included in the Data section. The listed output can be redirected to a file as in the command

% ncdump -c my_data.cdf > my_data.cdl



Ch10 Sec3.3. Standardized NetCDF attributes

A document detailing the COARDS NetCDF conventions to which the Ferret program adheres are available on line through the Ferret home page on the World Wide Web, at
    http://www.ferret.noaa.gov/noaa_coop/ coop_cdf_profile.html and at

    http://www.unidata.ucar.edu/packages/netcdf/conventions.html

The following are the attributes most commonly used with Ferret. They are described in greater detail in the reference document named above.

Global Attributes
:title = "my data set title"
:history = "general background information"

Data Variable Attributes
long_name = "title of my variable"
units = "units for this variable"
_FillValue = missing value flag
missing_value = alternative missing value flag
scale_factor = (optional) the data are to be multiplied by this factor
add_offset = (optional) this number is to be added to the data

Special Coordinate Variable Attributes
time_axis:units = "seconds since 1992-10-8 15:15:42.5 -6:00"; // example
y_axis:units = "degrees_north"
x_axis:units = "degrees_east"
z_axis:positive = "down"; // to indicate preferred plotting orientation
my_axis:point_spacing = "even"; // improved performance if present

Note that when using Ferret to output into NetCDF files that Ferret did not itself create, the results may not be entirely as expected. Case-sensitivity of names is one aspect of this.  Since Ferret is (by default) case insensitive and netCDF files  are case-sensitive writing into a "foreign" file may result in  duplicated entities in the file which differ only in case.


Ch10 Sec3.4. Directing data to a CDF file

The following is an example program which can be used on-line to convert existing data sets into NetCDF files. It also should provide guidance on sending data generated by numerical models directly to NetCDF files. This program assumes you have created the NetCDF file as described in the previous section. It is included in the distribution as $FER_DIR/doc/converting_to_netcdf.f.

    program converting_to_netcdf

c written by Dan Trueman
c updated 4/94 *sh*
     
c This program provides a model for converting a data set to NetCDF.
c The basic strategy used in this program is to open an existing NetCDF
c file, query the file for the ID's of the variables it contains, and
c then write the data to those variables.
     
c The output NetCDF file must be created **before** this program is run.
c The simplest way to do this is to cd to your scratch directory and
c    % cp $FER_DIR/doc/converting_to_netcdf.basic converting_to_netcdf.cdl
c and then edit converting_to_netcdf.cdl (an ASCII file) to describe YOUR
c data set. If your data set requires unequally spaced axes, climatological c time axes, staggered grids, etc. then converting_to_netcdf.supplement may c be a better starting point then the "basic" file used above.
c After you edit converting_to_netcdf.cdl then create the NetCDF file with
c the command
c    % ncgen -o converting_to_netcdf.cdf converting_to_netcdf.cdl
     
c Now we will read in **your** data (gridded oceanic temperature and
c salt in this example) and write it out into the NetCDF file
c converting_to_netcdf.cdf.  Note that the axis coordinates can be written
c out exactly the same methodology - including time step values (as below).
*************************************************************************
c An alternative to modifying this program is to use the command:
     
c     ncgen -f converting_to_netcdf.cdl
     
c This will create a large source code to which select lines can
c be added to write out your data.
*************************************************************************
c To compile and link converting_to_netcdf.f, use:
     
c     f77 -o converting_to_netcdf converting_to_netcdf.f -lnetcdf
     
*************************************************************************
c include file necessary for NetCDF
     
    include 'netcdf.inc'    ! may be found in $FER_DIR/fmt/cmn
*************************************************************************
c parameters relevant to the data being read in
c THESE NORMALLY MATCH THE DIMENSIONS IN THE CDL FILE
c (except nt which may be "unlimited")
     
    integer imt, jmt, km, nt, lnew, inlun
    parameter (imt=160, jmt=100, km=27, nt=5)
     
c imt is longitude, jmt latitude, km depth, and nt number of time steps
*************************************************************************
c variable declaration
     
    real temp(imt,jmt,km),salt(imt,jmt,km),time_step
     
    integer cdfid, rcode
c           ** cdfid = id number for the NetCDF file my_data.cdf
c     ** rcode = error id number
     
    integer tid, sid, timeaxid
c           ** tid = variable id number for temperature
c           ** sid = variable id number for salt
c           ** timeaxid = variable id for the time axis
    integer itime
c           ** itime = index for do loop
*************************************************************************
c dimension corner and step for defining size of gridded data
     
    integer corner(4)
    integer step(4)
     
c corner and step are used to define the size of the gridded data
c to be written out.  Since temp and salt are four dimensional arrays,
c corner and step must be four dimensions as well.  In each output
c to my_data.cdf within the do loop, the entire array of data (160 long.
c pts, 100 lat. pts., 27 depth pts.) will be written for one time step.
c Corner tells NetCDF where to start, and step indicates how many steps
c in each dimension to take.
     
          data corner/1, 1, 1, -1/      ! -1 is arbitrary; the time value
                                                                           ! of corner will be initialized
                                        ! within the do loop.
     
          data step/imt, jmt, km, 1/    ! NOT /1, km, jmt, imt/
     
c ***NOTE*** Since Fortran and C access data differently, the order of
c the variables in the Fortran code must be opposite that in the CDL
c file.  In Fortran, the first index varies fastest while in C, the
c last index varies fastest.
**************************************************************************
c initialize cdfid by using ncopn

    cdfid = ncopn('converting_to_netcdf.cdf', ncwrite, rcode)
    if (rcode.ne.ncnoerr) stop 'error with ncopn'

**************************************************************************
c get variable id's by using ncvid
c THE VARIABLE NAMES MUST MATCH THE CDL FILE (case sensitive)
     
    tid = ncvid(cdfid, 'temp', rcode)
    if (rcode.ne.ncnoerr) stop 'error with tid'
    sid = ncvid(cdfid, 'salt', rcode)
    if (rcode.ne.ncnoerr) stop 'error with sid'
    timeaxid = ncvid(cdfid, 'time', rcode)
    if (rcode.ne.ncnoerr) stop 'error with timeaxid'      
**************************************************************************
c this is a good place to open your input data file
    ! OPEN (FILE=my_data.dat,STATUS='OLD')
**************************************************************************
c begin do loop.  Each step will read in one time step of data
c and then write it out to my_data.cdf.


    do 10 itime = 1, nt

    corner(4) = itime             ! initialize time step in corner
    time_step = float(itime)      ! or you may read this from your file

* insert your data reading routine here
!     CALL READ_MY_DATA(temp,salt)  ! you write this

    write (6,*) 'writing time step: ',itime, time_step  ! diagnostic output

    call ncvpt(cdfid,tid,corner,step,temp(1,1,1),rcode) ! write data to
    if (rcode.ne.ncnoerr) stop 'error with t-put'
    call ncvpt(cdfid,sid,corner,step,salt(1,1,1),rcode) ! my_data.cdf with
    if (rcode.ne.ncnoerr) stop 'error with s-put'
    call ncvpt1(cdfid,timeaxid,itime,time_step,rcode)   ! ncvpt
    if (rcode.ne.ncnoerr) stop 'error with timax-put'

c ncvpt1 writes a single data point to the specified location within
c timeaxid. The itime argument in ncvpt1 specifies the location within
c time to write.
c float(itime) is used (rather than simply itime) so the type matches the
c type of time declared in the CDL file.

10    continue
**************************************************************************
c close my_data.cdf using ncclos
    call ncclos(cdfid, rcode)
    if (rcode.ne.ncnoerr) stop 'error with ncclos'
**************************************************************************
    stop
    end



Ch10 Sec3.5. Advanced NetCDF procedures

This section describes:

1.    Setting up a CDL file capable of handling data on staggered grids.

2.    Defining coordinate systems such that the data in the NetCDF file may be regarded as hyperslabs of larger coordinate spaces.

3.    Defining boundaries between unevenly spaced axis coordinates (used in numerical  integrations).

4.    Setting up "modulo" axes such as climatological time and longitude.

5.    Converting dates into numerical data appropriate for a NetCDF time axis.

The final section of this chapter contains the text of the CDL file for the example we use throughout this section.

In this sample data set, we will consider wind, salt, and velocity calculated using a staggered-grid, finite-difference technique. The wind data is limited to the surface layer of the ocean (i.e., normal to the depth axis). We will also consider the salt data to be limited to a narrow slab from 139E to 90W (I=10 to 140), 32.5N to 34.9N (J=80 to 82), and for all depth and time values.


Ch10 Sec3.5.1. Staggered grid

Ferret permits each variable of a NetCDF file to be defined on distinct axes and grids. Staggered grids are a straightforward application of this principle. Dimensions for each grid axis must be defined, the axes themselves must be defined (in Variables), and the coordinate values for each axis must be initialized (in Data). In the case of the example we use throughout this and the next section, there are two grids—a wind grid, and a velocity grid; slon, slat and sdepth are defined for the wind grid, and ulon, ulat, and wdepth for the velocity grid. The variables are then given dimensions to place them in their proper grids (i.e., wind(time, sdepth, slat, slon)).


Ch10 Sec3.5.2. Hyperslabs

There are a number of steps required to set up a NetCDF data set that represents a hyperslab of data from a larger grid definition (a parent grid).

1.    Define a dimension named "grid_definition." This dimension should be set equal to 1.

2.    Define parent grids in Variables with the argument "grid_definition".

char wind_grid(grid_definition) ;
char salt_grid(grid_definition) ;

3.    Define the 4 axes of the parent grids using the "axes" attribute.

wind_grid: axes = "slon slat normal time" ;
salt_grid: axes = "slon slat sdepth time" ;

The arguments are always a list of four axis names. Note that the order of arguments is opposite that in the variable declaration. The argument  "normal" indicates that wind_grid is normal to the depth axis.

4.    Define the variables that are hyperslabs of these grids with the proper dimensions.

float wind(time, slat, slon) ;  
float salt(time, sdepth, slat80_82, slon10_140) ;

where the dimension slat80_82 = 3 and slon10_140 = 131. Optionally, these axes may  be defined themselves with  the attribute "child_axis".

float slat80_82(slat80_82) ;
slat80_82: child_axis = " " ;

These "child axes" need not be initialized in data, nor do edges need to be defined for them;  Ferret will retrieve this information from the parent axis definitions. However, it is recommended that they be initialized to accommodate other software that may not recognize parent grids.

 5.    Use the "parent_grid" variable attribute to point to the parent grid.

wind: parent_grid = "wind_grid"
salt: parent_grid = "salt_grid"

6.    Also, as a variable attribute, define the index range of interest within the parent grid.

wind: slab_min_index = 1s, 1s, 1s, 0s ;
wind: slab_max_index = 160s, 100s, 1s, 0s ;
salt: slab_min_index = 10s, 80s, 1s, 0s ;
salt: slab_max_index = 140s, 82s, 27s, 0s ;

The "s" after each integer indicates a "short" 16-bit integer rather than the default "long"  32-bit integer. If an axis dimension is designated as "unlimited" then the index bounds for this axis must be designated as "0s".

These attributes will effectively locate the wind and salt data within the parent grid.


Ch10 Sec3.5.3. Unevenly spaced coordinates

For coordinate axes with uneven spacing, the boundaries between each coordinate can be indicated by pointing to an additional axis that contains the locations of the boundaries. The dimension of this "edge" axis is necessarily one larger than the coordinate axis concerned. If edges are not explicitly defined for an unevenly spaced axis, the midpoint between coordinates is assumed by default.

1.    Define a dimension one larger than the coordinate axis. For the sdepth axis, with 27 coordinates, define:


    sdepth_edges = 28 ;


2.    Define an axis called sdepth_edges.

3.    Initialize this axis with the desired boundaries (in Data).

4.    As an attribute of the main axis, point to edges list:


    sdepth: edges = "sdepth_edges" ;



Ch10 Sec3.5.4. Evenly spaced coordinates (long axes)

If the coordinate axes are evenly spaced, the attribute "point spacing" should be used:

slat: point_spacing = "even" ;

When used, this attribute will improve memory use efficiency in Ferret. This is especially important for very large axes—10,000 points or more.


Ch10 Sec3.5.5. "Modulo" axes

The "modulo" axis attribute indicates that the axis wraps around, the first point immediately following the last. The most common uses of modulo axes are:

1. longitude axes for globe-encircling data

2. time axes for climatological data


time: modulo = " " ;  // any arbitrary string is allowed

If the climatological data occurs in the years 0000 or 0001 then the year will be omitted from Ferret's output format.

NetCDF time axes encoded as year 0000 or 0001 are automatically flagged as modulo axes.


Ch10 Sec3.5.6. Reversed-coordinate axes

NetCDF axes may contain monotonically decreasing axis coordinates instead of monotonically increasing coordinates. Ferret will hide this aspect of the file data ordering.


Ch10 Sec3.5.7. Converting time word data to numerical data

To set up a time axis for data represented as dates (e.g., "1972 January 15 at 12:15") it is necessary to determine a numerical representation for each of the dates. Ferret can assist with this process, as the following example shows.

Suppose the data are 6-hourly observations from 1-JAN-1991 at 12:00 to 15-MAR-1991 at 18:00. These commands will assist in creating the necessary time axis for a NetCDF file:

yes? DEFINE AXIS/T="1-JAN-1991:12:00":"15-MAR-1991:18:00":6/UNITS=hours\
     my_time
yes? DEFINE GRID/T=my_time tgrid
yes? SET REGION/T="1-JAN-1991:12:00":"15-MAR-1991:18:00"
yes? LIST T[g=tgrid]                               !to see the time values
yes? SAVE/FILE=my_time.cdf T[g=tgrid]

The file my_time.cdf now contains a model of exactly the desired time axis. Use the Unix command

% ncdump my_time.cdf > my_time.cdl

to obtain the time axis definition as text that can be inserted into your CDL file.


Ch10 Sec3.6. Example CDL file

The following is an example CDL file utilizing many of the features described in the preceding section.

netcdf converting_to_netcdf_supplement {
//      CONVERTING DATA TO THE "NETWORK COMMON DATA FORM" (NetCDF):
//                         A SUPPLEMENT
//
// NOAA PMEL Thermal Modeling and Analysis Project (TMAP)
// Dan Trueman, Steve Hankin
// last revised: 1 Dec 1993:  slat80_82 and slon10_140 coordinates included
//
// I. INTRODUCTION
//
// This supplement to "Converting Data to the Network Common Data Form:
// an Introduction" describes:
//
//      1. How to set up a cdl file capable of handling data
//         on staggered grids.
//      2. How to define coordinate systems such that the data
//         in the NetCDF file may be regarded as hyperslabs of
//         larger coordinate spaces.
//      3. How to define variables of 1, 2, or 3 dimensions.
//      4. How to define boundaries between unevenly spaced axis
//         coordinates (used in numerical integrations).
//      5. How to set up climatological "modulo" time axes.
//      6. How to convert time word data into numerical data
//         appropriate for NetCDF.
//
// In this sample data set, we will consider wind, salt, and
// velocity calculated using a staggered-grid, finite-difference
// technique. The wind data is naturally limited to the surface
// layer of the ocean (i.e. normal to the  depth axis).  We will
// also consider the salt data to be limited to a narrow slab from
// 139E to 90W (I=10 to 140), 32.5N to 34.9N (J=80 to 82), and for
// all depth and time values.
//
// II. STAGGERED GRIDS
//
// Dealing with staggered grids is fairly straightforward.  Dimensions
// for each grid axis must be defined, the axes themselves must be
// defined (in Variables), and the coordinate values for each axis must
// be initialized (in Data).  In this case, there are two grids, a
// wind grid, and a velocity grid, so tlon, tlat and tdepth are
// defined for the wind grid, and ulon, ulat, and udepth for the velocity
// grid.  The variables are then given arguments to place them in their
// proper grids (i.e. wind(time, sdepth, slat, slon)).
//
// III. HYPERSLABS
//
// There are a number of steps required to set up a NetCDF data set that
// represents a hyperslab of data from a larger grid definition.
//
//      1. Define a dimension named "grid_definition".  This dimension
//         should be set equal to 1.
//      2. Define parent grids in Variables with the argument
//         "grid_definition".
//
//              char wind_grid(grid_definition) ;
//              char salt_grid(grid_definition) ;
//
//      3. Define the 4 axes of the parent grids using the "axes" attribute.
//
//                   wind_grid: axes = "slon slat normal time" ;
//                   salt_grid: axes = "slon slat sdepth time" ;
//         
//          Note that the order of arguments is opposite that in the
//          variable declaration.  The argument "normal" indicates that
//          wind_grid is normal to the depth axis.
//
//       4. Define the variables which are hyperslabs of these grids with
//          the proper dimensions.
//
//              float wind(time, slat, slon) ;  
//              float salt(time, sdepth, slat80_82, slon10_140) ;
//
//         where slat80_82 = 3 and slon10_140 = 131. The axis names are
///        arbitrary - chosen for readability. These axes (child axes)
//         must be defined with the attribute "child_axis" as follows:
//
//              float slat80_82(slat80_82) ;
//                    slat80_82: child_axis = " " ;
//
//         These "child axes" need not be initialized in Data, nor do their

//         edges need be defined; Ferret retrieves this information from
//         the parent axes.
//
//      5. Use the "parent_grid" variable attribute to point to the
//         parent grid.
//
//                   wind: parent_grid = "wind_grid"
//
//      6. Also as a variable attribute, define the index range of interest
//         within the parent grid.
//
//                   wind: slab_min_index = 1s, 1s, 1s, 0s ;
//                   wind: slab_max_index = 160s, 100s, 1s, 0s ;
//                   salt: slab_min_index = 10s, 80s, 1s, 0s ;
//                   salt: slab_max_index = 140s, 82s, 27s, 0s ;
//
//         The "s" after each integer indicates a "short" 16-bit integer
//         rather than the default "long" 32-bit integer.  If an axis
//         dimension is designated as "unlimited" then the index bounds
//         for this axis must be designated as "0s".
//
// These commands will effectively locate the wind and salt data within
// the full grid.
//
// IV. VARIABLES OF 1, 2, or 3 DIMENSIONS
//
// One, two, or three dimensional variables may be set up in one of
// two ways - either using the parent_grid and child_axis attributes
// as illustrated in the 3-dimensional variable "wind" from the hyperslab
// example, above, or by selecting axis names and units that provide
// Ferret with adequate hints to map this variable onto 4-dimensional
// space and time.  The following hints are recognized by Ferret:
//
//      Units of days, hours, minutes, etc. or an axis name of "TIME", "DATE"
//         implies a time axis.
//      Units of "degrees xxxx" where "xxxx" contains "lat" or "lon" implies
//         a latitude or longitude axis, respectively.
//      Units of "degrees" together with an axis name containing "LAT" or
//         "Y" implies a latitude axis else longitude is assumed.
//      Units of millibars, "layer" or "level" or an axis name containing
//         "Z" or "ELEV" implies a vertical axis.
//
// V. UNEVENLY SPACED COORDINATE BOUNDARIES
//
// For coordinate axes with uneven spacing, the boundaries between each
// coordinate can be indicated by pointing to an additional axis that
// contains the locations of the boundaries.  The dimension of this "edge"
// axis will necessarily be one larger than the coordinate axis concerned.
// If edges are not defined for an unevenly spaced axis, the midpoint
// between coordinates will be assumed by default.
//
//      1. Define a dimension one larger than the coordinate axis.  For
//         the sdepth axis, with 27 coordinates, define:
//
//              sdepth_edges = 28 ;
//
//      2. Define an axis called sdepth_edges.
//      3. Initialize this axis appropriately (in Data).
//      4. As a sdepth axis attribute, point to sdepth_edges:
//
//                   sdepth: edges = "sdepth_edges" ;
//
// If the coordinate axes are evenly spaced, the attribute "point spacing"
// should be used:
//
//                   slat: point_spacing = "even" ;
//
// When used, this attribute will improve memory use efficiency in Ferret.  
//
// VI. CLIMATOLOGICAL "MODULO" AXES
//
// The "modulo" axis attribute indicates that the axis wraps around,
// the first point immediately following the last.  The most common
// uses of modulo axes are:
//
//      1. As longitude axes for globe-encircling data.
//      2. As time axes for climatological data.
//
//                   time: modulo = " " ; // any arbitrary string is allowed
//
// If the climatological data occurs in the years 0000 or 0001 then Ferret
// will omit the year from the output formatting.
//
// VII. CONVERTING TIME WORD DATA TO NUMERICAL DATA
//
// If the time data being converted to NetCDF format exists in string format
// (i.e. 1972 - JANUARY 15 2:15:00), rather than numerical format (i.e. 55123
// seconds) a number of TMAP routines are available to aid in the conversion
// process.  The steps required for conversion are as follows:
//
//      1. Break the time string into its 6 pieces.  If the data is of the
//         form dd-mmm-yyyy:hh:mm:dd, the TMAP routine "tm_break_date.f" can
//         be used.
//      2. Choose a time_origin before the beginning of the time data to
//         assure that all time values are positive.  i.e. if the data begins
//         at 15-JAN-1982:05:30:00, choose a time origin of
//         15-JAN-1981:00:00:00. This time_origin should then be an attribute
//         of the time axis variable in the CDL file.
//      3. Produce numerical time data by using "tm_sec_from_bc.f", which
//         calculates the number of seconds between 01-01-0000:00:00:00 and
//         the date specified.  Continuing the example from (2), the time value
//         for the first time step with respect to the time_origin could be
//         calculated as follows:
//
//         time(1) = tm_sec_from_bc(1982, 1, 15, 5, 30, 0) -
//                   tm_sec_from_bc(1981, 1, 15, 0, 0, 0)
//
//         or more generally
//
//         time(n)=tm_sec_from_bc(nyear,nmonth,nday,nhour,nminute,nsecond) -
//                 tm-sec_from_bc(oyear,omonth,oday,ohour,ominute,osecond)
//
//         where nyear is the year for the nth time step and oyear is the year
//         of time_origin.
//
// VII. EXAMPLE CDL FILE dimensions:

// staggered grid dimension definitions:

           slon = 160 ;    // wind/salt longitude dimension
           ulon = 160 ;    // velocity longitude dimension
           slat = 100 ;    // wind/salt latitude dimension
           ulat = 100 ;    // velocity latitude dimension
           sdepth = 27 ;   // salt depth dimension
           wdepth = 27 ;   // velocity depth dimension

           slon10_140 = 131 ;      // for salt hyperslab
           slat80_82 = 3 ;         // for salt hyperslab
            time = unlimited ;

// grid_definition is the dimension name to be used for all grid definitions

           grid_definition = 1 ;

// edge dimension definitions:

           sdepth_edges = 28 ;
           wdepth_edges = 28 ;

variables:

 // variable definitions:

           float wind(time, slat, slon) ;  // 3-dimensional variable
                     wind: parent_grid = "wind_grid" ;
                     wind: slab_min_index = 1s, 1s, 1s, 0s ;
                     wind: slab_max_index = 160s, 100s, 1s, 0s ;
                     wind: long_name = "WIND" ;
                     wind: units     = "deg. C" ;
                     wind: _FillValue = 1E34f ;
           float salt(time, sdepth, slat80_82, slon10_140) ; // 4-dim. Variable
                     salt: parent_grid = "salt_grid" ;
                     salt: slab_min_index = 10s, 80s, 1s, 0s ;
                     salt: slab_max_index = 140s, 82s, 27s, 0s ;
                     salt: long_name = "(SALINITY(ppt) - 35) /1000" ;
                     salt: units     = "frac. by wt. less .035" ;
                     salt: _FillValue = -999.f ;

           float u(time, sdepth, ulat, ulon) ;
                     u: long_name    = "ZONAL VELOCITY" ;
                     u: units        = "cm/sec" ;
                     u: _FillValue = 1E34f ;
           float v(time, sdepth, ulat, ulon) ;
                     v: long_name    = "MERIDIONAL VELOCITY" ;
                     v: units        = "cm/sec" ;
                     v: _FillValue = 1E34f ;
           float w(time, wdepth, slat, slon) ;
                     w: long_name    = "VERTICAL VELOCITY" ;
                     w: units        = "cm/sec" ;
                     w: _FillValue = 1E34f ;

 // axis definitions:

           float slon(slon) ;
                     slon: units = "degrees" ;
                     slon: point_spacing = "even" ;
           float ulon(ulon) ;
                     ulon: units = "degrees" ;
                     ulon: point_spacing = "even" ;
           float slat(slat) ;
                     slat: units = "degrees" ;
                     slat: point_spacing = "even" ;
           float ulat(ulat) ;
                     ulat: units = "degrees" ;
                 ulat: point_spacing = "even" ;
           float sdepth(sdepth) ;
                     sdepth: units = "meters" ;
                     sdepth: positive = "down" ;
                     sdepth: edges = "sdepth_edges" ;
           float wdepth(wdepth) ;
                     wdepth: units = "meters" ;
                     wdepth: positive = "down" ;
                     wdepth: edges = "wdepth_edges" ;
           float time(time) ;
                     time: modulo = " " ;
                 time: time_origin = "15-JAN-1981:00:00:00" ;
                     time: units = "seconds" ;

 // child grid definitions:

           float slon10_140(slon10_140) ;
                     slon10_140: child_axis = " " ;

                     slon10_140: units = "degrees" ;
           float slat80_82(slat80_82) ;
                     slat80_82: child_axis = " " ;
                     slat80_82: units = "degrees" ;

 // edge axis definitions:

           float sdepth_edges(sdepth_edges) ;
           float wdepth_edges(wdepth_edges) ;

 // parent grid definition:

           char wind_grid(grid_definition) ;
                    wind_grid: axes = "slon slat normal time" ;
           char salt_grid(grid_definition) ;
                    salt_grid: axes = "slon slat sdepth time" ;

 // global attributes:
           :title = "NetCDF Title" ;

data:

//  //  ignore this block  //
//This next data entry, for time, should be ignored. Time is initialized here
// only so that Ferret can read test.cdf (the file created by this cdl file)
// with no additional data inserted into it.
Time=1000;
// // end of ignored block //

slat=
-28.8360729218,-26.5299491882,-24.2880744934,-22.1501560211,-20.1513576508,
-18.3207626343,-16.6801033020,-15.2428140640,-14.0134353638,-12.9874248505,
-12.1513509750,-11.4834814072,-10.9547319412,-10.5299386978,-10.1693935394,
-9.8333206177,-9.4999876022,-9.1666536331,-8.8333196640,-8.4999856949,
-8.1666526794,-7.8333187103,-7.4999847412,-7.1666512489,-6.8333182335,
-6.4999852180,-6.1666517258,-5.8333182335,-5.4999852180,-5.1666517258,
-4.8333187103,-4.4999852180,-4.1666517258,-3.8333187103,-3.4999852180,
-3.1666517258,-2.8333184719,-2.4999852180,-2.1666519642,-1.8333185911,
-1.4999852180,-1.1666518450,-0.8333183527,-0.4999849498,-0.1666515470,
0.1666818559,0.5000152588,0.8333486915,1.1666821241,1.5000154972,
1.8333489895,2.1666824818,2.5000159740,2.8333494663,3.1666829586,
3.5000162125,3.8333497047,4.1666831970,4.5000162125,4.8333497047,
5.1666831970,5.5000162125,5.8333497047,6.1666827202,6.5000162125,
6.8333497047,7.1666827202,7.5000166893,7.8333501816,8.1666841507,
8.5000181198,8.8333511353,9.1666851044,9.5000190735,9.8333530426,
10.1679363251,10.5137376785,10.8892869949,11.3138961792,11.8060989380,
12.3833675385,13.0618314743,13.8560228348,14.7786512375,15.8403968811,
17.0497493744,18.4128704071,19.9334945679,21.6128730774,23.4497566223,
25.4404067993,27.5786647797,29.8560409546,32.2618522644,34.7833900452,
37.4061241150,40.1139259338,42.8893203735,45.7137718201,48.5679702759;
ulat=
-27.6721439362,-25.3877544403,-23.1883945465,-21.1119174957,-19.1907978058,
-17.4507274628,-15.9094810486,-14.5761461258,-13.4507236481,-12.5241250992,
-11.7785758972,-11.1883859634,-10.7210769653,-10.3387994766,-9.9999876022,
-9.6666545868,-9.3333206177,-8.9999866486,-8.6666526794,-8.3333196640,
-7.9999856949,-7.6666517258,-7.3333182335,-6.9999847412,-6.6666512489,
-6.3333182335,-5.9999847412,-5.6666517258,-5.3333182335,-4.9999847412,
-4.6666517258,-4.3333182335,-3.9999849796,-3.6666517258,-3.3333184719,
-2.9999852180,-2.6666519642,-2.3333184719,-1.9999853373,-1.6666518450,
-1.3333184719,-0.9999850392,-0.6666516662,-0.3333182633,0.0000151545,
0.3333485723,0.6666819453,1.0000153780,1.3333487511,1.6666821241,
2.0000154972,2.3333489895,2.6666827202,3.0000162125,3.3333497047,
3.6666829586,4.0000162125,4.3333497047,4.6666827202,5.0000162125,
5.3333492279,5.6666827202,6.0000162125,6.3333492279,6.6666827202,
7.0000157356,7.3333497047,7.6666831970,8.0000171661,8.3333511353,
8.6666841507,9.0000181198,9.3333520889,9.6666860580,10.0000190735,
10.3358526230,10.6916217804,11.0869522095,11.5408391953,12.0713586807,
12.6953773499,13.4282865524,14.2837600708,15.2735414505,16.4072513580,
17.6922454834,19.1334934235,20.7334957123,22.4922523499,24.4072608948,
26.4735546112,28.6837768555,31.0283031464,33.4953994751,36.0713844299,
38.7408676147,41.4869842529,44.2916526794,47.1358833313,50.0000534058;
slon=
130.5,131.5,132.5,133.5,134.5,135.5,136.5,137.5,138.5,139.5,140.5,141.5,
142.5,143.5,144.5,145.5,146.5,147.5,148.5,149.5,150.5,151.5,152.5,153.5,
154.5,155.5,156.5,157.5,158.5,159.5,160.5,161.5,162.5,163.5,164.5,165.5,
166.5,167.5,168.5,169.5,170.5,171.5,172.5,173.5,174.5,175.5,176.5,177.5,
178.5,179.5,180.5,181.5,182.5,183.5,184.5,185.5,186.5,187.5,188.5,189.5,
190.5,191.5,192.5,193.5,194.5,195.5,196.5,197.5,198.5,199.5,200.5,201.5,
202.5,203.5,204.5,205.5,206.5,207.5,208.5,209.5,210.5,211.5,212.5,213.5,
214.5,215.5,216.5,217.5,218.5,219.5,220.5,221.5,222.5,223.5,224.5,225.5,
226.5,227.5,228.5,229.5,230.5,231.5,232.5,233.5,234.5,235.5,236.5,237.5,
238.5,239.5,240.5,241.5,242.5,243.5,244.5,245.5,246.5,247.5,248.5,249.5,
250.5,251.5,252.5,253.5,254.5,255.5,256.5,257.5,258.5,259.5,260.5,261.5,
262.5,263.5,264.5,265.5,266.5,267.5,268.5,269.5,270.5,271.5,272.5,273.5,
274.5,275.5,276.5,277.5,278.5,279.5,280.5,281.5,282.5,283.5,284.5,285.5,
286.5,287.5,288.5,289.5;
ulon=
131.0,132.0,133.0,134.0,135.0,136.0,137.0,138.0,139.0,140.0,141.0,142.0,
143.0,144.0,145.0,146.0,147.0,148.0,149.0,150.0,151.0,152.0,153.0,154.0,
155.0,156.0,157.0,158.0,159.0,160.0,161.0,162.0,163.0,164.0,165.0,166.0,
167.0,168.0,169.0,170.0,171.0,172.0,173.0,174.0,175.0,176.0,177.0,178.0,
179.0,180.0,181.0,182.0,183.0,184.0,185.0,186.0,187.0,188.0,189.0,190.0,
191.0,192.0,193.0,194.0,195.0,196.0,197.0,198.0,199.0,200.0,201.0,202.0,
203.0,204.0,205.0,206.0,207.0,208.0,209.0,210.0,211.0,212.0,213.0,214.0,
215.0,216.0,217.0,218.0,219.0,220.0,221.0,222.0,223.0,224.0,225.0,226.0,
227.0,228.0,229.0,230.0,231.0,232.0,233.0,234.0,235.0,236.0,237.0,238.0,
239.0,240.0,241.0,242.0,243.0,244.0,245.0,246.0,247.0,248.0,249.0,250.0,
251.0,252.0,253.0,254.0,255.0,256.0,257.0,258.0,259.0,260.0,261.0,262.0,
263.0,264.0,265.0,266.0,267.0,268.0,269.0,270.0,271.0,272.0,273.0,274.0,
275.0,276.0,277.0,278.0,279.0,280.0,281.0,282.0,283.0,284.0,285.0,286.0,
287.0,288.0,289.0,290.0;
sdepth=
5.0,15.0,25.0,35.0,45.0,55.0,65.0,75.0,85.0,95.0,106.25,120.0,136.25,155.0,
177.5,205.0,240.0,288.5,362.5,483.5,680.0,979.5,1395.5,1916.0,2524.0,3174.0,
3824.0;
sdepth_edges=
0.0,10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,112.5,127.5,
145.0,165.0,190.0,220.0,260.0,317.0,408.0,559.0,801.0,1158.0,1633.0,2199.0,
2849.0,3499.0,4149.0;
wdepth=
10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,112.5,127.5,145.0,165.0,
190.0,220.0,260.0,317.0,408.0,559.0,801.0,1158.0,1633.0,2199.0,2849.0,3499.0,
4149.0;
wdepth_edges=
5.0,15.0,25.0,35.0,45.0,55.0,65.0,75.0,85.0,94.375,105.625,119.375,135.625,
153.75,176.25,202.5,235.75,280.0,347.5,460.75,651.25,950.0,1372.75,1895.0,
2524.0,3174.0,3986.5,4311.0;
slon10_140=
       139.5, 140.5, 141.5, 142.5, 143.5, 144.5, 145.5, 146.5, 147.5,
       148.5, 149.5, 150.5, 151.5, 152.5, 153.5, 154.5, 155.5, 156.5, 157.5,
       158.5, 159.5, 160.5, 161.5, 162.5, 163.5, 164.5, 165.5, 166.5, 167.5,
       168.5, 169.5, 170.5, 171.5, 172.5, 173.5, 174.5, 175.5, 176.5, 177.5,
       178.5, 179.5, 180.5, 181.5, 182.5, 183.5, 184.5, 185.5, 186.5, 187.5,
       188.5, 189.5, 190.5, 191.5, 192.5, 193.5, 194.5, 195.5, 196.5, 197.5,
       198.5, 199.5, 200.5, 201.5, 202.5, 203.5, 204.5, 205.5, 206.5, 207.5,
       208.5, 209.5, 210.5, 211.5, 212.5, 213.5, 214.5, 215.5, 216.5, 217.5,
       218.5, 219.5, 220.5, 221.5, 222.5, 223.5, 224.5, 225.5, 226.5, 227.5,
       228.5, 229.5, 230.5, 231.5, 232.5, 233.5, 234.5, 235.5, 236.5, 237.5,
       238.5, 239.5, 240.5, 241.5, 242.5, 243.5, 244.5, 245.5, 246.5, 247.5,
       248.5, 249.5, 250.5, 251.5, 252.5, 253.5, 254.5, 255.5, 256.5, 257.5,
       258.5, 259.5, 260.5, 261.5, 262.5, 263.5, 264.5, 265.5, 266.5, 267.5,
       268.5, 269.5 ;
slat80_82=
       11.8060989379883, 12.3833675384522, 13.0618314743042 ;

}



Ch10 Sec4. CREATING A MULTI-FILE NETCDF DATA SET

Ferret supports collections of NetCDF files that are regarded as a single NetCDF data set. Such data sets are referred to as "MC" (multi CDF) data sets. They are defined via a descriptor file, in the style of TMAP-formatted data sets. These are FORTRAN NAMELIST-formatted files. Slight variations in syntax exist between systems. The requirements for an MC data set are described in the chapter "Data Set Basics", section "Multi-file NetCDF data sets".

Previous to version 5.2 Ferret performs sanity checking on the data set by comparing these time coordinates with those found in the data files as he data are read.  In version 5.3 and higher no sanity checks are performed. This means that the MC descriptor mechanism can be used to associate into time series groups of files that are not internally self-documenting with respect to time, however, it also shifts an additional burden onto the user of carefully checking the validity of the STEPFILE records in the descriptor files.

The fields which are essential to consider are

$FORMAT_RECORD

      D_TYPE               = '  MC' ,
     D_FORMAT             = '  1A',

which must be exactly as shown.

$BACKGROUND_RECORD

      D_TITLE              = 'Put your data set title here',

where you can insert a data sets title to appear on plots and listings;

      D_T0TIME             = '14-JAN-1980 14:00:00',

which corresponds exactly to the /T0 qualifier on the DEFINE AXIS command

      D_TIME_UNIT          = 3600.0,

which contains the same information as /UNITS= on the DEFINE AXIS command encoded      as numbers of seconds .  (/UNITS="minutes" corresponds to D_TIME_UNIT  = 60., /UNITS="hours" corresponds to D_TIME_UNIT  = 3600., etc.)

      D_CALTYPE          = 360_DAY,

to specify the name of the calendar if your time axis is not on the standard Gregorian calendar.  See the discussion of time axes and calendars (p. 118) for more on the calendars available.

$STEPFILE_RECORD

      S_FILENAME           = 'mtaa063-nc.001',

which points to the individual file names. Typically you will need one STEPFILE_RECORD for each file in the series,  however if the files are named with extension .001, .002, ... you can use S_NUM_OF_FILES below.

      S_START              = 17592.0,

which contains the time step value of the first time step in the file. (For help determining the time step values use DEFINE AXIS to create the desired time axis (say, my_t_ax) and then use LIST T[gt=my_t_ax] to see the dates and time steps.)

      S_END                = 34309.0,

which contains the time step value of the last time step in the file (or group of files if S_NUM_OF_FILES is greater than 1). If there is only a single time step in the file set S_END identical to S_START.

      S_DELTA              = 73.0,

which contains the delta value separating time steps within in the file. If there is only a single time step in the file set S_DELTA = 1.

      S_NUM_OF_FILES       = 23,

Normally  S_NUM_OF_FILES should be omitted or should have a value of 1. Use it for the special case that your files are named with ending .001, .002, .... in which case you can describe them all with a single STEPFILE_RECORD as in the example. ( S_DELTA must then also describe the delta between the last time step in each file and the first time step in the next file of the series.)

A typical MC descriptor file is given below. This file ties into a single data set the 23 files named mtaa063-nc.001 through mtaa063-nc.024. The time steps are encoded in the descriptor file through the S_START and S_END values.

Descriptor files have a space before the $ in the record headers, and comment lines begin with a *.  In addition there are differences in the formatting of descriptor files depending on the operationg system.  Here is an FAQ which addresses these differences:

http://ferret.wrc.noaa.gov/Ferret/FAQ/system/linux_mc_descriptors.html

***************************************************************************
*        NOAA/PMEL Tropical Modeling and Analysis Program, Seattle, WA.   *
*                      created by MAKE_DESCRIPT rev. 4.01                 *
***************************************************************************
$FORMAT_RECORD
      D_TYPE               = '  MC',
      D_FORMAT             = '  1A',
      D_SOURCE_CLASS       = 'MODEL OUTPUT',
$END
$BACKGROUND_RECORD
      D_EXPNUM             = '0063',
      D_MODNUM             = '  AA',
      D_TITLE              = 'MOM model output forced by Sadler winds',
      D_T0TIME             = '14-JAN-1980 14:00:00',
      D_TIME_UNIT          = 3600.0,
      D_TIME_MODULO        = .FALSE.,
      D_ADD_PARM           = 15*' ',
$END
$MESSAGE_RECORD
      D_MESSAGE            = ' ',
      D_ALERT_ON_OPEN      = F,
      D_ALERT_ON_OUTPUT    = F,
$END
*************************************************
$EXTRA_RECORD
$END

$STEPFILE_RECORD
      s_filename           = 'mtaa063-nc.001',
      S_AUX_SET_NUM        = 0,
      S_START              = 17592.0,
      S_END                = 34309.0,
      S_DELTA              = 73.0,
      S_NUM_OF_FILES       = 23,
      S_REGVARFLAG         = ' ',
$END
**************************************************
$STEPFILE_RECORD
      s_filename           = '**END OF STEPFILES**'

$END
**************************************************