Release Notes
**New Features:**
- `Grib2Message` creation from "scratch" (i.e. not read from an existing file). The logic to create a GRIB2 message remains largely the same from grib2io's predecessor, [ncepgrib2](https://github.com/jswhit/ncepgrib2). However, with `grib2io`, the creation of a new GRIB2 message is done through instantiation of the `grib2io.Grib2Message` class. When the class is instantiated with appropriate values to the keyword arguments `discipline` and `idsect`, an empty instance of `Grib2Message` is created. Then you call `Grib2Message` methods: `addgrid()` to add the grid definition section; `addfield()` to add the production definition, data representation, bitmap, and data sections; and finally `end()` to formally end the GRIB2 message.
- Write GRIB2 message to file. Class `grib2io.open` now contains a `write()` method that accepts a `Grib2Message` object.
- Decode GRIB2 messages that contain MDL (Gridded MOS) and NDFD Weather Strings. The gridded data are integer values that represent an index of a lookup table that contain weather strings. The lookup table is unique for each GRIB2 message and is stored in section 2 (Local Use Section) of each message. New functions, `utils.decode_mdl_wx_strings()` and `utils.decode_ndfd_wx_strings()` have been created to perform the decoding of the lookup tables. Different functions are required because the decoding is slightly different between MDL and NDFD. To decode weather strings while unpacking data, provide `Grib2Message.data()` method with the `map_keys=True` keyword argument.
- GRIB2 metadata attributes of the `Grib2Message` can now hold their coded integer value ***and*** the plain language defintion for that value. Where necessary, `Grib2Message` object attributes will be of type `Grib2Metadata` which stores the code value in `value` and the plain language definition in `definition`. See the following example using the `Grib2Message.discipline`:
python
>>> import grib2io
>>> g = grib2io.open('test.grib2')
>>> msg = g[50][0] Get the 50th GRIB2 message
>>> type(msg.discipline)
<class 'grib2io._grib2io.Grib2Metadata'>
>>> msg.discipline.value
0
>>> msg.discipline.definition
'Meteorological Products'
>>> msg.discipline == 0
True
>>> 'Met' in msg.discipline.definition
True
>>> print(msg.discipline)
0 - Meteorological Products
>>> msg.discipline()
0
**Class Updates:**
`grib2io.Grib2Message`
- new method, `unpack()`. This method handles the unpacking of the binary data from the GRIB2 message and creates the GRIB2 section values.
- new method, `decode()`. This method performs the decoding of packed GRIB2 values from each section into metadata variables (i.e. instance variables of `Grib2Message`). Where available, the code values are futher deciphered into their plain language defintions. Both the code value its definition are stored as an instance of class `Grib2Metadata`.
- new method, `addgrid()`. Adds Grid Definition Section information.
- new method, `addfield()`. Adds the Production Definition, Data Representation, Bitmap, and Data Sections.
- new method, `end()`. Add the End Section. This formally terminates the packed GRIB2 message.
- updated `__init__` to accommodate `discipline` and `idsect` keyword arguments (both have the default value of `None`). When both of these are specified ***and are not*** `None`, an empty `Grib2Message` object is created. ***NOTE: all other keyword arguments are ignored.***
- updated `data()` to add `map_keys` keyword for decoding data values to MDL or NDFD Wx Strings.
`grib2io.Grib2Metadata` ***(NEW)***
- New class to store decoded GRIB2 metadata as the coded value in instance vairable `value` and its plain language definition in instance variable `definition`.
- Class comparison methods use the `value` attribute. For `__contains__`, the `definition` atrribute is used. For `__call__`, `value` is returned.
**Changes:**
- Renamed `utils.get_varname_from_table()` to `utils.get_varinfo_from_table()`.
- `utils.get_table()` now returns an empty dictionary when the specified table is not found.
- `utils.get_value_from_table()` now returns `['Unknown','Unknown','Unknown']` when a value from a table is not found.
- Updates to docstrings
- NCEP GRIB2 tables updated to latest as of 8/31/2021. Logic added to table generation scripts to remove "(See Note *)" strings.
- Included [NCEP G2C](https://github.com/NOAA-EMC/NCEPLIBS-g2c) Library updated to verison 1.6.2.
**Bug Fixes:**
- Set ONE_MB to the correct value representing 1 MB in units of bytes.
- Fixed issues with decoding metadata for GRIB2 messages with production definition template number = 9.