GDV Conventions for Gridded Data in NetCDF
John Caron caron@ucar.edu
Last changed: 10/11/2001
GDV Conventions are a superset of COARDS
Conventions, so that a COARDS-compliant dataset is also a GDV
dataset. Because GDV allows dimensions to be in any order, a GDV dataset
is not necessaily a COARDS dataset. Additional features are added
while trying to retain the original simplicity and clarity of COARDS. In
general, the goal is to provide a minimal set of conventions that will
allow maximum data use by software programs.
This document reflects the state of implementation by the
Integrated
Data Viewer. These conventions are recommended to data providers who
are writing new gridded datasets in netCDF. If your gridded dataset cannot
be specified by these conventions, please let me know.
Convention Specification
Required:
:Conventions = "GDV";
or, if the file satisfies both COARDS and GDV conventions:
:Conventions = "COARDS, GDV";
Recommended:
:ConventionsURL = "http://www.unidata.ucar.edu/staff/caron/GDV/Conventions.html";
GeoGrids
A GeoGrid is a special type of NetCDF variable that follows the rules listed
next. The IDV is specialized to display GeoGrids, and so only displays those
netCDF variables that are GeoGrids.
Required:
-
All of the variable's dimensions must have a georeferencing coordinate
axis (see below); the axes may be in any order.
-
The variable can have a maximum of one x,y,z,and t
coordinate axis.
-
Missing data must be designated in one of the following ways:
-
the _FillValue attribute can be used to specify a missing value.
-
the missing_value attribute can be used to specify a list of missing
values.
-
valid_range can be used to specify the range of valid values;
values outside the range are missing. If valid_range is not present,
valid_min
and/or valid_max can be used to specify the range of valid values.
-
If the data type is float or double, the data value may be set to NaN.
-
Packed data must be specified using the scale_factor and add_offset
Variable attributes. Data is converted using:
unpacked_value = scale_factor * packed_value + add_offset
If you want to specify missing data with a packed data Variable, the following
rules apply:
-
_FillValue and missing_value are alwats in units
of external (packed) data.
-
If valid_range is the same type as scale_factor (actually
the wider of scale_factor and add_offset) and this is wider than the external
data type, then it will be interpreted as being in the units of the internal
(unpacked) data. Otherwise it is in the units of the external (packed)
data.
Recommended:
-
the long_name and units attributes are strongly recommended for each variable,
eg:
float geogrid(t,z,y,x);
geogrid:long_name = “descriptive name”;
geogrid:units = “unit string parsable by ucar.units”;
Coordinate Axes
Coordinate axes are a generalization of netCDF coordinate variables. When
we look at a variable, we see a list of dimensions. We need to associate
with each dimension a set of coordinates, which we call a coordinate
axis. Normally this is specified by a netCDF variable with some special
restrictions.
-
A coordinate variable is the best way to define a coordinate axis, for
example:
float lat(lat);
-
Sometimes due to naming or cardinality, this doesn't work, so you may also
define a coordinate axis by adding the attribute coord_axis to
a netCDF Variable, for example, to use a different name:
float myLat( lat);
myLat:coord_axis = "lat";
-
The other thing you might want to do is to define the edges of the coordinate
grids rather than coordinate points, which means you need n+1 edges for
n coordinates, so you can use the variable attribute coord_axis
whose value is the name of the dimension. For example:
float lat_edge( lat_edge);
lat_edge:coord_axis = "lat";
which says that lat_edge is a coordinate axis for dimension lat.
Variables that use the "lat" dimension will be properly georeferenced.
The dimension lat_edge must be exactly one greater than the dimension
lat. You can have both a regular coordinate axis and an "edge" coordinate
axis, and GDV will tell which is which by the cardinality. In no other
case can you have more than one coordinate axis for a dimension.
A coordinate axis must obey the following restrictions:
-
It must have an attribute named units, whose value is parsable
by udunits.
-
It must be strictly monotonic increasing or decreasing.
-
It may not have missing values.
GeoReferencing Coordinate Axes
These are coordinate axes that describe the spatial and time coordinates
of the data. There are three kinds: time, vertical, and horizontal.
Time Coordinate Axis
-
The time coordinate axis must have a udunits time unit, eg "secs
since 1970-01-01 00:00:00" or "days since 0000-01-01".
-
It is identified by one of these methods (preferred ones first).
-
the Variable name is time
-
it has an attribute: coord_alias = "time";
-
the units are in udunits of time.
Note that if you have other variables that have units of time, it
would be smart not to rely on method 3 to identify the time coordinates
axes.
Vertical Coordinate Axis
The vertical coordinate axis must have a unit attribute
It is identified by one of these methods:
-
the Variable name is z, level or lev.
-
the value of the Variable's attribute coord_alias is z, level or
lev.
-
the Variable units are hybrid_sigma_pressure or sigma_level.
-
the presence of a Variable attribute positive, whose value is
up
or down.
-
the units are in pressure (udunits convertible to millibar)
Note that if you have other variables that have units of pressure, it would
be smart not to rely on method 5 to identify the vertical coordinates axes.
Horizontal Coordinate Axes
The horizontal coordinate axis must specify lat/lon or projection coordinates:
Lat/Lon Horizontal Coordinate Axes
-
The lat coordinate values must be in degrees, north positive.
-
The lat units should be "degrees_north".
-
The lat axis is identified by one of these methods (preferred ones first):
-
the variable name is lat.
-
the value of the variable's attribute coord_alias is "lat".
-
the value of the variable's attribute units is "degrees_north",
"degree_north", "degrees_N", or "degree_N".
-
The lon coordinate values must be in degrees, east positive.
-
The lon units should be "degrees_east".
-
The lon axis is identified by one of these methods (preferred ones first):
-
the variable name is lon.
-
the value of the variable's attribute coord_alias is "lon".
-
the value of the variable's attribute units is "degrees_east",
"degree_east", "degrees_E", or "degree_E".
Note that if you have other variables that have units of degrees_north
or
degrees_east, it would be smart not to rely on units value to identify
the horizontal coordinates axes.
Projection Horizontal Coordinate Axes
Many gridded models are generated on a projection coordinate system. To
map these to the earth's surface, we use a projection function, which is
an invertible mapping from lat/lon to a cartesian (x,y) plane. The
grid coordinates can then be represented simply by two orthogonal coordinates
axes, x and y, and the projection function is used to map them to lat/lon.
The (x,y) coordinates are typically in units of "km on the projection plane".
-
The x and y units must be convertable to "km".
-
The x axis is identified by one of these methods (preferred ones first):
-
the variable name is x.
-
the value of the attribute coord_axis is "x".
-
The y axis is identified by one of these methods (preferred ones first):
-
the variable name is y.
-
the value of the attribute coord_axis is "y".
The projection function itself is specified by global attributes:
:projection = "<projection name>";
:projection_params = "<projection parameters>";
The currently implemented projections and their parameters are:
-
"LambertConformal", "<lat0> <lon0> <par1> <par2>"
-
<lat0>,<lon0> is the origin of the coord. system on the projection
plane
-
<par1> ,<par2> are the standard parallels
-
"TransverseMercator", "<central meridian> <origin lat>
<scale>"
-
<central meridian> is the longitude (meridian) that the cylinder
is tangent at
-
<origin lat> origin of the projection coord system is at (<origin
lat>, <central meridian>)
-
<scale> scale factor along the central meridian
-
"Stereographic", "<latt> <lont> <scale>"
-
<latt>, <lont>: tangent point of projection, also origin of projection
coord system
-
<scale>: scale factor at tangent point, "normally 1.0 but may be reduced"
The projection parameters are space or comma delimited. Reference:
John Snyder, Map Projections used by the USGS, Bulletin 1532, 2nd edition
(1983). Note that we havent yet dealt with projections that dont map to
the earth's surface (like some satellite projections).
Comparision to other netCDF conventions:
COARDS
-
GDV dimensions can be in any order
-
GDV coordinate variable names have additional conventions to allow unambiguous
identification of the x,y,z,t axes.
-
GDV allows projections for the horizontal coordinates
CSM (version 1)
CSM (version 1) are also a superset of COARDS, and GDV has included some
of their extensions. Ultimately it could be a superset of CSM1 also.
Not done yet is:
-
parsing the vertical cordinate information
-
coordinate attribute (multidimensional coordinate variables)
-
calendar
-
coord_op, bounds attribute
-
coord_label
-
proj_coordinates
If you are interested in having GDV read a CSM dataset that depends on
one of these features, please send me a sample dataset.
VMD
This is an older set of conventions developed in conjunction with the VMD
program, an earlier version of GDV written in C.
The coordinate axes can be identified by global attributes, eg:
:x = "Regular: npts 62 start_edge -7533.0 size 243 km";
:y = "Regular: npts 62 start_edge -7533.0 size 243 km";
:lev = "lev";
:time = "time";
The projection information is specified by:
:projection = "Oblique_Stereographic";
:proj_params = "lat0 90 lon0 -105 latt 90 lont -105 scale .93301270189";
It follows the CSM conventions for sigma coordinates:
float lev(lev);
:units = "hybrid";
:long_name = "hybrid coord midpoints";
:positive = "down";
:edge = "lev_edge";
float lev_edge(lev_edge);
:units = "hybrid";
:long_name = "hybrid coord edges";
:positive = "down";
float hybmida(lev);
float hybmidb(lev);
float hybinta(lev_edge);
float hybintb(lev_edge);
:pref = 100000.0; // global
:ps0 = 100000.0;
Notes on parsing NUWG Conventions
-
x,y: derived from nav variable
-
z: "fhg" or "fh" or "sigma" or contains "level"
-
t: "time"
-
create coord axis if referential