# CODA GRIB Mapping Description

CODA provides access to GRIB-1 and GRIB-2 formatted data by creating a view on the GRIB files using the CODA data types. Below we will describe how CODA maps the GRIB1/GRIB2 product structure to one that is based on the CODA data types. We assume you already have a decent understanding of the GRIB (edition 1 and 2) format and its details.

A file can contain one or more GRIB messages. CODA only supports files where GRIB messages are stored without any padding between the messages and where the file does not contain any non-GRIB header or footer information in the file. A file can contain a mix of messages with different GRIB edition numbers.

Since a file consists of a list of messages the root of the product is mapped to an array of union with each message being mapped to a union. The fields in the union reflect the edition number of the GRIB message and are called grib1 and grib2 (only one of the fields will be available, depending on the edition number of the GRIB message). The grib1 and grib2 fields contain record types for a GRIB1 and GRIB2 message respectively. The mapping for each is explained below.

CODA will try to provide as direct a mapping to the underlying data as possible. This means that code table indices will just be provided as indices and not be interpreted. You will have to consult the appropriate WMO code tables in order to interpret the data. The reason for this design choice was to eliminate as much as possible the dependency of CODA on the WMO tables. For certain structural information (such as the contents of the Grid Description Section or Product Definition Section) table information has been hard-coded in CODA.

There are a few exceptions to the 'direct mapping' approach. One is that CODA will already perform the decoding of the parameter values. The bit-packed data is already converted back to floating point values using the scale factors and reference value as described by the GRIB standard. The scale factors and reference values are still made accessible as fields in the GRIB message record, but they have the hidden property, since you should not need them to interpret the values that CODA will give back.

CODA will also perform the decoding of bitmap packed data (using the Bit Map Section). The data available in data/values[] will thus always contain the full grid, where missing grid points are given the 'referenceValue' as value.

In addition, for GRIB1, any IBM floating point values will be converted to IEEE754 floating point values.

CODA currently only supports to most common storage mechanism of GRIB which is the simple packing form. Data that is stored using complex packing or jpeg/png images is not supported. Also, CODA currently only supports grid definitions that use a lat/lon or Gaussian grid. Other grids, including Spherical Harmonic data, are currently not supported. If an unsupported feature is encountered, CODA will abort opening the product and return with an error.

## GRIB1

A GRIB1 message consists of the following sections:

- (0) Indicator Section
- (1) Product Definition Section (PDS)
- (2) Grid Description Section (GDS) - optional
- (3) Bit Map Section (BMS) - optional
- (4) Binary Data Section (BDS)
- (5) '7777' (ASCII Characters)

The contents of the PDS are mapped directly as fields in the message record, but for the GDS and BDS sections separate sub-records are used. The Indicator, BMS, and '7777' sections are not mapped.

For the naming of fields CODA tries to stay as close as possible to the naming scheme that is used by the ECMWF GRIB API software.

The following table gives the list of parameters that are available via CODA for a GRIB1 message:

path to variable | type class | read type | notes
--- | --- | --- | ---
/[]/grib1/editionNumber | integer | uint8 |
/[]/grib1/table2Version | integer | uint8 |
/[]/grib1/centre | integer | uint8 |
/[]/grib1/generatingProcessIdentifier | integer | uint8 |
/[]/grib1/gridDefinition | integer | uint8 |
/[]/grib1/indicatorOfParameter | integer | uint8 |
/[]/grib1/indicatorOfTypeOfLevel | integer | uint8 |
/[]/grib1/level | integer | uint16 |
/[]/grib1/yearOfCentury | integer | uint8 |
/[]/grib1/month | integer | uint8 |
/[]/grib1/day | integer | uint8 |
/[]/grib1/hour | integer | uint8 |
/[]/grib1/minute | integer | uint8 |
/[]/grib1/unitOfTimeRange | integer | uint8 |
/[]/grib1/P1 | integer | uint8 |
/[]/grib1/P2 | integer | uint8 |
/[]/grib1/timeRangeIndicator | integer | uint8 |
/[]/grib1/numberIncludedInAverage | integer | uint16 |
/[]/grib1/numberMissingFromAveragesOrAccumulations | integer | uint8 |
/[]/grib1/centuryOfReferenceTimeOfData | integer | uint8 |
/[]/grib1/decimalScaleFactor | integer | uint8 |
/[]/grib1/subCentre | integer | int16 | (hidden field)
/[]/grib1/local | raw | bytes | optional; the originating center specific data at the end of the PDS is made available as raw data via this field if it is available
/[]/grib1/grid/numberOfVerticalCoordinateValues | integer | uint8 |
/[]/grib1/grid/dataRepresentationType | integer | uint8 |
/[]/grib1/grid/Ni | integer | uint16 |
/[]/grib1/grid/Nj | integer | uint16 |
/[]/grib1/grid/latitudeOfFirstGridPoint | integer | int32 |
/[]/grib1/grid/longitudeOfFirstGridPoint | integer | int32 |
/[]/grib1/grid/resolutionAndComponentFlags | integer | uint8 |
/[]/grib1/grid/latitudeOfLastGridPoint | integer | int32 |
/[]/grib1/grid/longitudeOfLastGridPoint | integer | int32 |
/[]/grib1/grid/iDirectionIncrement | integer | int16 |
/[]/grib1/grid/jDirectionIncrement | integer | int16 | optional
/[]/grib1/grid/N | integer | int16 | optional
/[]/grib1/grid/scanningMode | integer | uint8 |
/[]/grib1/grid/coordinateValues[] | real | float | optional
/[]/grib1/grid/listOfNumbers[] | integer | uint16 | optional
/[]/grib1/data/bitsPerValue | integer | uint8 | (hidden field)
/[]/grib1/data/binaryScaleFactor | integer | int16 | (hidden field)
/[]/grib1/data/referenceValue | real | float | (hidden field)
/[]/grib1/data/values[] | real | float |

## GRIB2

A GRIB2 message consists of the following sections:

- (0) Indicator Section
- (1) Identification Section
- (2) Local Use Section - optional
- (3) Grid Definition Section
- (4) Product Definition Section
- (5) Data Representation Section
- (6) Bit-Map Section
- (7) Data Section
- (8) End Section

Within a message, sequences 3-7, 4-7, and/or 5-7 can be repeated several times.

The contents of the Identification Section are mapped directly as fields in the message record. For the Local Use, Grid Definition, and Data Sections special 'local', 'grid', and 'data' fields are available, with each being an array of the contents of each occurence of the section. Each 'data' record will contain a 0-based index into the 'grid' array to reference the applicable grid for the parameter. Similary, for each 'grid' record a 0-based index into the 'local' array will be available. The visible content of the Product Definition and Data Representation Section are available in the 'data' record of the associated Data Section (Product Definition Section information can thus end up appearing replicated).

As for GRIB1, for the naming of fields, CODA tries to stay as close as possible to the naming scheme that is used by the ECMWF GRIB API software.

The following table gives the list of parameters that are available via CODA for a GRIB2 message:

path to variable | type class | read type | notes
--- | --- | --- | ---
/[]/grib2/editionNumber | integer | uint8 |
/[]/grib2/discipline | integer | uint8 |
/[]/grib2/centre | integer | uint16 |
/[]/grib2/subCentre | integer | uint16 |
/[]/grib2/masterTablesVersion | integer | uint8 |
/[]/grib2/localTablesVersion | integer | uint8 |
/[]/grib2/significanceOfReferenceTime | integer | uint8 |
/[]/grib2/year | integer | uint16 |
/[]/grib2/month | integer | uint8 |
/[]/grib2/day | integer | uint8 |
/[]/grib2/hour | integer | uint8 |
/[]/grib2/minute | integer | uint8 |
/[]/grib2/second | integer | uint8 |
/[]/grib2/productionStatusOfProcessedData | integer | uint8 |
/[]/grib2/typeOfProcessedData | integer | uint8 |
/[]/grib2/local[] | raw | bytes |
/[]/grib2/grid[]/localRecordIndex | integer | int32 | index into /[]/local[] to find associated local use data. Will be -1 if no local use data is available
/[]/grib2/grid[]/sourceOfGridDefinition | integer | uint8 |
/[]/grib2/grid[]/numberOfDataPoints | integer | uint32 |
/[]/grib2/grid[]/interpretationOfListOfNumbers | integer | uint8 |
/[]/grib2/grid[]/gridDefinitionTemplateNumber | integer | uint16 |
/[]/grib2/grid[]/shapeOfTheEarth | integer | uint8 |
/[]/grib2/grid[]/scaleFactorOfRadiusOfSphericalEarth | integer | uint8 |
/[]/grib2/grid[]/scaledValueOfRadiusOfSphericalEarth | integer | uint32 |
/[]/grib2/grid[]/scaleFactorOfEarthMajorAxis | integer | uint8 |
/[]/grib2/grid[]/scaledValueOfEarthMajorAxis | integer | uint32 |
/[]/grib2/grid[]/scaleFactorOfEarthMinorAxis | integer | uint8 |
/[]/grib2/grid[]/scaledValueOfEarthMinorAxis | integer | uint32 |
/[]/grib2/grid[]/Ni | integer | uint32 |
/[]/grib2/grid[]/Nj | integer | uint32 |
/[]/grib2/grid[]/basicAngleOfTheInitialProductionDomain | integer | uint32 |
/[]/grib2/grid[]/subdivisionsOfBasicAngle | integer | uint32 |
/[]/grib2/grid[]/latitudeOfFirstGridPoint | integer | int32 |
/[]/grib2/grid[]/longitudeOfFirstGridPoint | integer | int32 |
/[]/grib2/grid[]/resolutionAndComponentFlags | integer | uint8 |
/[]/grib2/grid[]/latitudeOfLastGridPoint | integer | int32 |
/[]/grib2/grid[]/longitudeOfLastGridPoint | integer | int32 |
/[]/grib2/grid[]/iDirectionIncrement | integer | uint32 |
/[]/grib2/grid[]/jDirectionIncrement | integer | uint32 | optional
/[]/grib2/grid[]/N | integer | uint32 | optional
/[]/grib2/grid[]/scanningMode | integer | uint8 |
/[]/grib2/grid[]/listOfNumbers | integer | uint32 | optional
/[]/grib2/data[]/gridRecordIndex | integer | uint32 | index into /[]/grid[] to find associated grid definition data
/[]/grib2/data[]/parameterCategory | integer | uint8 |
/[]/grib2/data[]/parameterNumber | integer | uint8 |
/[]/grib2/data[]/typeOfGeneratingProcess | integer | uint8 |
/[]/grib2/data[]/backgroundProcess | integer | uint8 |
/[]/grib2/data[]/generatingProcessIdentifier | integer | uint8 |
/[]/grib2/data[]/hoursAfterDataCutoff | integer | uint16 |
/[]/grib2/data[]/minutesAfterDataCutoff | integer | uint8 |
/[]/grib2/data[]/indicatorOfUnitOfTimeRange | integer | uint8 |
/[]/grib2/data[]/forecastTime | integer | uint32 |
/[]/grib2/data[]/typeOfFirstFixedSurface | integer | uint8 |
/[]/grib2/data[]/firstFixedSurface | real | double |
/[]/grib2/data[]/typeOfSecondFixedSurface | integer | uint8 |
/[]/grib2/data[]/secondFixedSurface | real | double |
/[]/grib2/data[]/coordinateValues[] | real | float | optional
/[]/grib2/data[]/bitsPerValue | integer | uint8 | (hidden field)
/[]/grib2/data[]/decimalScaleFactor | integer | int16 | (hidden field)
/[]/grib2/data[]/binaryScaleFactor | integer | int16 | (hidden field)
/[]/grib2/data[]/referenceValue | real | float | (hidden field)
/[]/grib2/data[]/values[] | real | float |