Memory Buffers¶
wgrib2 C API has an unorthodox design. Usually, libraries are written
first, executables call functions from those libraries. In case of wgrib2,
the C main
functions was made a library function. As a consequence,
all arguments must be strings. Data returned by wgrib2
is written to
memory buffers. The API provides methods to read those buffers. wgrib2
can also process data written to memory buffers by the client application.
There can be up to 30 distinct memory buffers (and 20 RPN registers, used
to pass calculated data, those are also chunks of memory). The buffers are
identifiable by a number.
In order to free the library user from keeping track of those numbers,
pywgrib2_xr
has its own classes MemoryBuffer
and RPNRegister
that shadow their wgrib2
counterparts.
Instantiating a class retrieves available number from a pool, calling
close()
returns buffer number
to the pool. It does not free allocated memory. Closing the buffer can
also be achieved by using the with
construct.
Examples:
Create a short inventory of a GRIB2 file in memory, then print it.
import pywgrib2_xr as pywgrib2 from pywgrib2_xr.utils import localpath file = localpath('CMC_glb_TMP_ISBL_850_ps30km_2020012500_P000.grib2') with pywgrib2.MemoryBuffer() as buf: args = [file, '-inv', buf] pywgrib2.wgrib(*args) inv = buf.get('s') print(inv)
1:0:d=2020012500:TMP:850 mb:anl:
Here, the argument 's'
in a call to buf.get()
means the returned data should
be a string.
Read values and geolocation data into
numpy
arrays.
import pywgrib2_xr as pywgrib2 from pywgrib2_xr.utils import localpath from contextlib import ExitStack file = localpath('CMC_glb_ps30km_2020012512.grib2') with ExitStack() as stack: data_reg = stack.enter_context(pywgrib2.RPNRegister()) lon_reg = stack.enter_context(pywgrib2.RPNRegister()) lat_reg = stack.enter_context(pywgrib2.RPNRegister()) inv_buf = stack.enter_context(pywgrib2.MemoryBuffer()) args = [file, '-rewind_init', file, '-d', 3, '-inv', inv_buf, '-ftn_api_fn0', '-rpn_sto', data_reg, '-rpn', 'rcl_lon:sto_{}'.format(lon_reg), '-rpn', 'rcl_lat:sto_{}'.format(lat_reg)] pywgrib2.wgrib(*args) npts, nx, ny = [int(i) for i in buf.get('s').split()[2:5]] tmp = data_reg.get().reshape((ny, nx)) lon = lon_reg.get().reshape((ny, nx)) lat = lat_reg.get().reshape((ny, nx)) print(lon[:3,:3]) print(lat[:3,:3]) print(tmp[0,0], tmp[-1, -1])
[[225.38573 225.62788 225.87093]
[225.2796 225.5226 225.76648]
[225.17259 225.41641 225.66115]]
[[32.549114 32.637794 32.725685]
[32.752975 32.842205 32.93064 ]
[32.957066 33.04685 33.135838]]
288.38113 285.1811
All three registers and the memory buffers are available for reuse.