grib2io.tables
Functions for retrieving data from NCEP GRIB2 Tables.
1"""Functions for retrieving data from NCEP GRIB2 Tables.""" 2 3from functools import lru_cache 4 5from typing import Optional, Union, List 6from numpy.typing import ArrayLike 7 8from .section0 import * 9from .section1 import * 10from .section3 import * 11from .section4 import * 12from .section5 import * 13from .section6 import * 14from .originating_centers import * 15 16GRIB2_DISCIPLINES = [0, 1, 2, 3, 4, 10, 20] 17 18def get_table(table: str, expand: bool=False) -> dict: 19 """ 20 Return GRIB2 code table as a dictionary. 21 22 Parameters 23 ---------- 24 table 25 Code table number (e.g. '1.0'). 26 27 NOTE: Code table '4.1' requires a 3rd value representing the product 28 discipline (e.g. '4.1.0'). 29 expand 30 If `True`, expand output dictionary wherever keys are a range. 31 32 Returns 33 ------- 34 get_table 35 GRIB2 code table as a dictionary. 36 """ 37 if len(table) == 3 and table == '4.1': 38 raise Exception('GRIB2 Code Table 4.1 requires a 3rd value representing the discipline.') 39 if len(table) == 3 and table.startswith('4.2'): 40 raise Exception('Use function get_varinfo_from_table() for GRIB2 Code Table 4.2') 41 try: 42 tbl = globals()['table_'+table.replace('.','_')] 43 if expand: 44 _tbl = {} 45 for k,v in tbl.items(): 46 if '-' in k: 47 irng = [int(i) for i in k.split('-')] 48 for i in range(irng[0],irng[1]+1): 49 _tbl[str(i)] = v 50 else: 51 _tbl[k] = v 52 tbl = _tbl 53 return tbl 54 except(KeyError): 55 return {} 56 57 58def get_value_from_table( 59 value: Union[int, str], 60 table: str, 61 expand: bool = False, 62) -> Optional[Union[float, int]]: 63 """ 64 Return the definition given a GRIB2 code table. 65 66 Parameters 67 ---------- 68 value 69 Code table value. 70 table 71 Code table number. 72 expand 73 If `True`, expand output dictionary where keys are a range. 74 75 Returns 76 ------- 77 get_value_from_table 78 Table value or `None` if not found. 79 """ 80 try: 81 tbl = get_table(table,expand=expand) 82 value = str(value) 83 return tbl[value] 84 except(KeyError): 85 for k in tbl.keys(): 86 if '-' in k: 87 bounds = k.split('-') 88 if value >= bounds[0] and value <= bounds[1]: 89 return tbl[k] 90 return None 91 92 93def get_varinfo_from_table( 94 discipline: Union[int, str], 95 parmcat: Union[int, str], 96 parmnum: Union[int, str], 97 isNDFD: bool = False, 98): 99 """ 100 Return the GRIB2 variable information. 101 102 NOTE: This functions allows for all arguments to be converted to a string 103 type if arguments are integer. 104 105 Parameters 106 ---------- 107 discipline 108 Discipline code value of a GRIB2 message. 109 parmcat 110 Parameter Category value of a GRIB2 message. 111 parmnum 112 Parameter Number value of a GRIB2 message. 113 isNDFD: optional 114 If `True`, signals function to try to get variable information from the 115 supplemental NDFD tables. 116 117 Returns 118 ------- 119 full_name 120 Full name of the GRIB2 variable. "Unknown" if variable is not found. 121 units 122 Units of the GRIB2 variable. "Unknown" if variable is not found. 123 shortName 124 Abbreviated name of the GRIB2 variable. "Unknown" if variable is not 125 found. 126 """ 127 if isNDFD: 128 try: 129 tblname = f'table_4_2_{discipline}_{parmcat}_ndfd' 130 modname = f'.section4_discipline{discipline}' 131 exec('from '+modname+' import *') 132 return locals()[tblname][str(parmnum)] 133 except(ImportError,KeyError): 134 pass 135 try: 136 tblname = f'table_4_2_{discipline}_{parmcat}' 137 modname = f'.section4_discipline{discipline}' 138 exec('from '+modname+' import *') 139 return locals()[tblname][str(parmnum)] 140 except(ImportError,KeyError): 141 return ['Unknown','Unknown','Unknown'] 142 143 144@lru_cache(maxsize=None) 145def get_shortnames( 146 discipline: Optional[Union[int, str]] = None, 147 parmcat: Optional[Union[int, str]] = None, 148 parmnum: Optional[Union[int, str]] = None, 149 isNDFD: bool = False, 150) -> List[str]: 151 """ 152 Return a list of variable shortNames. 153 154 If all 3 args are None, then shortNames from all disciplines, parameter 155 categories, and numbers will be returned. 156 157 Parameters 158 ---------- 159 discipline 160 GRIB2 discipline code value. 161 parmcat 162 GRIB2 parameter category value. 163 parmnum 164 Parameter Number value of a GRIB2 message. 165 isNDFD: optional 166 If `True`, signals function to try to get variable information from the 167 supplemental NDFD tables. 168 169 Returns 170 ------- 171 get_shortnames 172 list of GRIB2 shortNames. 173 """ 174 shortnames = list() 175 if discipline is None: 176 discipline = GRIB2_DISCIPLINES 177 else: 178 discipline = [discipline] 179 if parmcat is None: 180 parmcat = list() 181 for d in discipline: 182 parmcat += list(get_table(f'4.1.{d}').keys()) 183 else: 184 parmcat = [parmcat] 185 if parmnum is None: 186 parmnum = list(range(256)) 187 else: 188 parmnum = [parmnum] 189 for d in discipline: 190 191 for pc in parmcat: 192 for pn in parmnum: 193 shortnames.append(get_varinfo_from_table(d,pc,pn,isNDFD)[2]) 194 195 shortnames = sorted(set(shortnames)) 196 try: 197 shortnames.remove('unknown') 198 shortnames.remove('Unknown') 199 except(ValueError): 200 pass 201 return shortnames 202 203 204@lru_cache(maxsize=None) 205def get_metadata_from_shortname(shortname: str): 206 """ 207 Provide GRIB2 variable metadata attributes given a GRIB2 shortName. 208 209 Parameters 210 ---------- 211 shortname 212 GRIB2 variable shortName. 213 214 Returns 215 ------- 216 get_metadata_from_shortname 217 list of dictionary items where each dictionary item contains the 218 variable metadata key:value pairs. 219 220 NOTE: Some variable shortNames will exist in multiple parameter 221 category/number tables according to the GRIB2 discipline. 222 """ 223 metadata = [] 224 for d in GRIB2_DISCIPLINES: 225 parmcat = list(get_table(f'4.1.{d}').keys()) 226 for pc in parmcat: 227 for pn in range(256): 228 varinfo = get_varinfo_from_table(d,pc,pn,False) 229 if shortname == varinfo[2]: 230 metadata.append(dict(discipline=d,parameterCategory=pc,parameterNumber=pn, 231 fullName=varinfo[0],units=varinfo[1])) 232 return metadata 233 234 235def get_wgrib2_level_string(pdtn: int, pdt: ArrayLike) -> str: 236 """ 237 Return a string that describes the level or layer of the GRIB2 message. 238 239 The format and language of the string is an exact replica of how wgrib2 240 produces the level/layer string in its inventory output. 241 242 Contents of wgrib2 source, 243 [Level.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Level.c), 244 were converted into a Python dictionary and stored in grib2io as table 245 'wgrib2_level_string'. 246 247 Parameters 248 ---------- 249 pdtn 250 GRIB2 Product Definition Template Number 251 pdt 252 Sequence containing GRIB2 Product Definition Template (Section 4). 253 254 Returns 255 ------- 256 get_wgrib2_level_string 257 wgrib2-formatted level/layer string. 258 """ 259 lvlstr = '' 260 if pdtn == 32: 261 return 'no_level' 262 elif pdtn == 48: 263 idxs = slice(20,26) 264 else: 265 idxs = slice(9,15) 266 type1, sfac1, sval1, type2, sfac2, sval2 = map(int,pdt[idxs]) 267 val1 = sval1/10**sfac1 268 if type1 in [100,108]: val1 *= 0.01 269 if type2 != 255: 270 # Layer 271 #assert type2 == type1, "Surface types are not equal: %g - %g" % (type1,type2) 272 val2 = sval2/10**sfac2 273 if type2 in [100,108]: val2 *= 0.01 274 lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[1] 275 vals = (val1,val2) 276 else: 277 # Level 278 lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[0] 279 vals = (val1) 280 if '%g' in lvlstr: lvlstr %= vals 281 return lvlstr
19def get_table(table: str, expand: bool=False) -> dict: 20 """ 21 Return GRIB2 code table as a dictionary. 22 23 Parameters 24 ---------- 25 table 26 Code table number (e.g. '1.0'). 27 28 NOTE: Code table '4.1' requires a 3rd value representing the product 29 discipline (e.g. '4.1.0'). 30 expand 31 If `True`, expand output dictionary wherever keys are a range. 32 33 Returns 34 ------- 35 get_table 36 GRIB2 code table as a dictionary. 37 """ 38 if len(table) == 3 and table == '4.1': 39 raise Exception('GRIB2 Code Table 4.1 requires a 3rd value representing the discipline.') 40 if len(table) == 3 and table.startswith('4.2'): 41 raise Exception('Use function get_varinfo_from_table() for GRIB2 Code Table 4.2') 42 try: 43 tbl = globals()['table_'+table.replace('.','_')] 44 if expand: 45 _tbl = {} 46 for k,v in tbl.items(): 47 if '-' in k: 48 irng = [int(i) for i in k.split('-')] 49 for i in range(irng[0],irng[1]+1): 50 _tbl[str(i)] = v 51 else: 52 _tbl[k] = v 53 tbl = _tbl 54 return tbl 55 except(KeyError): 56 return {}
Return GRIB2 code table as a dictionary.
Parameters
- table: Code table number (e.g. '1.0').
NOTE: Code table '4.1' requires a 3rd value representing the product discipline (e.g. '4.1.0').
- expand: If
True
, expand output dictionary wherever keys are a range.
Returns
- get_table: GRIB2 code table as a dictionary.
59def get_value_from_table( 60 value: Union[int, str], 61 table: str, 62 expand: bool = False, 63) -> Optional[Union[float, int]]: 64 """ 65 Return the definition given a GRIB2 code table. 66 67 Parameters 68 ---------- 69 value 70 Code table value. 71 table 72 Code table number. 73 expand 74 If `True`, expand output dictionary where keys are a range. 75 76 Returns 77 ------- 78 get_value_from_table 79 Table value or `None` if not found. 80 """ 81 try: 82 tbl = get_table(table,expand=expand) 83 value = str(value) 84 return tbl[value] 85 except(KeyError): 86 for k in tbl.keys(): 87 if '-' in k: 88 bounds = k.split('-') 89 if value >= bounds[0] and value <= bounds[1]: 90 return tbl[k] 91 return None
Return the definition given a GRIB2 code table.
Parameters
- value: Code table value.
- table: Code table number.
- expand: If
True
, expand output dictionary where keys are a range.
Returns
- get_value_from_table: Table value or
None
if not found.
94def get_varinfo_from_table( 95 discipline: Union[int, str], 96 parmcat: Union[int, str], 97 parmnum: Union[int, str], 98 isNDFD: bool = False, 99): 100 """ 101 Return the GRIB2 variable information. 102 103 NOTE: This functions allows for all arguments to be converted to a string 104 type if arguments are integer. 105 106 Parameters 107 ---------- 108 discipline 109 Discipline code value of a GRIB2 message. 110 parmcat 111 Parameter Category value of a GRIB2 message. 112 parmnum 113 Parameter Number value of a GRIB2 message. 114 isNDFD: optional 115 If `True`, signals function to try to get variable information from the 116 supplemental NDFD tables. 117 118 Returns 119 ------- 120 full_name 121 Full name of the GRIB2 variable. "Unknown" if variable is not found. 122 units 123 Units of the GRIB2 variable. "Unknown" if variable is not found. 124 shortName 125 Abbreviated name of the GRIB2 variable. "Unknown" if variable is not 126 found. 127 """ 128 if isNDFD: 129 try: 130 tblname = f'table_4_2_{discipline}_{parmcat}_ndfd' 131 modname = f'.section4_discipline{discipline}' 132 exec('from '+modname+' import *') 133 return locals()[tblname][str(parmnum)] 134 except(ImportError,KeyError): 135 pass 136 try: 137 tblname = f'table_4_2_{discipline}_{parmcat}' 138 modname = f'.section4_discipline{discipline}' 139 exec('from '+modname+' import *') 140 return locals()[tblname][str(parmnum)] 141 except(ImportError,KeyError): 142 return ['Unknown','Unknown','Unknown']
Return the GRIB2 variable information.
NOTE: This functions allows for all arguments to be converted to a string type if arguments are integer.
Parameters
- discipline: Discipline code value of a GRIB2 message.
- parmcat: Parameter Category value of a GRIB2 message.
- parmnum: Parameter Number value of a GRIB2 message.
- isNDFD (optional):
If
True
, signals function to try to get variable information from the supplemental NDFD tables.
Returns
- full_name: Full name of the GRIB2 variable. "Unknown" if variable is not found.
- units: Units of the GRIB2 variable. "Unknown" if variable is not found.
- shortName: Abbreviated name of the GRIB2 variable. "Unknown" if variable is not found.
145@lru_cache(maxsize=None) 146def get_shortnames( 147 discipline: Optional[Union[int, str]] = None, 148 parmcat: Optional[Union[int, str]] = None, 149 parmnum: Optional[Union[int, str]] = None, 150 isNDFD: bool = False, 151) -> List[str]: 152 """ 153 Return a list of variable shortNames. 154 155 If all 3 args are None, then shortNames from all disciplines, parameter 156 categories, and numbers will be returned. 157 158 Parameters 159 ---------- 160 discipline 161 GRIB2 discipline code value. 162 parmcat 163 GRIB2 parameter category value. 164 parmnum 165 Parameter Number value of a GRIB2 message. 166 isNDFD: optional 167 If `True`, signals function to try to get variable information from the 168 supplemental NDFD tables. 169 170 Returns 171 ------- 172 get_shortnames 173 list of GRIB2 shortNames. 174 """ 175 shortnames = list() 176 if discipline is None: 177 discipline = GRIB2_DISCIPLINES 178 else: 179 discipline = [discipline] 180 if parmcat is None: 181 parmcat = list() 182 for d in discipline: 183 parmcat += list(get_table(f'4.1.{d}').keys()) 184 else: 185 parmcat = [parmcat] 186 if parmnum is None: 187 parmnum = list(range(256)) 188 else: 189 parmnum = [parmnum] 190 for d in discipline: 191 192 for pc in parmcat: 193 for pn in parmnum: 194 shortnames.append(get_varinfo_from_table(d,pc,pn,isNDFD)[2]) 195 196 shortnames = sorted(set(shortnames)) 197 try: 198 shortnames.remove('unknown') 199 shortnames.remove('Unknown') 200 except(ValueError): 201 pass 202 return shortnames
Return a list of variable shortNames.
If all 3 args are None, then shortNames from all disciplines, parameter categories, and numbers will be returned.
Parameters
- discipline: GRIB2 discipline code value.
- parmcat: GRIB2 parameter category value.
- parmnum: Parameter Number value of a GRIB2 message.
- isNDFD (optional):
If
True
, signals function to try to get variable information from the supplemental NDFD tables.
Returns
- get_shortnames: list of GRIB2 shortNames.
205@lru_cache(maxsize=None) 206def get_metadata_from_shortname(shortname: str): 207 """ 208 Provide GRIB2 variable metadata attributes given a GRIB2 shortName. 209 210 Parameters 211 ---------- 212 shortname 213 GRIB2 variable shortName. 214 215 Returns 216 ------- 217 get_metadata_from_shortname 218 list of dictionary items where each dictionary item contains the 219 variable metadata key:value pairs. 220 221 NOTE: Some variable shortNames will exist in multiple parameter 222 category/number tables according to the GRIB2 discipline. 223 """ 224 metadata = [] 225 for d in GRIB2_DISCIPLINES: 226 parmcat = list(get_table(f'4.1.{d}').keys()) 227 for pc in parmcat: 228 for pn in range(256): 229 varinfo = get_varinfo_from_table(d,pc,pn,False) 230 if shortname == varinfo[2]: 231 metadata.append(dict(discipline=d,parameterCategory=pc,parameterNumber=pn, 232 fullName=varinfo[0],units=varinfo[1])) 233 return metadata
Provide GRIB2 variable metadata attributes given a GRIB2 shortName.
Parameters
- shortname: GRIB2 variable shortName.
Returns
- get_metadata_from_shortname: list of dictionary items where each dictionary item contains the variable metadata key:value pairs.
NOTE: Some variable shortNames will exist in multiple parameter category/number tables according to the GRIB2 discipline.
236def get_wgrib2_level_string(pdtn: int, pdt: ArrayLike) -> str: 237 """ 238 Return a string that describes the level or layer of the GRIB2 message. 239 240 The format and language of the string is an exact replica of how wgrib2 241 produces the level/layer string in its inventory output. 242 243 Contents of wgrib2 source, 244 [Level.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Level.c), 245 were converted into a Python dictionary and stored in grib2io as table 246 'wgrib2_level_string'. 247 248 Parameters 249 ---------- 250 pdtn 251 GRIB2 Product Definition Template Number 252 pdt 253 Sequence containing GRIB2 Product Definition Template (Section 4). 254 255 Returns 256 ------- 257 get_wgrib2_level_string 258 wgrib2-formatted level/layer string. 259 """ 260 lvlstr = '' 261 if pdtn == 32: 262 return 'no_level' 263 elif pdtn == 48: 264 idxs = slice(20,26) 265 else: 266 idxs = slice(9,15) 267 type1, sfac1, sval1, type2, sfac2, sval2 = map(int,pdt[idxs]) 268 val1 = sval1/10**sfac1 269 if type1 in [100,108]: val1 *= 0.01 270 if type2 != 255: 271 # Layer 272 #assert type2 == type1, "Surface types are not equal: %g - %g" % (type1,type2) 273 val2 = sval2/10**sfac2 274 if type2 in [100,108]: val2 *= 0.01 275 lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[1] 276 vals = (val1,val2) 277 else: 278 # Level 279 lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[0] 280 vals = (val1) 281 if '%g' in lvlstr: lvlstr %= vals 282 return lvlstr
Return a string that describes the level or layer of the GRIB2 message.
The format and language of the string is an exact replica of how wgrib2 produces the level/layer string in its inventory output.
Contents of wgrib2 source, Level.c, were converted into a Python dictionary and stored in grib2io as table 'wgrib2_level_string'.
Parameters
- pdtn: GRIB2 Product Definition Template Number
- pdt: Sequence containing GRIB2 Product Definition Template (Section 4).
Returns
- get_wgrib2_level_string: wgrib2-formatted level/layer string.