Iris-grib Load and Save API

In addition to direct load and save with Iris, as described above, it is also possible to load and save GRIB data using iris-grib functions.

Note

The API here is for special cases. It is usually simplest to load and save GRIB data using the regular iris load and save functions, as described at Simple GRIB Loading and Saving with Iris.

Loading and saving Cubes

Load

To load from a GRIB file with iris-grib, you can call the load_cubes() function :

>>> cubes_iter = iris_grib.load_cubes('testfile.grib')
>>> print(cubes_iter)
<generator object load_cubes at ...>

As we can see, this returns a generator object. The generator object may be iterated over to access all the Iris cubes loaded from the GRIB file, or converted directly to a list:

>>> cubes = list(cubes_iter)
>>> print(cubes)
[<iris 'Cube' of air_temperature / (K) (projection_y_coordinate: 200; projection_x_coordinate: 247)>]

In effect, this is the same as using iris.load_raw(...). So, in most cases, that is preferable.

Save

To use iris-grib to save Iris cubes to a GRIB file we can make use of the save_grib2() function :

>>> iris_grib.save_grib2(cube, 'my_file.grib2')

In effect, this is the same as using iris.save(cube, ...). So, in most cases, that is preferable.

Working with GRIB messages

Iris-grib also provides lower-level functions which allow the user to inspect and adjust actual GRIB encoding details, for precise custom control of loading and saving.

These functions use intermediate objects which represent individual GRIB file “messages”, with all the GRIB metadata.

For example:

  • correct loading of some messages with incorrectly encoded parameter number

  • save messages with adjusted parameter encodings

  • load messages with an unsupported parameter definition template : adjust them to mimic a similar type which is supported by cube translation, and post-modify the resulting cubes to correct the Iris metadata

You can load and save messages to and from files, and convert them to and from Cubes.

Note

at present this only works with GRIB2 data.

Note

Messages are not represented in the same way for loading and saving : the messages generated by loading from files are represented by iris_grib.message.GribMessage objects, whereas messages generated from cubes, for saving to files, are represented as message handles from the Python eccodes library .

Load

The key functions are load_pairs_from_fields() and messages_from_filename(). See those for more detail.

You can load data to ‘messages’, and filter or modify them to enable or correct how Iris converts them to ‘raw’ cubes (i.e. individual 2-dimensional fields).

Caution

Remember: modifying a GribMessage does NOT modify the underlying GRIB file.

For example:

>>> from iris_grib.message import GribMessage
>>> fields_iter = GribMessage.messages_from_filename('testfile.grib')
>>> # select only wanted data
>>> selected_fields = [
...   field
...   for field in fields_iter
...   if field.sections[4]['parameterNumber'] == 33
... ]
>>> cube_field_pairs = iris_grib.load_pairs_from_fields(selected_fields)

Filtering fields can be very useful to speed up loading, since otherwise all data must be converted to Iris before selection with constraints, which can be quite costly.

See also: How to modify GRIB content during loading.

Save

The key functions are save_pairs_from_cubes() and save_messages(). See those for more detail.

You can convert Iris cubes to eccodes messages, and modify or filter them before saving.

Note

The messages here are eccodes message “ids”, essentially integers, and not GribMessages. Thus, they must be inspected and manipulated using the eccodes library functions.

For example:

>>> # translate data to grib2 fields
>>> cube_field_pairs = list(iris_grib.save_pairs_from_cube(cube_height_2m5))
>>> # adjust some of them
>>> for cube, field in cube_field_pairs:
...   if cube.coords('height') and cube.coord('height').points[0] == 2.5:
...     # we know this will have been rounded, badly, so needs re-scaling.
...     assert eccodes.codes_get_long(field, 'scaleFactorOfFirstFixedSurface') == 0
...     assert eccodes.codes_get_long(field, 'scaledValueOfFirstFixedSurface') == 2
...     eccodes.codes_set_long(field, 'scaleFactorOfFirstFixedSurface', 1)
...     eccodes.codes_set_long(field, 'scaledValueOfFirstFixedSurface', 25)
...
>>> # save to file
>>> messages = [msg for (cube, msg) in cube_field_pairs]
>>> iris_grib.save_messages(messages, 'temp.grib2')
>>> # check result
>>> print(iris.load_cube('temp.grib2').coord('height').points)
[2.5]