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 putieeeint(r):
 42    """
 43    Convert an IEEE 32-bit float to a 32-bit integer.
 44
 45    Parameters
 46    ----------
 47
 48    **`r`**: Float value.
 49
 50    Returns
 51    -------
 52
 53    Integer representation of an IEEE 32-bit float.
 54    """
 55    ra = np.array([r],'f')
 56    ia = np.empty(1,'i')
 57    g2clib.rtoi_ieee(ra,ia)
 58    return ia[0]
 59
 60
 61def getieeeint(i):
 62    """
 63    Convert a 32-bit integer to an IEEE 32-bit float.
 64
 65    Parameters
 66    ----------
 67
 68    **`i`**: Integer value.
 69
 70    Returns
 71    -------
 72
 73    IEEE 32-bit float.
 74    """
 75    ia = np.array([i],'i')
 76    ra = np.empty(1,'f')
 77    g2clib.itor_ieee(ia,ra)
 78    return ra[0]
 79
 80
 81def getmd5str(a):
 82    """
 83    Generate a MD5 hash string from input list
 84    """
 85    import hashlib
 86    assert isinstance(a,list) or isinstance(a,bytes)
 87    return hashlib.md5(''.join([str(i) for i in a]).encode()).hexdigest()
 88
 89
 90def getdate(year,month,day,hour,minute=None,second=None):
 91    """
 92    Build an integer date from component input.
 93
 94    **`year`**: Year in 4-digit format.
 95
 96    **`month`**: Month in 2-digit format.
 97
 98    **`day`**: Day in 2-digit format.
 99
100    **`hour`**: Hour in 2-digit format.
101
102    **`minute`**: Minute in 2-digit format. This argument is required if second is provided, otherwise
103    it is optional.
104
105    **`second`**: Second in 2-digit format [OPTIONAL].
106    """
107    year_exp = 6
108    month_exp = 4
109    day_exp = 2
110    hour_exp = 0
111    #if second is not None and minute is None:
112    #    raise ValueError("Must provide minute argument if second argument is provided.")
113    #year_exp = 6
114    #month_exp = 4
115    #day_exp = 2
116    #hour_exp = 0
117    #minute_exp = -2
118    #second_exp = -4
119    #if minute is not None:
120    #    assert minute >= 0 and minute <= 60
121    #    year_exp += 2
122    #    month_exp += 2
123    #    day_exp += 2
124    #    hour_exp += 2
125    #    minute_exp += 2
126    #    second_exp += 2
127    #if second is not None:
128    #    assert second >= 0 and second <= 60
129    #    year_exp += 2
130    #    month_exp += 2
131    #    day_exp += 2
132    #    hour_exp += 2
133    #    minute_exp += 2
134    #    second_exp += 2
135    idate = (year*pow(10,year_exp))+(month*pow(10,month_exp))+\
136            (day*pow(10,day_exp))+(hour*pow(10,hour_exp))
137    #if minute is not None:
138    #    idate += minute*pow(10,minute_exp)
139    #if second is not None:
140    #    idate += second*pow(10,second_exp)
141    return idate
142
143
144def getleadtime(idsec,pdtn,pdt):
145    """
146    Computes the lead time (in units of hours) from using information from
147    GRIB2 Identification Section (Section 1), Product Definition Template
148    Number, and Product Definition Template (Section 4).
149
150    Parameters
151    ----------
152
153    **`idsec`**: seqeunce containing GRIB2 Identification Section (Section 1).
154
155    **`pdtn`**: GRIB2 Product Definition Template Number
156
157    **`idsec`**: seqeunce containing GRIB2 Product Definition Template (Section 4).
158
159    Returns
160    -------
161
162    **`lt`**: Lead time in units of hours
163    """
164    refdate = datetime.datetime(*idsec[5:11])
165    if pdtn == 8:
166        enddate = datetime.datetime(*pdt[15:21])
167        td = enddate - refdate
168        lt = (td).total_seconds()/3600.0
169    elif pdtn == 9:
170        enddate = datetime.datetime(*pdt[22:28])
171        td = enddate - refdate
172        lt = (td).total_seconds()/3600.0
173    elif pdtn == 10:
174        enddate = datetime.datetime(*pdt[16:22])
175        td = enddate - refdate
176        lt = (td).total_seconds()/3600.0
177    elif pdtn == 11:
178        enddate = datetime.datetime(*pdt[18:24])
179        td = enddate - refdate
180        lt = (td).total_seconds()/3600.0
181    elif pdtn == 12:
182        enddate = datetime.datetime(*pdt[17:23])
183        td = enddate - refdate
184        lt = (td).total_seconds()/3600.0
185    else:
186        lt = pdt[8]*(tables.get_value_from_table(pdt[7],'scale_time_hours'))
187    return int(lt)
188
189
190def getduration(pdtn,pdt):
191    """
192    Computes the duration time (in units of hours) from using information from
193    Product Definition Template Number, and Product Definition Template (Section 4).
194
195    Parameters
196    ----------
197
198    **`pdtn`**: GRIB2 Product Definition Template Number
199
200    **`pdt`**: sequence containing GRIB2 Product Definition Template (Section 4).
201
202    Returns
203    -------
204
205    **`dur`**: Duration time in units of hours
206    """
207    if pdtn == 8:
208        dur = pdt[26]*(tables.get_value_from_table(pdt[25],'scale_time_hours'))
209    elif pdtn == 9:
210        dur = pdt[33]*(tables.get_value_from_table(pdt[32],'scale_time_hours'))
211    elif pdtn == 10:
212        dur = pdt[27]*(tables.get_value_from_table(pdt[26],'scale_time_hours'))
213    elif pdtn == 11:
214        dur = pdt[29]*(tables.get_value_from_table(pdt[28],'scale_time_hours'))
215    elif pdtn == 12:
216        dur = pdt[28]*(tables.get_value_from_table(pdt[27],'scale_time_hours'))
217    else:
218        dur = 0
219    return int(dur)
220
221
222def decode_mdl_wx_strings(lus):
223    """
224    Decode GRIB2 Local Use Section to obtain MDL Weather Strings.  The
225    decode procedure is defined here:
226
227    https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_mdl_temp2-1.shtml
228
229    Parameters
230    ----------
231
232    **`lus`**: GRIB2 Local Use Section containing MDL weather strings.
233
234    Returns
235    -------
236
237    **`list`**: List of weather strings.
238    """
239    assert lus[0] == 1
240    # Unpack information related to the simple packing method
241    # the packed weather string data.
242    ngroups = struct.unpack('>h',lus[1:3])[0]
243    nvalues = struct.unpack('>i',lus[3:7])[0]
244    refvalue = struct.unpack('>i',lus[7:11])[0]
245    dsf = struct.unpack('>h',lus[11:13])[0]
246    nbits = lus[13]
247    datatype = lus[14]
248    if datatype == 0: # Floating point
249        refvalue = np.float32(getieeeint(refvalue)*10**-dsf)
250    elif datatype == 1: # Integer
251        refvalue = np.int32(getieeeint(refvalue)*10**-dsf)
252    #print("TEST:",ngroups,nvalues,refvalue,dsf,nbits,datatype)
253    # Store the "data" part of the packed weather strings as
254    # a binary string.
255    b = bin(int.from_bytes(lus[15:],byteorder='big'))
256    # Generated begin and end values. Note the offset begins at 2
257    # due to the format nature of b (binary string).
258    idxb = list(range(2,len(b),nbits))[0:nvalues-1]
259    idxe = list(range(2+nbits,len(b)+nbits,nbits))[0:nvalues-1]
260    # Iterate over the packed data, converting the nbits space to
261    # and integer, then convert integer to an ASCII character.
262    wxstring = ''
263    for ib,ie in zip(idxb,idxe):
264        wxstring += chr(int(b[ib:ie],2)+refvalue)
265    # Return string as list, split by null character.
266    return wxstring.split('\0')
267
268
269def decode_ndfd_wx_strings(lus):
270    """
271    Decode GRIB2 Local Use Section to obtain NDFD Weather Strings.  The
272    decode procedure is defined here:
273
274    https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_mdl_temp2-1.shtml
275
276    NOTE: From testing, it seems how the process for packing Section 2 for NDFD
277          Weather grids is different than GMOS and thus the need for a different
278          method for decoding NDFD Wx vs. GMOS Wx.
279
280    Parameters
281    ----------
282
283    **`lus`**: GRIB2 Local Use Section containing NDFD weather strings.
284
285    Returns
286    -------
287
288    **`list`**: List of NDFD weather strings.
289    """
290    assert lus[0] == 1
291    # Unpack information related to the simple packing method
292    # the packed weather string data.
293    ngroups = struct.unpack('>h',lus[1:3])[0]
294    nvalues = struct.unpack('>i',lus[3:7])[0]
295    refvalue = struct.unpack('>i',lus[7:11])[0]
296    dsf = struct.unpack('>h',lus[11:13])[0]
297    nbits = lus[13]
298    datatype = lus[14]
299    if datatype == 0: # Floating point
300        refvalue = np.float32(getieeeint(refvalue)*10**-dsf)
301    elif datatype == 1: # Integer
302        refvalue = np.int32(getieeeint(refvalue)*10**-dsf)
303    # Iterate over the data of section 2 in 4-byte (32-bit)
304    # words OR 2-byte word at the end. Each word is unpacked
305    # as an unsigned integer. Then convert the integer word
306    # to a binary string and fill to the appropriate bit
307    # size (16 or 32) and concatenate to b (binary string).
308    b = ''
309    for i in range(15,len(lus),4):
310        if len(lus)-i < 4:
311            iword = struct.unpack('>H',lus[i:i+2])[0]
312            b += bin(iword).split('b')[1].zfill(16)
313        else:
314            iword = struct.unpack('>I',lus[i:i+4])[0]
315            b += bin(iword).split('b')[1].zfill(32)
316    # Iterate over the binary string (b). For each nbits
317    # chunk, convert to an integer, including the refvalue,
318    # and then convert the int to an ASCII character, then
319    # concatenate to wxstring.
320    wxstring = ''
321    for i in range(0,len(b),nbits):
322        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
323    # Return string as list, split by null character.
324    return list(filter(None,wxstring.split('\0')))
325
326
327def get_wgrib2_prob_string(probtype,sfacl,svall,sfacu,svalu):
328    """
329    Return a wgrib2-formatted string explaining probabilistic
330    threshold informaiton.  Logic from wgrib2 source, [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
331    is replicated here.
332
333    Parameters
334    ----------
335
336    **`probtype`**: `int` type of probability (Code Table 4.9).
337
338    **`sfacl`**: `int` scale factor of lower limit.
339
340    **`svall`**: `int` scaled value of lower limit.
341
342    **`sfacu`**: `int` scale factor of upper limit.
343
344    **`svalu`**: `int` scaled value of upper limit.
345
346    Returns
347    -------
348
349    **`str`**: wgrib2-formatted string of probability threshold.
350    """
351    probstr = ''
352    lower = svall/(10**sfacl)
353    upper = svalu/(10**sfacu)
354    if probtype == 0:
355        probstr = 'prob <%g' % (lower)
356    elif probtype == 1:
357        probstr = 'prob >%g' % (upper)
358    elif probtype == 2:
359        if lower == upper:
360            probstr = 'prob =%g' % (lower)
361        else:
362            probstr = 'prob >=%g <%g' % (lower,upper)
363    elif probtype == 3:
364        probstr = 'prob >%g' % (lower)
365    elif probtype == 4:
366        probstr = 'prob <%g' % (upper)
367    return probstr
def int2bin(i, nbits=8, output=)
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 putieeeint(r)
42def putieeeint(r):
43    """
44    Convert an IEEE 32-bit float to a 32-bit integer.
45
46    Parameters
47    ----------
48
49    **`r`**: Float value.
50
51    Returns
52    -------
53
54    Integer representation of an IEEE 32-bit float.
55    """
56    ra = np.array([r],'f')
57    ia = np.empty(1,'i')
58    g2clib.rtoi_ieee(ra,ia)
59    return ia[0]

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

Parameters

r: Float value.

Returns

Integer representation of an IEEE 32-bit float.

def getieeeint(i)
62def getieeeint(i):
63    """
64    Convert a 32-bit integer to an IEEE 32-bit float.
65
66    Parameters
67    ----------
68
69    **`i`**: Integer value.
70
71    Returns
72    -------
73
74    IEEE 32-bit float.
75    """
76    ia = np.array([i],'i')
77    ra = np.empty(1,'f')
78    g2clib.itor_ieee(ia,ra)
79    return ra[0]

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

Parameters

i: Integer value.

Returns

IEEE 32-bit float.

def getmd5str(a)
82def getmd5str(a):
83    """
84    Generate a MD5 hash string from input list
85    """
86    import hashlib
87    assert isinstance(a,list) or isinstance(a,bytes)
88    return hashlib.md5(''.join([str(i) for i in a]).encode()).hexdigest()

Generate a MD5 hash string from input list

def getdate(year, month, day, hour, minute=None, second=None)
 91def getdate(year,month,day,hour,minute=None,second=None):
 92    """
 93    Build an integer date from component input.
 94
 95    **`year`**: Year in 4-digit format.
 96
 97    **`month`**: Month in 2-digit format.
 98
 99    **`day`**: Day in 2-digit format.
100
101    **`hour`**: Hour in 2-digit format.
102
103    **`minute`**: Minute in 2-digit format. This argument is required if second is provided, otherwise
104    it is optional.
105
106    **`second`**: Second in 2-digit format [OPTIONAL].
107    """
108    year_exp = 6
109    month_exp = 4
110    day_exp = 2
111    hour_exp = 0
112    #if second is not None and minute is None:
113    #    raise ValueError("Must provide minute argument if second argument is provided.")
114    #year_exp = 6
115    #month_exp = 4
116    #day_exp = 2
117    #hour_exp = 0
118    #minute_exp = -2
119    #second_exp = -4
120    #if minute is not None:
121    #    assert minute >= 0 and minute <= 60
122    #    year_exp += 2
123    #    month_exp += 2
124    #    day_exp += 2
125    #    hour_exp += 2
126    #    minute_exp += 2
127    #    second_exp += 2
128    #if second is not None:
129    #    assert second >= 0 and second <= 60
130    #    year_exp += 2
131    #    month_exp += 2
132    #    day_exp += 2
133    #    hour_exp += 2
134    #    minute_exp += 2
135    #    second_exp += 2
136    idate = (year*pow(10,year_exp))+(month*pow(10,month_exp))+\
137            (day*pow(10,day_exp))+(hour*pow(10,hour_exp))
138    #if minute is not None:
139    #    idate += minute*pow(10,minute_exp)
140    #if second is not None:
141    #    idate += second*pow(10,second_exp)
142    return idate

Build an integer date from component input.

year: Year in 4-digit format.

month: Month in 2-digit format.

day: Day in 2-digit format.

hour: Hour in 2-digit format.

minute: Minute in 2-digit format. This argument is required if second is provided, otherwise it is optional.

second: Second in 2-digit format [OPTIONAL].

def getleadtime(idsec, pdtn, pdt)
145def getleadtime(idsec,pdtn,pdt):
146    """
147    Computes the lead time (in units of hours) from using information from
148    GRIB2 Identification Section (Section 1), Product Definition Template
149    Number, and Product Definition Template (Section 4).
150
151    Parameters
152    ----------
153
154    **`idsec`**: seqeunce containing GRIB2 Identification Section (Section 1).
155
156    **`pdtn`**: GRIB2 Product Definition Template Number
157
158    **`idsec`**: seqeunce containing GRIB2 Product Definition Template (Section 4).
159
160    Returns
161    -------
162
163    **`lt`**: Lead time in units of hours
164    """
165    refdate = datetime.datetime(*idsec[5:11])
166    if pdtn == 8:
167        enddate = datetime.datetime(*pdt[15:21])
168        td = enddate - refdate
169        lt = (td).total_seconds()/3600.0
170    elif pdtn == 9:
171        enddate = datetime.datetime(*pdt[22:28])
172        td = enddate - refdate
173        lt = (td).total_seconds()/3600.0
174    elif pdtn == 10:
175        enddate = datetime.datetime(*pdt[16:22])
176        td = enddate - refdate
177        lt = (td).total_seconds()/3600.0
178    elif pdtn == 11:
179        enddate = datetime.datetime(*pdt[18:24])
180        td = enddate - refdate
181        lt = (td).total_seconds()/3600.0
182    elif pdtn == 12:
183        enddate = datetime.datetime(*pdt[17:23])
184        td = enddate - refdate
185        lt = (td).total_seconds()/3600.0
186    else:
187        lt = pdt[8]*(tables.get_value_from_table(pdt[7],'scale_time_hours'))
188    return int(lt)

Computes the lead time (in units of hours) from 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

lt: Lead time in units of hours

def getduration(pdtn, pdt)
191def getduration(pdtn,pdt):
192    """
193    Computes the duration time (in units of hours) from using information from
194    Product Definition Template Number, and Product Definition Template (Section 4).
195
196    Parameters
197    ----------
198
199    **`pdtn`**: GRIB2 Product Definition Template Number
200
201    **`pdt`**: sequence containing GRIB2 Product Definition Template (Section 4).
202
203    Returns
204    -------
205
206    **`dur`**: Duration time in units of hours
207    """
208    if pdtn == 8:
209        dur = pdt[26]*(tables.get_value_from_table(pdt[25],'scale_time_hours'))
210    elif pdtn == 9:
211        dur = pdt[33]*(tables.get_value_from_table(pdt[32],'scale_time_hours'))
212    elif pdtn == 10:
213        dur = pdt[27]*(tables.get_value_from_table(pdt[26],'scale_time_hours'))
214    elif pdtn == 11:
215        dur = pdt[29]*(tables.get_value_from_table(pdt[28],'scale_time_hours'))
216    elif pdtn == 12:
217        dur = pdt[28]*(tables.get_value_from_table(pdt[27],'scale_time_hours'))
218    else:
219        dur = 0
220    return int(dur)

Computes the duration time (in units of hours) from 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

dur: Duration time in units of hours

def decode_mdl_wx_strings(lus)
223def decode_mdl_wx_strings(lus):
224    """
225    Decode GRIB2 Local Use Section to obtain MDL Weather Strings.  The
226    decode procedure is defined here:
227
228    https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_mdl_temp2-1.shtml
229
230    Parameters
231    ----------
232
233    **`lus`**: GRIB2 Local Use Section containing MDL weather strings.
234
235    Returns
236    -------
237
238    **`list`**: List of weather strings.
239    """
240    assert lus[0] == 1
241    # Unpack information related to the simple packing method
242    # the packed weather string data.
243    ngroups = struct.unpack('>h',lus[1:3])[0]
244    nvalues = struct.unpack('>i',lus[3:7])[0]
245    refvalue = struct.unpack('>i',lus[7:11])[0]
246    dsf = struct.unpack('>h',lus[11:13])[0]
247    nbits = lus[13]
248    datatype = lus[14]
249    if datatype == 0: # Floating point
250        refvalue = np.float32(getieeeint(refvalue)*10**-dsf)
251    elif datatype == 1: # Integer
252        refvalue = np.int32(getieeeint(refvalue)*10**-dsf)
253    #print("TEST:",ngroups,nvalues,refvalue,dsf,nbits,datatype)
254    # Store the "data" part of the packed weather strings as
255    # a binary string.
256    b = bin(int.from_bytes(lus[15:],byteorder='big'))
257    # Generated begin and end values. Note the offset begins at 2
258    # due to the format nature of b (binary string).
259    idxb = list(range(2,len(b),nbits))[0:nvalues-1]
260    idxe = list(range(2+nbits,len(b)+nbits,nbits))[0:nvalues-1]
261    # Iterate over the packed data, converting the nbits space to
262    # and integer, then convert integer to an ASCII character.
263    wxstring = ''
264    for ib,ie in zip(idxb,idxe):
265        wxstring += chr(int(b[ib:ie],2)+refvalue)
266    # Return string as list, split by null character.
267    return wxstring.split('\0')

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

https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_mdl_temp2-1.shtml

Parameters

lus: GRIB2 Local Use Section containing MDL weather strings.

Returns

list: List of weather strings.

def decode_ndfd_wx_strings(lus)
270def decode_ndfd_wx_strings(lus):
271    """
272    Decode GRIB2 Local Use Section to obtain NDFD Weather Strings.  The
273    decode procedure is defined here:
274
275    https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_mdl_temp2-1.shtml
276
277    NOTE: From testing, it seems how the process for packing Section 2 for NDFD
278          Weather grids is different than GMOS and thus the need for a different
279          method for decoding NDFD Wx vs. GMOS Wx.
280
281    Parameters
282    ----------
283
284    **`lus`**: GRIB2 Local Use Section containing NDFD weather strings.
285
286    Returns
287    -------
288
289    **`list`**: List of NDFD weather strings.
290    """
291    assert lus[0] == 1
292    # Unpack information related to the simple packing method
293    # the packed weather string data.
294    ngroups = struct.unpack('>h',lus[1:3])[0]
295    nvalues = struct.unpack('>i',lus[3:7])[0]
296    refvalue = struct.unpack('>i',lus[7:11])[0]
297    dsf = struct.unpack('>h',lus[11:13])[0]
298    nbits = lus[13]
299    datatype = lus[14]
300    if datatype == 0: # Floating point
301        refvalue = np.float32(getieeeint(refvalue)*10**-dsf)
302    elif datatype == 1: # Integer
303        refvalue = np.int32(getieeeint(refvalue)*10**-dsf)
304    # Iterate over the data of section 2 in 4-byte (32-bit)
305    # words OR 2-byte word at the end. Each word is unpacked
306    # as an unsigned integer. Then convert the integer word
307    # to a binary string and fill to the appropriate bit
308    # size (16 or 32) and concatenate to b (binary string).
309    b = ''
310    for i in range(15,len(lus),4):
311        if len(lus)-i < 4:
312            iword = struct.unpack('>H',lus[i:i+2])[0]
313            b += bin(iword).split('b')[1].zfill(16)
314        else:
315            iword = struct.unpack('>I',lus[i:i+4])[0]
316            b += bin(iword).split('b')[1].zfill(32)
317    # Iterate over the binary string (b). For each nbits
318    # chunk, convert to an integer, including the refvalue,
319    # and then convert the int to an ASCII character, then
320    # concatenate to wxstring.
321    wxstring = ''
322    for i in range(0,len(b),nbits):
323        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
324    # Return string as list, split by null character.
325    return list(filter(None,wxstring.split('\0')))

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

https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_mdl_temp2-1.shtml

NOTE: From testing, it seems how the process for packing Section 2 for NDFD Weather grids is different than GMOS and thus the need for a different method for decoding NDFD Wx vs. GMOS Wx.

Parameters

lus: GRIB2 Local Use Section containing NDFD weather strings.

Returns

list: List of NDFD weather strings.

def get_wgrib2_prob_string(probtype, sfacl, svall, sfacu, svalu)
328def get_wgrib2_prob_string(probtype,sfacl,svall,sfacu,svalu):
329    """
330    Return a wgrib2-formatted string explaining probabilistic
331    threshold informaiton.  Logic from wgrib2 source, [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
332    is replicated here.
333
334    Parameters
335    ----------
336
337    **`probtype`**: `int` type of probability (Code Table 4.9).
338
339    **`sfacl`**: `int` scale factor of lower limit.
340
341    **`svall`**: `int` scaled value of lower limit.
342
343    **`sfacu`**: `int` scale factor of upper limit.
344
345    **`svalu`**: `int` scaled value of upper limit.
346
347    Returns
348    -------
349
350    **`str`**: wgrib2-formatted string of probability threshold.
351    """
352    probstr = ''
353    lower = svall/(10**sfacl)
354    upper = svalu/(10**sfacu)
355    if probtype == 0:
356        probstr = 'prob <%g' % (lower)
357    elif probtype == 1:
358        probstr = 'prob >%g' % (upper)
359    elif probtype == 2:
360        if lower == upper:
361            probstr = 'prob =%g' % (lower)
362        else:
363            probstr = 'prob >=%g <%g' % (lower,upper)
364    elif probtype == 3:
365        probstr = 'prob >%g' % (lower)
366    elif probtype == 4:
367        probstr = 'prob <%g' % (upper)
368    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.