1 of 11

python-bufr

Generic BUFR file reader in python

2 of 11

What does it do?

  • Reads BUFR files in python
  • Provides a framework for generic BUFR to NetCDF conversion

3 of 11

Depends on / requires

  • BUFR reading
    • ECMWF BUFR library
    • numpy
  • BUFR NetCDF conversion
    • sqlalchemy
    • netCDF4

4 of 11

How does it work?

  • Wrapper in C around ECMWF library
  • Provides basic types:
    • The BUFRFile class as the main file container. Supports iterator interface for reading data
    • The BUFRFileEntry class as the standard data container. Provides the following attributes:
      • name (variable name, e.g SATELLITE IDENTIFIER)
      • unit (data unit)
      • data (data as numpy array)
      • index (Index in the BUFR subsection)

5 of 11

How does it work?

>>> TESTFILE = "./sample_data/iasi_20120206_190254_metopa_27506_eps_o_clp.l2_bufr"�>>> import bufr�>>> import numpy as np�>>> bfr = bufr.BUFRFile(TESTFILE)

6 of 11

How does it work...

>>> nxt = bfr.next()�>>> print [ s.name for s in nxt ]

'SATELLITE IDENTIFIER ',� 'IDENTIFICATION OF ORIGINATING/GENERATING CENTRE (SEE NOTE 10) ',� 'SATELLITE INSTRUMENTS ',� 'SATELLITE CLASSIFICATION ',� 'YEAR ',� 'MONTH ',�...�'HEIGHT OF STATION (SEE NOTE 1) ',�'VERTICAL SIGNIFICANCE (SATELLITE OBSERVATIONS) ',�'PRESSURE ',

...

>>> print nxt[32].name�'PRESSURE '

7 of 11

How does it work...

>>> bfr = bufr.BUFRFile(TESTFILE)�>>> lon = []�>>> lat = []�>>> pres = []�>>> for record in bfr:�>>> for entry in record:�>>> if entry.index == 32:�>>> pres.append(entry.data)�>>> if entry.name.find("LONGITUDE") == 0:�>>> lon.append(entry.data)�>>> if entry.name.find("LATITUDE") == 0:�>>> lat.append(entry.data)�>>> lons = np.concatenate(lon)�>>> lats = np.concatenate(lat)�>>> pres = np.concatenate(pres) / 100.0 # hPa�>>> pres = np.ma.masked_greater(pres, 1.0e+6)

8 of 11

Let's do something with the data

>>> import pyresample as pr

>>> from pyresample import kd_tree, geometry

>>> from pyresample import utils

>>> swath_def = geometry.SwathDefinition(lons=lons, lats=lats)

>>> area_def = utils.parse_area_file('./region_config.cfg', 'scan2')[0]

9 of 11

Let's do something with the data

>>> result = kd_tree.resample_nearest(swath_def, pres,

area_def,

radius_of_influence=12000,

epsilon=100,

fill_value=None)

>>> pr.plot.save_quicklook('/tmp/iasi_ctp_quick.png',

area_def, result, label='IASI - Cloud Top Pressure',

coast_res = 'h')

10 of 11

Let's do something with the data

Remapped IASI lvl2 Pressure

11 of 11

Status

  • Stable and in operation at DMI

  • TODO:
    • Improve performance
    • More robust NetCDF conversion, related to different BUFR data layouts.
      • Satellite data can be stored in the BUFR files ordered by either field of view or by scanline.