The Dataset Attribute Structure (DAS) is used to store attributes for variables in the dataset. An attribute is any piece of information about a variable that the creator wants to bind with that variable excluding the type and shape, which are part of the DDS. Attributes can be as simple as error measurements or as elaborate as text describing how the data was collected or processed21. In principle, attributes are not processed by software, other than to be displayed. However, many systems rely on attributes to store extra information that is necessary to perform certain manipulations of data. In effect, attributes are used to store information that is used `by convention' rather than `by design'. OPeNDAP can effectively support these conventions by passing the attributes from data set to user program via the DAS. Of course, OPeNDAP cannot enforce conventions in datasets where they were not followed in the first place.
Similarly to the DDS, the actual location of the DAS storage will vary from one API to another. Data files created with some APIs will contain within themselves attribute information that can be contained in the DAS. For these APIs, the DAS will be constructed dynamically by the OPeNDAP server from data within the files.
Other data access APIs must have attribute information specified in an
ancillary data file. APIs that contain attribute information
can have that information enriched by the addition of these ancillary
attribute files. These files are typically stored in the same
directory as the data files, and given the same name as the data
files, appended with .das.
The syntax for attributes in a DAS is given in table 6.4.2. Every attribute of a variable is a triple: attribute name, type and value. Note that the attributes specified using the DAS are different from the information contained in the DDS. Each attribute is completely distinct from the name, type, and value of its associated variable. The name of an attribute is an identifier, following the normal rules for an identifier in a programming language with the addition that the `/' character may be used. The type of an attribute may be one of: Byte, Int32, UInt32, Float64, String or Url. An attribute may be scalar or vector. In the latter case the values of the vector are separated by commas (,) in the textual representation of the DAS.
|
DAS | Attributes { var-attr-list
} |
|
var-attr-list | var-attr |
| var-attr-list var-attr | |
| (empty list) | |
|
var-attr | variable
{ attr-list } |
container { var-attr-list
} | |
| global-attr | |
| alias | |
|
global-attr | Global variable
{ attr-list } |
|
attr-list | attr-triple ; |
| attr-list attr-triple | |
| (empty list) | |
|
attr-triple | attr-type attribute attr-val-vec
; |
|
attr-val-vec | attr-val |
attr-val-vec , attr-val | |
|
attr-val | numeric value |
| variable | |
| "string" | |
|
attr-type | Byte |
Int32 | |
UInt32 | |
Float64 | |
String | |
Url | |
|
alias | Alias alias-name variable ; |
|
variable | user-chosen variable name |
|
attribute | user-chosen attribute name |
|
container | user-chosen container name |
|
alias-name | user-chosen alias name |
When creating a DAS to be kept in an ancillary file, you can use the
# character as a comment indicator. All characters after the
# on a line are ignored.
An attribute can contain another attribute, or set of attributes. This is roughly comparable to the way compound variables can contain other variables in the DDS. The container defines a new lexical scope for the attributes it contains22.
Consider the following example:
Attributes {
Bill {
String LastName "Evans";
Byte Age 53;
String DaughterName "Matilda";
Matilda {
String LastName "Fink";
Byte Age 26;
}
}
}
Here, the attribute Bill.LastName would be associated with the
string "Evans", and Bill.Age with the number 53. However, the
attribute Bill.Matilda.LastName would be associated with the
string "Fink" and Bill.Matilda.Age with the number 26.
Using container attributes as above, you can construct a DAS that
exactly mirrors the construction of a DDS that uses compound data
types, like Structure and Sequence. Note that though
the Bill attribute is a container, it has attributes of its own,
as well. This exactly corresponds to the situation where, for
example, a Sequence would have attributes belonging to it, as
well as attributes for each of its member variables. Suppose the
sequence represented a single time series of measurements, where
several different data types are measured at each time. The sequence
attributes might be the time and location of the measurements, and the
individual variables might have attributes describing the method or
accuracy of that measurement.
Building on the previous example, it might be true that it would be
convenient to refer to Matilda without prefixing every reference with
Bill. In this case, we can define an alias attribute
as follows:
Attributes {
Bill {
String LastName "Evans";
Byte Age 53;
String DaughterName "Matilda";
Matilda {
String LastName "Fink";
Byte Age 26;
}
}
Alias Matilda Bill.Matilda;
}
By defining an equivalence between the alias Matilda and the
original attribute Bill.Matilda, the string Matilda.Age
can be used with or without the prefix Bill. In either case,
the attribute value will be 26.
A global attribute is not bound to a
particular identifier in a dataset; these attributes are stored in one
or more containers with the name Global or ending with
_Global. Global attributes are used to describe attributes of
an entire dataset. For example, a global attribute might contain the
name of the satellite or ship from which the data was collected.
Here's an example:
Attributes {
Bill {
String LastName "Evans";
Byte Age 53;
String DaughterName "Matilda";
Matilda {
String LastName "Fink";
Byte Age 26;
}
}
Alias Matilda Bill.Matilda;
Global {
String Name "FamilyData";
String DateCompiled "11/17/98";
}
}
Global attributes can be used to define a certain view of a dataset. For example, consider the following DAS:
Attributes {
CTD {
String Ship "Oceanus";
Temp {
String Name "Temperature";
}
Salt {
String Name "Salinity";
}
}
Global {
String Names "OPeNDAP";
}
FNO_Global {
String Names "FNO";
CTD {
Temp {
String FNOName "TEMPERATURE";
}
Salinity {
String FNOName "SALINITY";
}
}
Alias T CTD.Temp;
Alias S CTD.Salt;
}
}
Here, a dataset contains temperature and salinity measurements. To
aid processing of this dataset by some OPeNDAP client, long names are
supplied for the Temp and Salt variables. However, a
different client (FNO) spells variable names differently. Since it is
seldom practical to come up with general-purpose translation
tables23, the dataset administrator has chosen to include
these synonyms under the FNO_Global attributes, as a convenience
to those users.
Similar conveniences can be provided using the Alias feature. In the
example in figure 6.4.2, the temperature variable
can be referred to as FNO_Global.T if desired. That is, a
global alias can provide a client with a known attribute name to query
for some property, even if that attribute name is not an integral part
of the dataset.
Using global attributes, a dataset or catalog administrator can create a layer of aliases and attributes to make OPeNDAP datasets conform to several different dataset naming standards. This becomes significant when trying to compile an OPeNDAP dataset database.