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

str: wgrib2-formatted string of probability threshold.