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
 19    **`i`**: Integer value to convert to binary representation.
 20
 21    **`nbits`**: Number of bits to return.  Valid values are 8 [DEFAULT], 16,
 22    32, and 64.
 23
 24    **`output`**: Return data as `str` [DEFAULT] or `list` (list of ints).
 25
 26    Returns
 27    -------
 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
 47    **`f`**: Float value.
 48
 49    Returns
 50    -------
 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)
 56
 57
 58def ieee_int_to_float(i):
 59    """
 60    Convert a 32-bit integer to an IEEE 32-bit float.
 61
 62    Parameters
 63    ----------
 64
 65    **`i`**: Integer value.
 66
 67    Returns
 68    -------
 69
 70    Numpy float32
 71    """
 72    f = struct.unpack('>f',struct.pack('>i',np.int32(i)))[0]
 73    return np.float32(f)
 74
 75
 76def get_leadtime(idsec,pdtn,pdt):
 77    """
 78    Computes lead time as a datetime.timedelta object using information from
 79    GRIB2 Identification Section (Section 1), Product Definition Template
 80    Number, and Product Definition Template (Section 4).
 81
 82    Parameters
 83    ----------
 84
 85    **`idsec`**: seqeunce containing GRIB2 Identification Section (Section 1).
 86
 87    **`pdtn`**: GRIB2 Product Definition Template Number
 88
 89    **`idsec`**: seqeunce containing GRIB2 Product Definition Template (Section 4).
 90
 91    Returns
 92    -------
 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')))
105
106
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
115    **`pdtn`**: GRIB2 Product Definition Template Number
116
117    **`pdt`**: sequence containing GRIB2 Product Definition Template (Section 4).
118
119    Returns
120    -------
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
129
130
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
139    **`lus`**: GRIB2 Local Use Section containing NDFD weather strings.
140
141    Returns
142    -------
143
144    **`dict`**: Dictionary of NDFD/MDL weather strings. Keys are an integer
145    value that represent the sequential order of the key in the packed loca
146    use section and the value is the weather key.
147    """
148    assert lus[0] == 1
149    # Unpack information related to the simple packing method
150    # the packed weather string data.
151    ngroups = struct.unpack('>H',lus[1:3])[0]
152    nvalues = struct.unpack('>i',lus[3:7])[0]
153    refvalue = struct.unpack('>i',lus[7:11])[0]
154    dsf = struct.unpack('>h',lus[11:13])[0]
155    nbits = lus[13]
156    datatype = lus[14]
157    if datatype == 0: # Floating point
158        refvalue = np.float32(ieee_int_to_float(refvalue)*10**-dsf)
159    elif datatype == 1: # Integer
160        refvalue = np.int32(ieee_int_to_float(refvalue)*10**-dsf)
161    # Upack each byte starting at byte 15 to end of the local use
162    # section, create a binary string and append to the full
163    # binary string.
164    b = ''
165    for i in range(15,len(lus)):
166        iword = struct.unpack('>B',lus[i:i+1])[0]
167        b += bin(iword).split('b')[1].zfill(8)
168    # Iterate over the binary string (b). For each nbits
169    # chunk, convert to an integer, including the refvalue,
170    # and then convert the int to an ASCII character, then
171    # concatenate to wxstring.
172    wxstring = ''
173    for i in range(0,len(b),nbits):
174        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
175    # Return string as list, split by null character.
176    #return list(filter(None,wxstring.split('\0')))
177    return {n:k for n,k in enumerate(list(filter(None,wxstring.split('\0'))))}
178
179
180def get_wgrib2_prob_string(probtype,sfacl,svall,sfacu,svalu):
181    """
182    Return a wgrib2-formatted string explaining probabilistic
183    threshold informaiton.  Logic from wgrib2 source, [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
184    is replicated here.
185
186    Parameters
187    ----------
188
189    **`probtype`**: `int` type of probability (Code Table 4.9).
190
191    **`sfacl`**: `int` scale factor of lower limit.
192
193    **`svall`**: `int` scaled value of lower limit.
194
195    **`sfacu`**: `int` scale factor of upper limit.
196
197    **`svalu`**: `int` scaled value of upper limit.
198
199    Returns
200    -------
201
202    **`str`**: wgrib2-formatted string of probability threshold.
203    """
204    probstr = ''
205    if sfacl == -127: sfacl = 0
206    if sfacu == -127: sfacu = 0
207    lower = svall/(10**sfacl)
208    upper = svalu/(10**sfacu)
209    if probtype == 0:
210        probstr = 'prob <%g' % (lower)
211    elif probtype == 1:
212        probstr = 'prob >%g' % (upper)
213    elif probtype == 2:
214        if lower == upper:
215            probstr = 'prob =%g' % (lower)
216        else:
217            probstr = 'prob >=%g <%g' % (lower,upper)
218    elif probtype == 3:
219        probstr = 'prob >%g' % (lower)
220    elif probtype == 4:
221        probstr = 'prob <%g' % (upper)
222    else:
223        probstr = ''
224    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
20    **`i`**: Integer value to convert to binary representation.
21
22    **`nbits`**: Number of bits to return.  Valid values are 8 [DEFAULT], 16,
23    32, and 64.
24
25    **`output`**: Return data as `str` [DEFAULT] or `list` (list of ints).
26
27    Returns
28    -------
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: Integer value to convert to binary representation.

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

output: 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
48    **`f`**: Float value.
49
50    Returns
51    -------
52
53    Numpy Int32 representation of an IEEE 32-bit float.
54    """
55    i = struct.unpack('>i',struct.pack('>f',np.float32(f)))[0]
56    return np.int32(i)

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

Parameters

f: Float value.

Returns

Numpy Int32 representation of an IEEE 32-bit float.

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

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

Parameters

i: Integer value.

Returns

Numpy float32

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

pdtn: GRIB2 Product Definition Template Number

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

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

Returns

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

def get_wgrib2_prob_string(probtype, sfacl, svall, sfacu, svalu):
181def get_wgrib2_prob_string(probtype,sfacl,svall,sfacu,svalu):
182    """
183    Return a wgrib2-formatted string explaining probabilistic
184    threshold informaiton.  Logic from wgrib2 source, [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
185    is replicated here.
186
187    Parameters
188    ----------
189
190    **`probtype`**: `int` type of probability (Code Table 4.9).
191
192    **`sfacl`**: `int` scale factor of lower limit.
193
194    **`svall`**: `int` scaled value of lower limit.
195
196    **`sfacu`**: `int` scale factor of upper limit.
197
198    **`svalu`**: `int` scaled value of upper limit.
199
200    Returns
201    -------
202
203    **`str`**: 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

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

str: wgrib2-formatted string of probability threshold.