GVRS Jump Start 04_Elements - gwlucastrig/gridfour GitHub Wiki

Introduction

The GvrsElement classes provide the primary access point for moving data in and out of a Gridfour Raster Data Store. In GVRS, the term element is used to describe the collection of individual data values assigned to each cell in a raster grid. Each cell in the grid is essentially a tuple consisting of one or more elements. Although these tuples may contain a mix of data types, the structure of the tuple is defined consistently across all grid cells.

The element-tuple structure is established when a GVRS data store is created. GVRS includes a family of element-specification classes that are used to define what elements are added to the data store (e.g. the GvrsFile object). When the GvrsFile is constructed, a related family of element-access classes is used to permit application code to read and write the data in the data store.

Currently, the GVRS raster elements support four data types:

  1. Signed short integers (16-bit integers in two's complement form)
  2. Signed integers (32-bit integers in two's complement form)
  3. Single-precision floating-point values (32-bit IEEE-754 standard)
  4. A hybrid integer-coded float type (floats scaled to integer values).

There is both a specification and an access class for each type. The structure of the two families of element classes is shown below. Note that each if the type-specific classes derives from a base class: GvrsElementSpecification for specifications and GvrsElement for access operations.

GVRS element hierarchy

Creating a multi-element data store

The previous article in this series showed how to create a GvrsFile containing a single element. The following code fragment provides an example of how we might create a GVRS specification containing three elements. The first, named "elevation", would give elevation above mean sea level. The second element, "accuracy", would give an estimated accuracy for each associated elevation value. And the third, "source", would give an integer value indicating a data source or processing method for the associated elevation value.

    GvrsElementSpecification zElv = new GvrsElementSpecificationFloat("elevation");
    GvrsElementSpecification zAcc = new GvrsElementSpecificationFloat("accuracy";
    GvrsElementSpecification zSrc = new GvrsElementSpecificationInt(  "source");

    GvrsFileSpecification fileSpec = new GvrsFileSpecification(1000, 1000);
    fileSpec.addElementSpecification(zElv);
    fileSpec.addElementSpecification(zAcc);
    fileSpec.addElementSpecification(zSrc);

    File javaFileReference = new File("Example.gvrs");
    GvrsFile gvrsFile      = new GvrsFile(javaFileReference, fileSpec);

    GvrsElement eElv = gvrsFile.getElement("elevation");
    GvrsElement eAcc = gvrsFile.getElement("accuracy");
    GvrsElement eSrc = gvrsFile.getElement("source");

Metadata for elements

Although the primary function of a GvrsElement instance is to transfer data between an application and the GVRS storage space, GvrsElement also provides a set of metadata properties. This metadata is intended to support operations related to the use, display, and interpretation of the elements with which they are associated.

In general, the GVRS API defines to categories of metadata:

  1. Functional metadata provides information to support data-processing operations
  2. Descriptive metadata provides information to support user-based operations including documentation, display, and report generation.

The metadata properties provided by GvrsElement classes are given in the table below.

Property Type Description
Name String (ASCII) Functional: A unique identifier that allows software to find and access elements
DataType GvrsElementType Functional: Indicates the kind of data stored in an element
Min, Max Value Numeric Functional: Indicates the range of values for an element
Fill Value Numeric Functional: The value assigned to data cells that are not otherwise populated
Label String (UTF-8) Descriptive: A unique identifier intended for user interfaces and reports
Description String (UTF-8) Descriptive: Free-form explanatory text
Unit of Measure String (ASCII) Descriptive, potentially functional: Unit of measure for data element

All the descriptive metadata properties listed in the table are optional. Minimum, maximum, and fill values are always available. Some applications may depend on the default values supplied by the GVRS API when elements are constructed.

As noted above, the numeric data types include signed short integers (16 bit integers), signed integers (32 bit integers), and single-precision floating-point values (32 bit, IEEE-754 standard floating point values). An additional, hybrid type called the integer-coded float is also available.

The element name

The name property serves as a kind of identifying key for a GVRS element. The previous articles in this Jump Start series showed examples of a name string being used to obtain a GvrsElement instance from a GvrsFile object. Because the name property is intended to be used by software, it uses a simple syntax based on a limited character set:

  1. Names begin with an ASCII letter (upper or lower case)
  2. Subsequent characters may be any combination of letters, digits, or underscores
  3. The maximum length of a name string is 32 characters.

The syntax for the name property is similar to that of identifiers used in most computer languages, though it is somewhat more restricted. This approach was taken to ensure portability across languages. For example, even though languages such as Java and C# permit the use of the underscore as the first character in a variable name, GVRS does not. The underscore cannot be used as a leading character because languages such as Python may assign special meanings to variables that have names starting with underscores. So, to support portability across languages, GVRS implements the rule that names begin with a letter. GVRS also sets the maximum length of names to a specific size, 32, to facilitate their use as attributes (fields) in relational database tables.

The element label and description properties

While the name property is intended for software, the label property is intended for human beings. Both are intended to be used as unique identifiers for data elements. But the text for a label can be whatever the products author chooses, in whatever language or character set he prefers. For practical purposes, it is usually better to use short strings for labels. But the GVRS API does not enforce any limit on their length.

The description property is intended to give somewhat longer explanatory text telling the user what the data in the associated element means or represents.

An expanded example

Let's expand the code example from above to include additional metadata elements, The GVRS API implements default values for the range-of-value and fill-value parameters, but they can also be established when a GvrsElementSpecification is constructed. In the example below, we will treat the element named "elevation" as giving elevation above mean sea level in meters. Elevations can range from nearly 11000 meters in the Challenger Deep to 8848.86 meters at the peak of Mount Everest. The fill value for elevation is set to "not a number" to indicate no-data values for non-populated raster cells. The element labels and descriptions are specified in Portuguese rather than English just to reinforce the idea that element names and labels are distinct parameters.


    GvrsElementSpecification zElv, zAcc, zSrc;

    zElv = new GvrsElementSpecificationFloat("elevation", -11000F, 8848.86F, Float.NaN);
    zAcc = new GvrsElementSpecificationFloat("accuracy",     -10F,   10F,    Float.NaN);
    zSrc = new GvrsElementSpecificationInt(  "source",         0,     5,     Integer.MIN_VALUE);

    zElv.setUnitOfMeasure("m"); // meters
    zAcc.setUnitOfMeasure("m"); // meters
    zSrc.setUnitOfMeasure("");  // unitless
    
    zElv.setLabel("Elevação");
    zElv.setDescription("Elevação em metros sobre o nível médio do mar");
    
    zAcc.setLabel("Exatidão");
    zSrc.setLabel("Origem ou método");
    
    GvrsFileSpecification fileSpec = new GvrsFileSpecification(1000, 1000);
    fileSpec.addElementSpecification(zElv);
    fileSpec.addElementSpecification(zAcc);
    fileSpec.addElementSpecification(zSrc);

    File javaFileReference = new File("Example.gvrs");
    GvrsFile gvrsFile      = new GvrsFile(javaFileReference, fileSpec);

What the "fill" value means

In practice, you may think of the fill value as playing two roles. Some applications may treat it as a "no-data" value. That was basically the implication in the example above. Other applications may treat it as a "default" value or something meaningful. For example, consider a raster data set that gives terrestrial elevation but treats all ocean locations as having "zero elevation". In such a case, a grid cell with a value of zero is not merely a default or no-data value. It actually provides information about the surface at the associated point.

Here's an example constructor for a terrestrial elevation data set:

zTerrain = new GvrsElementSpecificationShort("terrestrial_elevation",  0, 8848, 0); // min, max, fill

At present, the GVRS API does not implement a specific feature to indicate how a product's author intends the fill value to be used. In practice, I find that if the fill value falls within the range of values (minimum and maximum values), it is intended to be a meaningful value. If the fill value is out of the valid range, it is intended to indicate a "no-data" point.

Future work on the unit of measure specification

At present, the GVRS API does not enforce any particular syntax for unit of measure specifications. In order to ensure the greatest potential usefulness and protability of your data, you would do well to always specify units of measure in internationally accepted standards. The ideal way to do this would be through a dedicated API such as the Java Units of Measurement API (JSR 385).

One of the guiding principles in the implementation of the Gridfour Core library (of which GVRS is a part) is that it does not introduce 3rd party software dependencies beyond the standard Java API. However, in future work on the Gridfour Demo library, we may include examples that apply the Units of Measure API to illustrate its use.

Conclusion

In application code, GvrsElements do double duty. They provide a way of accessing data, and they provide a way of indicating how that data can be used. Additional details on the use of elements is available through the Javadoc included with the Gridfour source code.