# grib2io.utils

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

View Source

      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'>): View Source

    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): View Source

    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): View Source

    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): View Source

     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): View Source

    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): View Source

    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): View Source

    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.