To save space in the netCDF file, it may be desirable to eliminate points from data arrays that are invariably missing. Such a compression can operate over one or more adjacent axes, and is accomplished with reference to a list of the points to be stored. The list is constructed by considering a mask array that only includes the axes to be compressed, and then mapping this array onto one dimension without reordering. The list is the set of indices in this one-dimensional mask of the required points. In the compressed array, the axes to be compressed are all replaced by a single axis, whose dimension is the number of wanted points. The wanted points appear along this dimension in the same order they appear in the uncompressed array, with the unwanted points skipped over. Compression and uncompression are executed by looping over the list.
The list is stored as the coordinate variable
for the compressed axis of the data array. Thus,
the list variable and its dimension have the same
name. The list variable has a string attribute
compress
, containing a blank-separated list
of the dimensions which were affected by the
compression in the order of the CDL declaration
of the uncompressed array. The presence of
this attribute identifies the list variable
as such. The list, the original dimensions
and coordinate variables (including boundary
variables), and the compressed variables with
all the attributes of the uncompressed variables
are written to the netCDF file. The uncompressed
variables can be reconstituted exactly as they
were using this information.
Example 8.1. Horizontal compression of a three-dimensional array
We eliminate sea
points at all depths in a
longitude-latitude-depth array of
soil temperatures. In this case,
only the longitude and latitude
axes would be affected by the
compression. We construct a list
landpoint(landpoint)
containing
the indices of land points.
dimensions: lat=73; lon=96; landpoint=2381; depth=4; variables: int landpoint(landpoint); landpoint:compress="lat lon"; float landsoilt(depth,landpoint); landsoilt:long_name="soil temperature"; landsoilt:units="K"; float depth(depth); float lat(lat); float lon(lon); data: landpoint=363, 364, 365, ...;
Since
landpoint(0)=363
,
for instance, we know that
landsoilt(*,0)
maps on to point 363 of the original data with dimensions
(lat,lon)
.
This corresponds to indices
(3,75)
,
i.e.,
363 = 3*96 + 75
.
Example 8.2. Compression of a three-dimensional field
We compress a longitude-latitude-depth field of ocean salinity by eliminating points below the sea-floor. In this case, all three dimensions are affected by the compression, since there are successively fewer active ocean points at increasing depths.
variables: float salinity(time,oceanpoint); int oceanpoint(oceanpoint); oceanpoint:compress="depth lat lon"; float depth(depth); float lat(lat); float lon(lon); double time(time);
This information implies that
the salinity field should be
uncompressed to an array with
dimensions
(depth,lat,lon)
.