Constructor types, such as arrays, structures, and lists, describe the grouping of one or more variables within a dataset. These classes are used to describe different types of relations between the variables that comprise the dataset. For example, an array might indicate that the variables grouped are all measurements of the same quantity with some spatial relation to one another, whereas a structure might indicate a grouping of measurements of disparate quantities that happened at the same place and time.
There are six classes of type constructor variables defined by the OPeNDAP DAP: lists, arrays, structures, sequences, functions, and grids. The types are defined as:
list before the variable's class, for example,
list int32 or list grid. Access to the elements of a
list is possible using one of the three operators shown in
table 6.3.3:
length Returns the integer length of the
list.
nth(n) Returns the nth member of
the list.
member(value) Returns true if
the value is a member of the list.
NOTE: The syntax of these operators differs between their use in a
C++ program and a constraint expression. The length of some list,
given by list.length() in a program, would be
length(list) in a constraint expression. Similarly, in a
constraint expression, the position of a value in a list is given
by nth(list, value), and the presence of a value is
indicated by member(list, value). See
Section 4.1 for more information about
constraint expressions.
A list declaration to create a list of integers would look like the following:
List Int32 months;
()).
For example, temp[3][4] would indicate the value in the fourth
row and fifth column of the temp array.17 A chunk of an array may be specified
with subscript ranges; the array temp[2:10][3:4] indicates an
array of nine rows and two columns whose values have been lifted
intact from the larger temp array.
A hyperslab may be selected from an
array with a stride value. The array
represented by temp[2:2:10][3:4] would have only five rows;
the middle value in the first subscript range indicates that the
output array values are to be selected from alternate input array
rows. The array temp[2:3:10][3:4] would select from every
third row, and so on. table 6.3.3 shows the syntax
for array accesses including hyperslabs.
To declare a 5x6 array of floating point numbers, the declaration would look like the following:
Float64 data[5][6];
In addition to its magnitude, every dimension of an array may also have a name. The previous declaration could be written:
Float64 data[height = 5][width = 6];
A Structure declaration containing some data and the month in which the data was taken might look like this:
Structure {
Int32 month;
Float64 data[5][6];
} measurement;
Use the . operator to refer to members of a Structure. For
example, measurement.month would identify the integer member of
the Structure defined in the above declaration.
s_0 0 . s_0 n . . . s_i 0 . s_i n
Every instance of sequence S has the same number, order, and class of member variables. A Sequence implies that each of the variables is related to each other in some logical way. For example, a sequence containing position and temperature measurements might imply that the temperature measurements were taken at the corresponding position. A sequence is different from a structure because its constituent variables have several instances while a structure's variables have only one instance (or value). Because a sequence has several values for each of its variables it has an implied state, in addition to those values. The state corresponds to a single element in the sequence.
A Sequence declaration is similar to a Structure's. For example, the following would define a Sequence that would contain many members like the Structure defined above:
Sequence {
Int32 month;
Float64 data[5][6];
} measurement;
Note that, unlike an Array, a Sequence has
no index. This means that a Sequence's values are not
simultaneously accessible. Like a Structure, the variable
measurement.month has a single value. The distinction is that
this variable's value changes depending on the state of the
Sequence.
As an example, consider an array of temperature values that is six columns wide by five rows long. Suppose that this array represents measurements of temperature at five different depths in six different locations. The problem is the indication of the precise location of each temperature measurement, relative to one another.18
If the six locations are evenly spaced, and the five depths are also evenly spaced, then the data set can be completely described using the array and two scalar values indicating the distance between adjacent vertices of the array. However, if the spacing of the measurements is not regular, as in figure 6.3.2 then an array will be inadequate. To adequately describe the positions of each of the points in the grid, the precise location of each volume and row must be described.
Grid {
Float64 data[distance = 6][depth = 5];
Float64 distance[6];
Float64 depth[5];
} measurement;
In the above example, an vector called depth would contain five
values corresponding to the depths of each row of the array, while
another vector called distance might contain the scalar distance
between the location of the corresponding column, and some reference
point. The distance array could also contain six (latitude,
longitude) pairs indicating the absolute location of each column of
the grid.
Grid {
Float64 data[distance = 6][depth = 5];
Float64 depth[5];
Array Structure {
Float64 latitude;
Float64 longitude;
} distance[6];
} measurement;