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