When the CDM reads an OPeNDAP dataset, it makes the following transformations:
OPeNDAP primitive | CDM primitive |
---|---|
Boolean | boolean |
Byte | byte* |
Float32 | float |
Float64 | double |
Int16 | short |
Int32 | int |
UInt16 | short* |
UInt32 | int* |
* the _Unsigned
attribute is set
Constructor Type | CDM DataType |
---|---|
Grid | Variable |
List | ignored |
Sequence | Structure(*) |
String | String or char |
Structure | Structure |
URL | ignored |
OPeNDAP Attributes
An OPeNDAP Attribute may be a name/value pair, or may contain other attributes, in which case it is called an attribute container.
Containers may be nested.
The CDM first matches OPeNDAP attribute containers against Variable
names.
On a match, the attributes become the Variable’s attributes.
Anything that doesn’t match is made into a global Variable
.
The CDM does not support nested attributes, so these are flattened by using a “.” to separate the container(s) from the name.
Certain OPeNDAP attribute containers are handled separately.
An attribute named NC_GLOBAL
or HDF_GLOBAL
is assumed to contain global attributes.
Attribute
containers named DODS_EXTRA
and EXTRA_DIMENSION
are handled as described in the next section.
OPeNDAP Dimensions
OPeNDAP (version 2) does not have explicit shared Dimensions
in its object model, except for Map
arrays inside of Grids
.
NetCDF has only shared Dimensions
, while the CDM data model allows for both shared and private (non-shared) Dimensions
.
A shared CDM Dimension
always has a name, while a private CDM Dimension
may or may not be named.
Unnamed OPeNDAP Dimensions
are mapped to anonymous (private, unnamed) CDM Dimensions
.
Named OPeNDAP Dimensions
are made into shared CDM Dimensions
, in the order they are found in the DDS
.
If a shared Dimension
with the same name already exists, and it has a different length, a named OPeNDAP Dimension
is made into a private, named CDM Dimension
.
Because DAP 2 doesn’t have Groups
, all shared Dimensions
will be global.
This effectively means that we assume that OPeNDAP Dimensions
of the same name and length are the same object.
In order to get the full semantics of NetCDF files transported across the OPeNDAP protocol, we use 2 special global attributes.
If there is a global attribute called DODS_EXTRA/Unlimited_Dimension
then the value of that attribute is assumed to be a Dimension
name, which is then set to be an Unlimited
Dimension
.
If there is a global attribute called EXTRA_DIMENSION
, then it contains one or more (name, length) attributes which are made into shared CDM Dimensions
.
This allows a server to pass Dimensions
which are not used in a Variable
, but conceivably might be needed by a client.
Here are examples of these two cases:
DODS_EXTRA { String Unlimited_Dimension record; }
DODS_EXTRA
and EXTRA_DIMENSION
are ad-hoc Conventions used only by the TDS as far as I know.
OPeNDAP Grids
An OPeNDAP Grid
object is decomposed into different Variables
for the data array and for each map vector in the Grid
.
The map vectors are placed at the global level, in the order they are found in the DDS
.
If a map vector already exists, then it is assumed to be identical with the existing one.
Dimensions
are currently not checked.
or both maps and arrays, the containing grid name is discarded.
These assumptions preserve the semantics of netCDF datasets, but are a violation of the OPeNDAP specification in which Grids
constitute a separate namespace.
Trying to preserve the namespace makes netCDF datasets incorrect.
This is one of the most important incompatibilities of the netCDF and OPeNDAP data models, since there is not workaround for DAP 2.
In order to preserve the semantics of the map vectors, the following CDM attribute is added to the data variable:
_Coordinate.Axes = "map1 map2 map3";
The CDM Coordinate System layer uses this to associate the array and map Variables, as intended by the Grid specification
OPeNDAP Strings
The default case is to map OPeNDAP Strings to CDM Strings.
If the Variable
has an attribute named DODS/strlen
, then the CDM instead uses DataType.CHAR
.
The value of the DODS/strlen
attribute is the length of the innermost dimension.
For example, an OPeNDAP String of dimension (5, 7) becomes a char Variable
of dimension (5,7,strlen).
If the Variable
has an attribute named DODS/dimName
, then dimName
becomes the dimension name of the inner Dimension
, otherwise the Dimension
is anonymous.
Some older OPeNDAP servers that read netCDF files map multidimensional char arrays to multidimensional String arrays, with each String being length 1.
As a workaround, the CDM reads the data for all String variables from an OPeNDAP dataset when the dataset is opened.
If it discovers that the data consists of Strings of length 1, it changes the Variable
dataType
to DataType.CHAR
.
In any case, we cache the String data on the client.
This workaround is reasonable as long as there isn’t huge amounts of String data in the dataset.
OPeNDAP Sequences
An OPeNDAP Sequence
is mapped to a one-dimensional CDM Structure
of variable length (uses Dimension.VLEN
).
The CDM now has a Sequence
class, but we have not yet converted the CDM opendap code to use it.
The semantics of both are the same, the user is only allowed to read the entire sequence (no subsetting).
In the general API (ie through the NetcdfFile
interface), constraint expressions are not supported .
However, a user could break encapsulation and call DODSNetcdfFile.readWithCE()
to read data with a relational constraint expression on a Sequence
.