grib2io.utils

Collection of utility functions to assist in the encoding and decoding of GRIB2 Messages.

  1"""
  2Collection of utility functions to assist in the encoding and decoding
  3of GRIB2 Messages.
  4"""
  5
  6import datetime
  7import numpy as np
  8import struct
  9
 10from .. import tables
 11
 12def int2bin(i, nbits=8, output=str):
 13    """
 14    Convert integer to binary string or list
 15
 16    Parameters
 17    ----------
 18    **`i : int`**
 19        Integer value to convert to binary representation.
 20
 21    **`nbits : int, optional`**
 22        Number of bits to return.  Valid values are 8 [DEFAULT], 16, 32, and 64.
 23
 24    **`output : type`**
 25        Return data as `str` [DEFAULT] or `list` (list of ints).
 26
 27    Returns
 28    -------
 29    `str` or `list` (list of ints) of binary representation of the integer value.
 30    """
 31    i = int(i) if not isinstance(i,int) else i
 32    assert nbits in [8,16,32,64]
 33    bitstr = "{0:b}".format(i).zfill(nbits)
 34    if output is str:
 35        return bitstr
 36    elif output is list:
 37        return [int(b) for b in bitstr]
 38
 39
 40def ieee_float_to_int(f):
 41    """
 42    Convert an IEEE 32-bit float to a 32-bit integer.
 43
 44    Parameters
 45    ----------
 46    **`f : float`**
 47        Floating-point value.
 48
 49    Returns
 50    -------
 51    `numpy.int32` representation of an IEEE 32-bit float.
 52    """
 53    i = struct.unpack('>i',struct.pack('>f',np.float32(f)))[0]
 54    return np.int32(i)
 55
 56
 57def ieee_int_to_float(i):
 58    """
 59    Convert a 32-bit integer to an IEEE 32-bit float.
 60
 61    Parameters
 62    ----------
 63    **`i : int`**
 64        Integer value.
 65
 66    Returns
 67    -------
 68    `numpy.float32` representation of a 32-bit int.
 69    """
 70    f = struct.unpack('>f',struct.pack('>i',np.int32(i)))[0]
 71    return np.float32(f)
 72
 73
 74def get_leadtime(idsec, pdtn, pdt):
 75    """
 76    Computes lead time as a datetime.timedelta object using information from
 77    GRIB2 Identification Section (Section 1), Product Definition Template
 78    Number, and Product Definition Template (Section 4).
 79
 80    Parameters
 81    ----------
 82    **`idsec : list or array_like`**
 83        Seqeunce containing GRIB2 Identification Section (Section 1).
 84
 85    **`pdtn : int`**
 86        GRIB2 Product Definition Template Number
 87
 88    **`pdt : list or array_like`**
 89        Seqeunce containing GRIB2 Product Definition Template (Section 4).
 90
 91    Returns
 92    -------
 93    **`datetime.timedelta`** object representing the lead time of the GRIB2 message.
 94    """
 95    _key = {8:slice(15,21), 9:slice(22,28), 10:slice(16,22), 11:slice(18,24), 12:slice(17,23)}
 96    refdate = datetime.datetime(*idsec[5:11])
 97    try:
 98        return datetime.datetime(*pdt[_key[pdtn]])-refdate
 99    except(KeyError):
100        if pdtn == 48:
101            return datetime.timedelta(hours=pdt[19]*(tables.get_value_from_table(pdt[18],'scale_time_hours')))
102        else:
103            return datetime.timedelta(hours=pdt[8]*(tables.get_value_from_table(pdt[7],'scale_time_hours')))
104
105
106def get_duration(pdtn, pdt):
107    """
108    Computes a time duration as a datetime.timedelta using information from
109    Product Definition Template Number, and Product Definition Template (Section 4).
110
111    Parameters
112    ----------
113    **`pdtn : int`**
114        GRIB2 Product Definition Template Number
115
116    **`pdt : list or array_like`**
117        Sequence containing GRIB2 Product Definition Template (Section 4).
118
119    Returns
120    -------
121    **`datetime.timedelta`** object representing the time duration of the GRIB2 message.
122    """
123    _key = {8:25, 9:32, 10:26, 11:28, 12:27}
124    try:
125        return datetime.timedelta(hours=pdt[_key[pdtn]+1]*tables.get_value_from_table(pdt[_key[pdtn]],'scale_time_hours'))
126    except(KeyError):
127        return None
128
129
130def decode_wx_strings(lus):
131    """
132    Decode GRIB2 Local Use Section to obtain NDFD/MDL Weather Strings.  The
133    decode procedure is defined [here](https://vlab.noaa.gov/web/mdl/nbm-gmos-grib2-wx-info).
134
135    Parameters
136    ----------
137    **`lus : bytes`**
138        GRIB2 Local Use Section containing NDFD weather strings.
139
140    Returns
141    -------
142    **`dict`** of NDFD/MDL weather strings. Keys are an integer value that represent 
143    the sequential order of the key in the packed local use section and the value is 
144    the weather key.
145    """
146    assert lus[0] == 1
147    # Unpack information related to the simple packing method
148    # the packed weather string data.
149    ngroups = struct.unpack('>H',lus[1:3])[0]
150    nvalues = struct.unpack('>i',lus[3:7])[0]
151    refvalue = struct.unpack('>i',lus[7:11])[0]
152    dsf = struct.unpack('>h',lus[11:13])[0]
153    nbits = lus[13]
154    datatype = lus[14]
155    if datatype == 0: # Floating point
156        refvalue = np.float32(ieee_int_to_float(refvalue)*10**-dsf)
157    elif datatype == 1: # Integer
158        refvalue = np.int32(ieee_int_to_float(refvalue)*10**-dsf)
159    # Upack each byte starting at byte 15 to end of the local use
160    # section, create a binary string and append to the full
161    # binary string.
162    b = ''
163    for i in range(15,len(lus)):
164        iword = struct.unpack('>B',lus[i:i+1])[0]
165        b += bin(iword).split('b')[1].zfill(8)
166    # Iterate over the binary string (b). For each nbits
167    # chunk, convert to an integer, including the refvalue,
168    # and then convert the int to an ASCII character, then
169    # concatenate to wxstring.
170    wxstring = ''
171    for i in range(0,len(b),nbits):
172        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
173    # Return string as list, split by null character.
174    #return list(filter(None,wxstring.split('\0')))
175    return {n:k for n,k in enumerate(list(filter(None,wxstring.split('\0'))))}
176
177
178def get_wgrib2_prob_string(probtype,sfacl,svall,sfacu,svalu):
179    """
180    Return a wgrib2-formatted string explaining probabilistic
181    threshold informaiton.  Logic from wgrib2 source, [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
182    is replicated here.
183
184    Parameters
185    ----------
186    **`probtype : int`**
187        Type of probability (Code Table 4.9).
188
189    **`sfacl : int`**
190        Scale factor of lower limit.
191
192    **`svall : int`**
193        Scaled value of lower limit.
194
195    **`sfacu : int`**
196        Scale factor of upper limit.
197
198    **`svalu : int`**
199        Scaled value of upper limit.
200
201    Returns
202    -------
203    wgrib2-formatted string of probability threshold.
204    """
205    probstr = ''
206    if sfacl == -127: sfacl = 0
207    if sfacu == -127: sfacu = 0
208    lower = svall/(10**sfacl)
209    upper = svalu/(10**sfacu)
210    if probtype == 0:
211        probstr = 'prob <%g' % (lower)
212    elif probtype == 1:
213        probstr = 'prob >%g' % (upper)
214    elif probtype == 2:
215        if lower == upper:
216            probstr = 'prob =%g' % (lower)
217        else:
218            probstr = 'prob >=%g <%g' % (lower,upper)
219    elif probtype == 3:
220        probstr = 'prob >%g' % (lower)
221    elif probtype == 4:
222        probstr = 'prob <%g' % (upper)
223    else:
224        probstr = ''
225    return probstr
def int2bin(i, nbits=8, output=<class 'str'>):
13def int2bin(i, nbits=8, output=str):
14    """
15    Convert integer to binary string or list
16
17    Parameters
18    ----------
19    **`i : int`**
20        Integer value to convert to binary representation.
21
22    **`nbits : int, optional`**
23        Number of bits to return.  Valid values are 8 [DEFAULT], 16, 32, and 64.
24
25    **`output : type`**
26        Return data as `str` [DEFAULT] or `list` (list of ints).
27
28    Returns
29    -------
30    `str` or `list` (list of ints) of binary representation of the integer value.
31    """
32    i = int(i) if not isinstance(i,int) else i
33    assert nbits in [8,16,32,64]
34    bitstr = "{0:b}".format(i).zfill(nbits)
35    if output is str:
36        return bitstr
37    elif output is list:
38        return [int(b) for b in bitstr]

Convert integer to binary string or list

Parameters

i : int Integer value to convert to binary representation.

nbits : int, optional Number of bits to return. Valid values are 8 [DEFAULT], 16, 32, and 64.

output : type Return data as str [DEFAULT] or list (list of ints).

Returns

str or list (list of ints) of binary representation of the integer value.

def ieee_float_to_int(f):
41def ieee_float_to_int(f):
42    """
43    Convert an IEEE 32-bit float to a 32-bit integer.
44
45    Parameters
46    ----------
47    **`f : float`**
48        Floating-point value.
49
50    Returns
51    -------
52    `numpy.int32` representation of an IEEE 32-bit float.
53    """
54    i = struct.unpack('>i',struct.pack('>f',np.float32(f)))[0]
55    return np.int32(i)

Convert an IEEE 32-bit float to a 32-bit integer.

Parameters

f : float Floating-point value.

Returns

numpy.int32 representation of an IEEE 32-bit float.

def ieee_int_to_float(i):
58def ieee_int_to_float(i):
59    """
60    Convert a 32-bit integer to an IEEE 32-bit float.
61
62    Parameters
63    ----------
64    **`i : int`**
65        Integer value.
66
67    Returns
68    -------
69    `numpy.float32` representation of a 32-bit int.
70    """
71    f = struct.unpack('>f',struct.pack('>i',np.int32(i)))[0]
72    return np.float32(f)

Convert a 32-bit integer to an IEEE 32-bit float.

Parameters

i : int Integer value.

Returns

numpy.float32 representation of a 32-bit int.

def get_leadtime(idsec, pdtn, pdt):
 75def get_leadtime(idsec, pdtn, pdt):
 76    """
 77    Computes lead time as a datetime.timedelta object using information from
 78    GRIB2 Identification Section (Section 1), Product Definition Template
 79    Number, and Product Definition Template (Section 4).
 80
 81    Parameters
 82    ----------
 83    **`idsec : list or array_like`**
 84        Seqeunce containing GRIB2 Identification Section (Section 1).
 85
 86    **`pdtn : int`**
 87        GRIB2 Product Definition Template Number
 88
 89    **`pdt : list or array_like`**
 90        Seqeunce containing GRIB2 Product Definition Template (Section 4).
 91
 92    Returns
 93    -------
 94    **`datetime.timedelta`** object representing the lead time of the GRIB2 message.
 95    """
 96    _key = {8:slice(15,21), 9:slice(22,28), 10:slice(16,22), 11:slice(18,24), 12:slice(17,23)}
 97    refdate = datetime.datetime(*idsec[5:11])
 98    try:
 99        return datetime.datetime(*pdt[_key[pdtn]])-refdate
100    except(KeyError):
101        if pdtn == 48:
102            return datetime.timedelta(hours=pdt[19]*(tables.get_value_from_table(pdt[18],'scale_time_hours')))
103        else:
104            return datetime.timedelta(hours=pdt[8]*(tables.get_value_from_table(pdt[7],'scale_time_hours')))

Computes lead time as a datetime.timedelta object using information from GRIB2 Identification Section (Section 1), Product Definition Template Number, and Product Definition Template (Section 4).

Parameters

idsec : list or array_like Seqeunce containing GRIB2 Identification Section (Section 1).

pdtn : int GRIB2 Product Definition Template Number

pdt : list or array_like Seqeunce containing GRIB2 Product Definition Template (Section 4).

Returns

datetime.timedelta object representing the lead time of the GRIB2 message.

def get_duration(pdtn, pdt):
107def get_duration(pdtn, pdt):
108    """
109    Computes a time duration as a datetime.timedelta using information from
110    Product Definition Template Number, and Product Definition Template (Section 4).
111
112    Parameters
113    ----------
114    **`pdtn : int`**
115        GRIB2 Product Definition Template Number
116
117    **`pdt : list or array_like`**
118        Sequence containing GRIB2 Product Definition Template (Section 4).
119
120    Returns
121    -------
122    **`datetime.timedelta`** object representing the time duration of the GRIB2 message.
123    """
124    _key = {8:25, 9:32, 10:26, 11:28, 12:27}
125    try:
126        return datetime.timedelta(hours=pdt[_key[pdtn]+1]*tables.get_value_from_table(pdt[_key[pdtn]],'scale_time_hours'))
127    except(KeyError):
128        return None

Computes a time duration as a datetime.timedelta using information from Product Definition Template Number, and Product Definition Template (Section 4).

Parameters

pdtn : int GRIB2 Product Definition Template Number

pdt : list or array_like Sequence containing GRIB2 Product Definition Template (Section 4).

Returns

datetime.timedelta object representing the time duration of the GRIB2 message.

def decode_wx_strings(lus):
131def decode_wx_strings(lus):
132    """
133    Decode GRIB2 Local Use Section to obtain NDFD/MDL Weather Strings.  The
134    decode procedure is defined [here](https://vlab.noaa.gov/web/mdl/nbm-gmos-grib2-wx-info).
135
136    Parameters
137    ----------
138    **`lus : bytes`**
139        GRIB2 Local Use Section containing NDFD weather strings.
140
141    Returns
142    -------
143    **`dict`** of NDFD/MDL weather strings. Keys are an integer value that represent 
144    the sequential order of the key in the packed local use section and the value is 
145    the weather key.
146    """
147    assert lus[0] == 1
148    # Unpack information related to the simple packing method
149    # the packed weather string data.
150    ngroups = struct.unpack('>H',lus[1:3])[0]
151    nvalues = struct.unpack('>i',lus[3:7])[0]
152    refvalue = struct.unpack('>i',lus[7:11])[0]
153    dsf = struct.unpack('>h',lus[11:13])[0]
154    nbits = lus[13]
155    datatype = lus[14]
156    if datatype == 0: # Floating point
157        refvalue = np.float32(ieee_int_to_float(refvalue)*10**-dsf)
158    elif datatype == 1: # Integer
159        refvalue = np.int32(ieee_int_to_float(refvalue)*10**-dsf)
160    # Upack each byte starting at byte 15 to end of the local use
161    # section, create a binary string and append to the full
162    # binary string.
163    b = ''
164    for i in range(15,len(lus)):
165        iword = struct.unpack('>B',lus[i:i+1])[0]
166        b += bin(iword).split('b')[1].zfill(8)
167    # Iterate over the binary string (b). For each nbits
168    # chunk, convert to an integer, including the refvalue,
169    # and then convert the int to an ASCII character, then
170    # concatenate to wxstring.
171    wxstring = ''
172    for i in range(0,len(b),nbits):
173        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
174    # Return string as list, split by null character.
175    #return list(filter(None,wxstring.split('\0')))
176    return {n:k for n,k in enumerate(list(filter(None,wxstring.split('\0'))))}

Decode GRIB2 Local Use Section to obtain NDFD/MDL Weather Strings. The decode procedure is defined here.

Parameters

lus : bytes GRIB2 Local Use Section containing NDFD weather strings.

Returns

dict of NDFD/MDL weather strings. Keys are an integer value that represent the sequential order of the key in the packed local use section and the value is the weather key.

def get_wgrib2_prob_string(probtype, sfacl, svall, sfacu, svalu):
179def get_wgrib2_prob_string(probtype,sfacl,svall,sfacu,svalu):
180    """
181    Return a wgrib2-formatted string explaining probabilistic
182    threshold informaiton.  Logic from wgrib2 source, [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
183    is replicated here.
184
185    Parameters
186    ----------
187    **`probtype : int`**
188        Type of probability (Code Table 4.9).
189
190    **`sfacl : int`**
191        Scale factor of lower limit.
192
193    **`svall : int`**
194        Scaled value of lower limit.
195
196    **`sfacu : int`**
197        Scale factor of upper limit.
198
199    **`svalu : int`**
200        Scaled value of upper limit.
201
202    Returns
203    -------
204    wgrib2-formatted string of probability threshold.
205    """
206    probstr = ''
207    if sfacl == -127: sfacl = 0
208    if sfacu == -127: sfacu = 0
209    lower = svall/(10**sfacl)
210    upper = svalu/(10**sfacu)
211    if probtype == 0:
212        probstr = 'prob <%g' % (lower)
213    elif probtype == 1:
214        probstr = 'prob >%g' % (upper)
215    elif probtype == 2:
216        if lower == upper:
217            probstr = 'prob =%g' % (lower)
218        else:
219            probstr = 'prob >=%g <%g' % (lower,upper)
220    elif probtype == 3:
221        probstr = 'prob >%g' % (lower)
222    elif probtype == 4:
223        probstr = 'prob <%g' % (upper)
224    else:
225        probstr = ''
226    return probstr

Return a wgrib2-formatted string explaining probabilistic threshold informaiton. Logic from wgrib2 source, Prob.c, is replicated here.

Parameters

probtype : int Type of probability (Code Table 4.9).

sfacl : int Scale factor of lower limit.

svall : int Scaled value of lower limit.

sfacu : int Scale factor of upper limit.

svalu : int Scaled value of upper limit.

Returns

wgrib2-formatted string of probability threshold.