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
  4from typing import Optional, Union, List
  5from numpy.typing import ArrayLike
  6import itertools
  7import importlib
  8import numpy as np
  9
 10from .section0 import *
 11from .section1 import *
 12from .section3 import *
 13from .section4 import *
 14from .section5 import *
 15from .section6 import *
 16from .originating_centers import *
 17from .ndfd_additionals import *
 18from .cf import *
 19
 20_varinfo_tables_datastore = {}
 21
 22# Note 209 is MRMS
 23GRIB2_DISCIPLINES = [0, 1, 2, 3, 4, 10, 20, 209]
 24
 25AEROSOL_PDTNS = [46, 48]  # 47, 49, 80, 81, 82, 83, 84, 85] <- these don't seem to be working
 26AEROSOL_PARAMS = list(itertools.chain(range(0,19),range(50,82),range(100,113),range(192,197)))
 27
 28def _load_varinfo_tables(modname: str):
 29    """
 30    Load variable information tables from sub modules into the local
 31    varinfo table datastore (_varinfo_tables_datastore).
 32
 33    Parameters
 34    ----------
 35    modname
 36        Module name to extract variable info tables from.
 37    """
 38    module = importlib.import_module(modname, package=__name__)
 39    names = getattr(module, '__all__', [name for name in dir(module) if name.startswith('table_')])
 40    _varinfo_tables_datastore.update({name: getattr(module, name) for name in names})
 41
 42
 43def get_table(table: str, expand: bool=False) -> dict:
 44    """
 45    Return GRIB2 code table as a dictionary.
 46
 47    Parameters
 48    ----------
 49    table
 50        Code table number (e.g. '1.0').
 51
 52        NOTE: Code table '4.1' requires a 3rd value representing the product
 53        discipline (e.g. '4.1.0').
 54    expand
 55        If `True`, expand output dictionary wherever keys are a range.
 56
 57    Returns
 58    -------
 59    get_table
 60        GRIB2 code table as a dictionary.
 61    """
 62    if len(table) == 3 and table == '4.1':
 63        raise Exception('GRIB2 Code Table 4.1 requires a 3rd value representing the discipline.')
 64    if len(table) == 3 and table.startswith('4.2'):
 65        raise Exception('Use function get_varinfo_from_table() for GRIB2 Code Table 4.2')
 66    try:
 67        tbl = globals()['table_'+table.replace('.','_')]
 68        if expand:
 69            _tbl = {}
 70            for k,v in tbl.items():
 71                if '-' in k:
 72                    irng = [int(i) for i in k.split('-')]
 73                    for i in range(irng[0],irng[1]+1):
 74                        _tbl[str(i)] = v
 75                else:
 76                    _tbl[k] = v
 77            tbl = _tbl
 78        return tbl
 79    except(KeyError):
 80        return {}
 81
 82
 83def get_value_from_table(
 84    value: Union[int, str],
 85    table: str,
 86    expand: bool = False,
 87) -> Optional[Union[float, int]]:
 88    """
 89    Return the definition given a GRIB2 code table.
 90
 91    Parameters
 92    ----------
 93    value
 94        Code table value.
 95    table
 96        Code table number.
 97    expand
 98        If `True`, expand output dictionary where keys are a range.
 99
100    Returns
101    -------
102    get_value_from_table
103        Table value or `None` if not found.
104    """
105    try:
106        tbl = get_table(table,expand=expand)
107        value = str(value)
108        return tbl[value]
109    except(KeyError):
110        for k in tbl.keys():
111            if '-' in k:
112                bounds = k.split('-')
113                if value >= bounds[0] and value <= bounds[1]:
114                    return tbl[k]
115        return None
116
117
118def get_varinfo_from_table(
119    discipline: Union[int, str],
120    parmcat: Union[int, str],
121    parmnum: Union[int, str],
122    isNDFD: bool = False,
123):
124    """
125    Return the GRIB2 variable information.
126
127    NOTE: This functions allows for all arguments to be converted to a string
128    type if arguments are integer.
129
130    Parameters
131    ----------
132    discipline
133        Discipline code value of a GRIB2 message.
134    parmcat
135        Parameter Category value of a GRIB2 message.
136    parmnum
137        Parameter Number value of a GRIB2 message.
138    isNDFD: optional
139        If `True`, then attempt to get variable information from the
140        supplemental NDFD tables, otherwise fallback to default tables.
141
142    Returns
143    -------
144    full_name
145        Full name of the GRIB2 variable. "Unknown" if variable is not found.
146    units
147        Units of the GRIB2 variable. "Unknown" if variable is not found.
148    shortName
149        Abbreviated name of the GRIB2 variable. "Unknown" if variable is not
150        found.
151    """
152    template = f'table_4_2_{discipline}_{parmcat}'
153    tbls = []
154    if isNDFD:
155        tbls.append(template+'_ndfd')
156    tbls.append(template)
157    for tbl in tbls:
158        vartbl = None
159        modname = f'.section4_discipline{discipline}'
160        if tbl not in _varinfo_tables_datastore.keys():
161            _load_varinfo_tables(modname)
162        try:
163            vartbl = _varinfo_tables_datastore[tbl][str(parmnum)]
164        except(KeyError):
165            vartbl = ['Unknown','Unknown','Unknown']
166        if vartbl is not None:
167            break
168    return vartbl
169
170
171@lru_cache(maxsize=None)
172def get_shortnames(
173    discipline: Optional[Union[int, str]] = None,
174    parmcat: Optional[Union[int, str]] = None,
175    parmnum: Optional[Union[int, str]] = None,
176    isNDFD: bool = False,
177) -> List[str]:
178    """
179    Return a list of variable shortNames.
180
181    If all 3 args are None, then shortNames from all disciplines, parameter
182    categories, and numbers will be returned.
183
184    Parameters
185    ----------
186    discipline
187        GRIB2 discipline code value.
188    parmcat
189        GRIB2 parameter category value.
190    parmnum
191        Parameter Number value of a GRIB2 message.
192    isNDFD: optional
193        If `True`, signals function to try to get variable information from the
194        supplemental NDFD tables.
195
196    Returns
197    -------
198    get_shortnames
199        list of GRIB2 shortNames.
200    """
201    shortnames = list()
202    if discipline is None:
203        discipline = GRIB2_DISCIPLINES
204    else:
205        discipline = [discipline]
206    if parmcat is None:
207        parmcat = list()
208        for d in discipline:
209            parmcat += list(get_table(f'4.1.{d}').keys())
210    else:
211        parmcat = [parmcat]
212    if parmnum is None:
213        parmnum = list(range(256))
214    else:
215        parmnum = [parmnum]
216    for d in discipline:
217
218        for pc in parmcat:
219            for pn in parmnum:
220                shortnames.append(get_varinfo_from_table(d,pc,pn,isNDFD)[2])
221
222    shortnames = sorted(set(shortnames))
223    try:
224        shortnames.remove('unknown')
225        shortnames.remove('Unknown')
226    except(ValueError):
227        pass
228    return shortnames
229
230
231@lru_cache(maxsize=None)
232def get_metadata_from_shortname(shortname: str):
233    """
234    Provide GRIB2 variable metadata attributes given a GRIB2 shortName.
235
236    Parameters
237    ----------
238    shortname
239        GRIB2 variable shortName.
240
241    Returns
242    -------
243    get_metadata_from_shortname
244        list of dictionary items where each dictionary item contains the
245        variable metadata key:value pairs.
246
247        NOTE: Some variable shortNames will exist in multiple parameter
248        category/number tables according to the GRIB2 discipline.
249    """
250    metadata = []
251    for d in GRIB2_DISCIPLINES:
252        parmcat = list(get_table(f'4.1.{d}').keys())
253        for pc in parmcat:
254            for pn in range(256):
255                varinfo = get_varinfo_from_table(d,pc,pn,False)
256                if shortname == varinfo[2]:
257                    metadata.append(dict(discipline=d,parameterCategory=pc,parameterNumber=pn,
258                                         fullName=varinfo[0],units=varinfo[1]))
259    return metadata
260
261
262def get_wgrib2_level_string(pdtn: int, pdt: ArrayLike) -> str:
263    """
264    Return a string that describes the level or layer of the GRIB2 message.
265
266    The format and language of the string is an exact replica of how wgrib2
267    produces the level/layer string in its inventory output.
268
269    Contents of wgrib2 source,
270    [Level.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Level.c),
271    were converted into a Python dictionary and stored in grib2io as table
272    'wgrib2_level_string'.
273
274    Parameters
275    ----------
276    pdtn
277        GRIB2 Product Definition Template Number
278    pdt
279        Sequence containing GRIB2 Product Definition Template (Section 4).
280
281    Returns
282    -------
283    get_wgrib2_level_string
284        wgrib2-formatted level/layer string.
285    """
286    lvlstr = ''
287    if pdtn == 32:
288        return 'no_level'
289    elif pdtn == 48:
290        idxs = slice(20,26)
291    else:
292        idxs = slice(9,15)
293    type1, sfac1, sval1, type2, sfac2, sval2 = map(int,pdt[idxs])
294    val1 = sval1/10**sfac1
295    if type1 in [100,108]: val1 *= 0.01
296    if type2 != 255:
297        # Layer
298        #assert type2 == type1, "Surface types are not equal: %g - %g" % (type1,type2)
299        val2 = sval2/10**sfac2
300        if type2 in [100,108]: val2 *= 0.01
301        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[1]
302        vals = (val1,val2)
303    else:
304        # Level
305        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[0]
306        vals = (val1)
307    if '%g' in lvlstr: lvlstr %= vals
308    return lvlstr
309
310
311def _build_aerosol_shortname(obj) -> str:
312    """
313    """
314    _OPTICAL_WAVELENGTH_MAPPING = get_table('aerosol_optical_wavelength')
315    _LEVEL_MAPPING = get_table('aerosol_level')
316    _PARAMETER_MAPPING = get_table('aerosol_parameter')
317    _AERO_TYPE_MAPPING = get_table('aerosol_type')
318
319    # Build shortname from aerosol components
320    parts = []
321
322    # Get aerosol type
323    aero_type = str(obj.typeOfAerosol.value) if obj.typeOfAerosol is not None else ""
324
325    # Add size information if applicable
326    aero_size = ""
327    if hasattr(obj, 'scaledValueOfFirstSize'):
328        if float(obj.scaledValueOfFirstSize) > 0:
329            first_size = float(obj.scaledValueOfFirstSize)
330
331            # Map common PM sizes
332            size_map = {1: 'pm1', 25: 'pm25', 10: 'pm10', 20: 'pm20'}
333            aero_size = size_map.get(first_size, f"pm{int(first_size)}")
334
335            # Check for size intervals
336            if (hasattr(obj, 'scaledValueOfSecondSize') and
337                obj.scaledValueOfSecondSize is not None and
338                hasattr(obj, 'typeOfIntervalForAerosolSize') and
339                obj.typeOfIntervalForAerosolSize.value == 6):
340
341                second_size = float(obj.scaledValueOfSecondSize)
342                if second_size > 0:
343                    if (first_size == 2.5 and second_size == 10):
344                        aero_size = 'PM25to10'
345                    elif (first_size == 10 and second_size == 20):
346                        aero_size = 'PM10to20'
347                    else:
348                        aero_size = f"PM{int(first_size)}to{int(second_size)}"
349
350    # Add optical and wavelength information
351    var_wavelength = ''
352    if (hasattr(obj, 'parameterNumber') and
353        hasattr(obj, 'scaledValueOfFirstWavelength') and
354        hasattr(obj, 'scaledValueOfSecondWavelength')):
355
356        optical_type = str(obj.parameterNumber)
357        if obj.scaledValueOfFirstWavelength > 0:
358            first_wl = obj.scaledValueOfFirstWavelength
359            second_wl = obj.scaledValueOfSecondWavelength
360
361            # Special case for AE between 440-870nm
362            if optical_type == '111' and first_wl == 440 and second_wl == 870:
363                key = (optical_type, '440TO870')
364            else:
365                # Find matching wavelength band
366                for wl_key, wl_info in _OPTICAL_WAVELENGTH_MAPPING.items():
367                    if (wl_key[0] == optical_type and  # Check optical_type first
368                        int(wl_key[1]) == first_wl and
369                        (second_wl is None or int(wl_key[2]) == second_wl)):
370                        key = wl_key
371                        break
372                else:
373                    # If no match found, use raw values
374                    key = (optical_type, str(first_wl),
375                          str(second_wl) if second_wl is not None else '')
376
377            # FIX THIS...
378            if key in _OPTICAL_WAVELENGTH_MAPPING.keys():
379                var_wavelength = _OPTICAL_WAVELENGTH_MAPPING[key]
380
381    # Add level information
382    level_str = ''
383    if hasattr(obj, 'typeOfFirstFixedSurface'):
384        first_level = str(obj.typeOfFirstFixedSurface.value)
385        first_value = str(obj.scaledValueOfFirstFixedSurface) if obj.scaledValueOfFirstFixedSurface > 0 else ''
386        if first_level in _LEVEL_MAPPING:
387            level_str = f"{_LEVEL_MAPPING[first_level]}{first_value}"
388
389    # Get parameter type
390    param = ''
391    if hasattr(obj, 'parameterNumber'):
392        param_num = str(obj.parameterNumber)
393        if param_num in _PARAMETER_MAPPING:
394            param = _PARAMETER_MAPPING[param_num]
395
396    # Build the final shortname
397    if var_wavelength and aero_type in _AERO_TYPE_MAPPING:
398        shortname = f"{_AERO_TYPE_MAPPING[aero_type]}{var_wavelength}"
399    elif aero_type in _AERO_TYPE_MAPPING:
400        parts = []
401        if level_str:
402            parts.append(level_str)
403        parts.append(_AERO_TYPE_MAPPING[aero_type])
404        if aero_size:
405            parts.append(aero_size)
406        if param:
407            parts.append(param)
408        shortname = '_'.join(parts) if len(parts) > 1 else parts[0]
409    else:
410        return get_varinfo_from_table(obj.section0[2], *obj.section4[2:4], isNDFD=obj._isNDFD)[2]
411
412    return shortname
413
414
415@lru_cache(maxsize=None)
416def get_table_names(var_tables: bool=False) -> tuple:
417    """
418    Return the names of available GRIB2 tables.
419
420    The table dictionaries as they exist in grib2io are prefixed
421    with "table_". When accessing a table through the available
422    functions, the prefix is not necessary.
423
424    Parameters
425    ----------
426    var_tables : bool, optional
427        If True, include names of variable tables.
428        If False (default), include only non-variable tables.
429
430    Returns
431    -------
432    tuple of str
433        A tuple sorted names of available tables.
434    """
435    tables = [
436        name.replace("table_","") for name, val in globals().items()
437        if isinstance(val, dict) and name.startswith("table_")
438    ]
439
440    tables = [
441        t.replace("_",".") if t.startswith(tuple("0123456789")) else t for t in tables
442    ]
443
444    if var_tables:
445        for d in GRIB2_DISCIPLINES:
446            modname = f'.section4_discipline{d}'
447            _load_varinfo_tables(modname)
448        vt = [t.replace("table_","").replace("_",".") for t in _varinfo_tables_datastore.keys()]
449        tables.extend(vt)
450
451    return tuple(sorted(tables))
GRIB2_DISCIPLINES = [0, 1, 2, 3, 4, 10, 20, 209]
AEROSOL_PDTNS = [46, 48]
AEROSOL_PARAMS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 192, 193, 194, 195, 196]
def get_table(table: str, expand: bool = False) -> dict:
44def get_table(table: str, expand: bool=False) -> dict:
45    """
46    Return GRIB2 code table as a dictionary.
47
48    Parameters
49    ----------
50    table
51        Code table number (e.g. '1.0').
52
53        NOTE: Code table '4.1' requires a 3rd value representing the product
54        discipline (e.g. '4.1.0').
55    expand
56        If `True`, expand output dictionary wherever keys are a range.
57
58    Returns
59    -------
60    get_table
61        GRIB2 code table as a dictionary.
62    """
63    if len(table) == 3 and table == '4.1':
64        raise Exception('GRIB2 Code Table 4.1 requires a 3rd value representing the discipline.')
65    if len(table) == 3 and table.startswith('4.2'):
66        raise Exception('Use function get_varinfo_from_table() for GRIB2 Code Table 4.2')
67    try:
68        tbl = globals()['table_'+table.replace('.','_')]
69        if expand:
70            _tbl = {}
71            for k,v in tbl.items():
72                if '-' in k:
73                    irng = [int(i) for i in k.split('-')]
74                    for i in range(irng[0],irng[1]+1):
75                        _tbl[str(i)] = v
76                else:
77                    _tbl[k] = v
78            tbl = _tbl
79        return tbl
80    except(KeyError):
81        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.
def get_value_from_table( value: Union[int, str], table: str, expand: bool = False) -> Union[float, int, NoneType]:
 84def get_value_from_table(
 85    value: Union[int, str],
 86    table: str,
 87    expand: bool = False,
 88) -> Optional[Union[float, int]]:
 89    """
 90    Return the definition given a GRIB2 code table.
 91
 92    Parameters
 93    ----------
 94    value
 95        Code table value.
 96    table
 97        Code table number.
 98    expand
 99        If `True`, expand output dictionary where keys are a range.
100
101    Returns
102    -------
103    get_value_from_table
104        Table value or `None` if not found.
105    """
106    try:
107        tbl = get_table(table,expand=expand)
108        value = str(value)
109        return tbl[value]
110    except(KeyError):
111        for k in tbl.keys():
112            if '-' in k:
113                bounds = k.split('-')
114                if value >= bounds[0] and value <= bounds[1]:
115                    return tbl[k]
116        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.
def get_varinfo_from_table( discipline: Union[int, str], parmcat: Union[int, str], parmnum: Union[int, str], isNDFD: bool = False):
119def get_varinfo_from_table(
120    discipline: Union[int, str],
121    parmcat: Union[int, str],
122    parmnum: Union[int, str],
123    isNDFD: bool = False,
124):
125    """
126    Return the GRIB2 variable information.
127
128    NOTE: This functions allows for all arguments to be converted to a string
129    type if arguments are integer.
130
131    Parameters
132    ----------
133    discipline
134        Discipline code value of a GRIB2 message.
135    parmcat
136        Parameter Category value of a GRIB2 message.
137    parmnum
138        Parameter Number value of a GRIB2 message.
139    isNDFD: optional
140        If `True`, then attempt to get variable information from the
141        supplemental NDFD tables, otherwise fallback to default tables.
142
143    Returns
144    -------
145    full_name
146        Full name of the GRIB2 variable. "Unknown" if variable is not found.
147    units
148        Units of the GRIB2 variable. "Unknown" if variable is not found.
149    shortName
150        Abbreviated name of the GRIB2 variable. "Unknown" if variable is not
151        found.
152    """
153    template = f'table_4_2_{discipline}_{parmcat}'
154    tbls = []
155    if isNDFD:
156        tbls.append(template+'_ndfd')
157    tbls.append(template)
158    for tbl in tbls:
159        vartbl = None
160        modname = f'.section4_discipline{discipline}'
161        if tbl not in _varinfo_tables_datastore.keys():
162            _load_varinfo_tables(modname)
163        try:
164            vartbl = _varinfo_tables_datastore[tbl][str(parmnum)]
165        except(KeyError):
166            vartbl = ['Unknown','Unknown','Unknown']
167        if vartbl is not None:
168            break
169    return vartbl

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, then attempt to get variable information from the supplemental NDFD tables, otherwise fallback to default 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.
@lru_cache(maxsize=None)
def get_shortnames( discipline: Union[int, str, NoneType] = None, parmcat: Union[int, str, NoneType] = None, parmnum: Union[int, str, NoneType] = None, isNDFD: bool = False) -> List[str]:
172@lru_cache(maxsize=None)
173def get_shortnames(
174    discipline: Optional[Union[int, str]] = None,
175    parmcat: Optional[Union[int, str]] = None,
176    parmnum: Optional[Union[int, str]] = None,
177    isNDFD: bool = False,
178) -> List[str]:
179    """
180    Return a list of variable shortNames.
181
182    If all 3 args are None, then shortNames from all disciplines, parameter
183    categories, and numbers will be returned.
184
185    Parameters
186    ----------
187    discipline
188        GRIB2 discipline code value.
189    parmcat
190        GRIB2 parameter category value.
191    parmnum
192        Parameter Number value of a GRIB2 message.
193    isNDFD: optional
194        If `True`, signals function to try to get variable information from the
195        supplemental NDFD tables.
196
197    Returns
198    -------
199    get_shortnames
200        list of GRIB2 shortNames.
201    """
202    shortnames = list()
203    if discipline is None:
204        discipline = GRIB2_DISCIPLINES
205    else:
206        discipline = [discipline]
207    if parmcat is None:
208        parmcat = list()
209        for d in discipline:
210            parmcat += list(get_table(f'4.1.{d}').keys())
211    else:
212        parmcat = [parmcat]
213    if parmnum is None:
214        parmnum = list(range(256))
215    else:
216        parmnum = [parmnum]
217    for d in discipline:
218
219        for pc in parmcat:
220            for pn in parmnum:
221                shortnames.append(get_varinfo_from_table(d,pc,pn,isNDFD)[2])
222
223    shortnames = sorted(set(shortnames))
224    try:
225        shortnames.remove('unknown')
226        shortnames.remove('Unknown')
227    except(ValueError):
228        pass
229    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.
@lru_cache(maxsize=None)
def get_metadata_from_shortname(shortname: str):
232@lru_cache(maxsize=None)
233def get_metadata_from_shortname(shortname: str):
234    """
235    Provide GRIB2 variable metadata attributes given a GRIB2 shortName.
236
237    Parameters
238    ----------
239    shortname
240        GRIB2 variable shortName.
241
242    Returns
243    -------
244    get_metadata_from_shortname
245        list of dictionary items where each dictionary item contains the
246        variable metadata key:value pairs.
247
248        NOTE: Some variable shortNames will exist in multiple parameter
249        category/number tables according to the GRIB2 discipline.
250    """
251    metadata = []
252    for d in GRIB2_DISCIPLINES:
253        parmcat = list(get_table(f'4.1.{d}').keys())
254        for pc in parmcat:
255            for pn in range(256):
256                varinfo = get_varinfo_from_table(d,pc,pn,False)
257                if shortname == varinfo[2]:
258                    metadata.append(dict(discipline=d,parameterCategory=pc,parameterNumber=pn,
259                                         fullName=varinfo[0],units=varinfo[1]))
260    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.

def get_wgrib2_level_string( pdtn: int, pdt: Union[Buffer, numpy._typing._array_like._SupportsArray[numpy.dtype[Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[Any]]], complex, bytes, str, numpy._typing._nested_sequence._NestedSequence[complex | bytes | str]]) -> str:
263def get_wgrib2_level_string(pdtn: int, pdt: ArrayLike) -> str:
264    """
265    Return a string that describes the level or layer of the GRIB2 message.
266
267    The format and language of the string is an exact replica of how wgrib2
268    produces the level/layer string in its inventory output.
269
270    Contents of wgrib2 source,
271    [Level.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Level.c),
272    were converted into a Python dictionary and stored in grib2io as table
273    'wgrib2_level_string'.
274
275    Parameters
276    ----------
277    pdtn
278        GRIB2 Product Definition Template Number
279    pdt
280        Sequence containing GRIB2 Product Definition Template (Section 4).
281
282    Returns
283    -------
284    get_wgrib2_level_string
285        wgrib2-formatted level/layer string.
286    """
287    lvlstr = ''
288    if pdtn == 32:
289        return 'no_level'
290    elif pdtn == 48:
291        idxs = slice(20,26)
292    else:
293        idxs = slice(9,15)
294    type1, sfac1, sval1, type2, sfac2, sval2 = map(int,pdt[idxs])
295    val1 = sval1/10**sfac1
296    if type1 in [100,108]: val1 *= 0.01
297    if type2 != 255:
298        # Layer
299        #assert type2 == type1, "Surface types are not equal: %g - %g" % (type1,type2)
300        val2 = sval2/10**sfac2
301        if type2 in [100,108]: val2 *= 0.01
302        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[1]
303        vals = (val1,val2)
304    else:
305        # Level
306        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[0]
307        vals = (val1)
308    if '%g' in lvlstr: lvlstr %= vals
309    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.
@lru_cache(maxsize=None)
def get_table_names(var_tables: bool = False) -> tuple:
416@lru_cache(maxsize=None)
417def get_table_names(var_tables: bool=False) -> tuple:
418    """
419    Return the names of available GRIB2 tables.
420
421    The table dictionaries as they exist in grib2io are prefixed
422    with "table_". When accessing a table through the available
423    functions, the prefix is not necessary.
424
425    Parameters
426    ----------
427    var_tables : bool, optional
428        If True, include names of variable tables.
429        If False (default), include only non-variable tables.
430
431    Returns
432    -------
433    tuple of str
434        A tuple sorted names of available tables.
435    """
436    tables = [
437        name.replace("table_","") for name, val in globals().items()
438        if isinstance(val, dict) and name.startswith("table_")
439    ]
440
441    tables = [
442        t.replace("_",".") if t.startswith(tuple("0123456789")) else t for t in tables
443    ]
444
445    if var_tables:
446        for d in GRIB2_DISCIPLINES:
447            modname = f'.section4_discipline{d}'
448            _load_varinfo_tables(modname)
449        vt = [t.replace("table_","").replace("_",".") for t in _varinfo_tables_datastore.keys()]
450        tables.extend(vt)
451
452    return tuple(sorted(tables))

Return the names of available GRIB2 tables.

The table dictionaries as they exist in grib2io are prefixed with "table_". When accessing a table through the available functions, the prefix is not necessary.

Parameters
  • var_tables (bool, optional): If True, include names of variable tables. If False (default), include only non-variable tables.
Returns
  • tuple of str: A tuple sorted names of available tables.