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