grib2io.tables API documentation

# grib2io.tables

Functions for retrieving data from NCEP GRIB2 Tables.

View Source

      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            pass
    166        if vartbl is not None:
    167            break
    168    if vartbl is None:
    169        vartbl = ['Unknown','Unknown','Unknown']
    170    return vartbl
    171
    172
    173@lru_cache(maxsize=None)
    174def get_shortnames(
    175    discipline: Optional[Union[int, str]] = None,
    176    parmcat: Optional[Union[int, str]] = None,
    177    parmnum: Optional[Union[int, str]] = None,
    178    isNDFD: bool = False,
    179) -> List[str]:
    180    """
    181    Return a list of variable shortNames.
    182
    183    If all 3 args are None, then shortNames from all disciplines, parameter
    184    categories, and numbers will be returned.
    185
    186    Parameters
    187    ----------
    188    discipline
    189        GRIB2 discipline code value.
    190    parmcat
    191        GRIB2 parameter category value.
    192    parmnum
    193        Parameter Number value of a GRIB2 message.
    194    isNDFD: optional
    195        If `True`, signals function to try to get variable information from the
    196        supplemental NDFD tables.
    197
    198    Returns
    199    -------
    200    get_shortnames
    201        list of GRIB2 shortNames.
    202    """
    203    shortnames = list()
    204    if discipline is None:
    205        discipline = GRIB2_DISCIPLINES
    206    else:
    207        discipline = [discipline]
    208    if parmcat is None:
    209        parmcat = list()
    210        for d in discipline:
    211            parmcat += list(get_table(f'4.1.{d}').keys())
    212    else:
    213        parmcat = [parmcat]
    214    if parmnum is None:
    215        parmnum = list(range(256))
    216    else:
    217        parmnum = [parmnum]
    218    for d in discipline:
    219
    220        for pc in parmcat:
    221            for pn in parmnum:
    222                shortnames.append(get_varinfo_from_table(d,pc,pn,isNDFD)[2])
    223
    224    shortnames = sorted(set(shortnames))
    225    try:
    226        shortnames.remove('unknown')
    227        shortnames.remove('Unknown')
    228    except(ValueError):
    229        pass
    230    return shortnames
    231
    232
    233@lru_cache(maxsize=None)
    234def get_metadata_from_shortname(shortname: str):
    235    """
    236    Provide GRIB2 variable metadata attributes given a GRIB2 shortName.
    237
    238    Parameters
    239    ----------
    240    shortname
    241        GRIB2 variable shortName.
    242
    243    Returns
    244    -------
    245    get_metadata_from_shortname
    246        list of dictionary items where each dictionary item contains the
    247        variable metadata key:value pairs.
    248
    249        NOTE: Some variable shortNames will exist in multiple parameter
    250        category/number tables according to the GRIB2 discipline.
    251    """
    252    metadata = []
    253    for d in GRIB2_DISCIPLINES:
    254        parmcat = list(get_table(f'4.1.{d}').keys())
    255        for pc in parmcat:
    256            for pn in range(256):
    257                varinfo = get_varinfo_from_table(d,pc,pn,False)
    258                if shortname == varinfo[2]:
    259                    metadata.append(dict(discipline=d,parameterCategory=pc,parameterNumber=pn,
    260                                         fullName=varinfo[0],units=varinfo[1]))
    261    return metadata
    262
    263
    264def get_wgrib2_level_string(pdtn: int, pdt: ArrayLike) -> str:
    265    """
    266    Return a string that describes the level or layer of the GRIB2 message.
    267
    268    The format and language of the string is an exact replica of how wgrib2
    269    produces the level/layer string in its inventory output.
    270
    271    Contents of wgrib2 source,
    272    [Level.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Level.c),
    273    were converted into a Python dictionary and stored in grib2io as table
    274    'wgrib2_level_string'.
    275
    276    Parameters
    277    ----------
    278    pdtn
    279        GRIB2 Product Definition Template Number
    280    pdt
    281        Sequence containing GRIB2 Product Definition Template (Section 4).
    282
    283    Returns
    284    -------
    285    get_wgrib2_level_string
    286        wgrib2-formatted level/layer string.
    287    """
    288    lvlstr = ''
    289    if pdtn == 32:
    290        return 'no_level'
    291    elif pdtn == 48:
    292        idxs = slice(20,26)
    293    else:
    294        idxs = slice(9,15)
    295    type1, sfac1, sval1, type2, sfac2, sval2 = map(int,pdt[idxs])
    296    val1 = sval1/10**sfac1
    297    if type1 in [100,108]: val1 *= 0.01
    298    if type2 != 255:
    299        # Layer
    300        #assert type2 == type1, "Surface types are not equal: %g - %g" % (type1,type2)
    301        val2 = sval2/10**sfac2
    302        if type2 in [100,108]: val2 *= 0.01
    303        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[1]
    304        vals = (val1,val2)
    305    else:
    306        # Level
    307        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[0]
    308        vals = (val1)
    309    if '%g' in lvlstr: lvlstr %= vals
    310    return lvlstr
    311
    312
    313def _build_aerosol_shortname(obj) -> str:
    314    """
    315    """
    316    _OPTICAL_WAVELENGTH_MAPPING = get_table('aerosol_optical_wavelength')
    317    _LEVEL_MAPPING = get_table('aerosol_level')
    318    _PARAMETER_MAPPING = get_table('aerosol_parameter')
    319    _AERO_TYPE_MAPPING = get_table('aerosol_type')
    320
    321    # Build shortname from aerosol components
    322    parts = []
    323
    324    # Get aerosol type
    325    aero_type = str(obj.typeOfAerosol.value) if obj.typeOfAerosol is not None else ""
    326
    327    # Add size information if applicable
    328    aero_size = ""
    329    if hasattr(obj, 'scaledValueOfFirstSize'):
    330        if float(obj.scaledValueOfFirstSize) > 0:
    331            first_size = float(obj.scaledValueOfFirstSize)
    332
    333            # Map common PM sizes
    334            size_map = {1: 'pm1', 25: 'pm25', 10: 'pm10', 20: 'pm20'}
    335            aero_size = size_map.get(first_size, f"pm{int(first_size)}")
    336
    337            # Check for size intervals
    338            if (hasattr(obj, 'scaledValueOfSecondSize') and
    339                obj.scaledValueOfSecondSize is not None and
    340                hasattr(obj, 'typeOfIntervalForAerosolSize') and
    341                obj.typeOfIntervalForAerosolSize.value == 6):
    342
    343                second_size = float(obj.scaledValueOfSecondSize)
    344                if second_size > 0:
    345                    if (first_size == 2.5 and second_size == 10):
    346                        aero_size = 'PM25to10'
    347                    elif (first_size == 10 and second_size == 20):
    348                        aero_size = 'PM10to20'
    349                    else:
    350                        aero_size = f"PM{int(first_size)}to{int(second_size)}"
    351
    352    # Add optical and wavelength information
    353    var_wavelength = ''
    354    if (hasattr(obj, 'parameterNumber') and
    355        hasattr(obj, 'scaledValueOfFirstWavelength') and
    356        hasattr(obj, 'scaledValueOfSecondWavelength')):
    357
    358        optical_type = str(obj.parameterNumber)
    359        if obj.scaledValueOfFirstWavelength > 0:
    360            first_wl = obj.scaledValueOfFirstWavelength
    361            second_wl = obj.scaledValueOfSecondWavelength
    362
    363            # Special case for AE between 440-870nm
    364            if optical_type == '111' and first_wl == 440 and second_wl == 870:
    365                key = (optical_type, '440TO870')
    366            else:
    367                # Find matching wavelength band
    368                for wl_key, wl_info in _OPTICAL_WAVELENGTH_MAPPING.items():
    369                    if (wl_key[0] == optical_type and  # Check optical_type first
    370                        int(wl_key[1]) == first_wl and
    371                        (second_wl is None or int(wl_key[2]) == second_wl)):
    372                        key = wl_key
    373                        break
    374                else:
    375                    # If no match found, use raw values
    376                    key = (optical_type, str(first_wl),
    377                          str(second_wl) if second_wl is not None else '')
    378
    379            # FIX THIS...
    380            if key in _OPTICAL_WAVELENGTH_MAPPING.keys():
    381                var_wavelength = _OPTICAL_WAVELENGTH_MAPPING[key]
    382
    383    # Add level information
    384    level_str = ''
    385    if hasattr(obj, 'typeOfFirstFixedSurface'):
    386        first_level = str(obj.typeOfFirstFixedSurface.value)
    387        first_value = str(obj.scaledValueOfFirstFixedSurface) if obj.scaledValueOfFirstFixedSurface > 0 else ''
    388        if first_level in _LEVEL_MAPPING:
    389            level_str = f"{_LEVEL_MAPPING[first_level]}{first_value}"
    390
    391    # Get parameter type
    392    param = ''
    393    if hasattr(obj, 'parameterNumber'):
    394        param_num = str(obj.parameterNumber)
    395        if param_num in _PARAMETER_MAPPING:
    396            param = _PARAMETER_MAPPING[param_num]
    397
    398    # Build the final shortname
    399    if var_wavelength and aero_type in _AERO_TYPE_MAPPING:
    400        shortname = f"{_AERO_TYPE_MAPPING[aero_type]}{var_wavelength}"
    401    elif aero_type in _AERO_TYPE_MAPPING:
    402        parts = []
    403        if level_str:
    404            parts.append(level_str)
    405        parts.append(_AERO_TYPE_MAPPING[aero_type])
    406        if aero_size:
    407            parts.append(aero_size)
    408        if param:
    409            parts.append(param)
    410        shortname = '_'.join(parts) if len(parts) > 1 else parts[0]
    411    else:
    412        return get_varinfo_from_table(obj.section0[2], *obj.section4[2:4], isNDFD=obj._isNDFD)[2]
    413
    414    return shortname
    415
    416
    417@lru_cache(maxsize=None)
    418def get_table_names(var_tables: bool=False) -> tuple:
    419    """
    420    Return the names of available GRIB2 tables.
    421
    422    The table dictionaries as they exist in grib2io are prefixed
    423    with "table_". When accessing a table through the available
    424    functions, the prefix is not necessary.
    425
    426    Parameters
    427    ----------
    428    var_tables : bool, optional
    429        If True, include names of variable tables.
    430        If False (default), include only non-variable tables.
    431
    432    Returns
    433    -------
    434    tuple of str
    435        A tuple sorted names of available tables.
    436    """
    437    tables = [
    438        name.replace("table_","") for name, val in globals().items()
    439        if isinstance(val, dict) and name.startswith("table_")
    440    ]
    441
    442    tables = [
    443        t.replace("_",".") if t.startswith(tuple("0123456789")) else t for t in tables
    444    ]
    445
    446    if var_tables:
    447        for d in GRIB2_DISCIPLINES:
    448            modname = f'.section4_discipline{d}'
    449            _load_varinfo_tables(modname)
    450        vt = [t.replace("table_","").replace("_",".") for t in _varinfo_tables_datastore.keys()]
    451        tables.extend(vt)
    452
    453    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: View Source

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

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

    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            pass
    167        if vartbl is not None:
    168            break
    169    if vartbl is None:
    170        vartbl = ['Unknown','Unknown','Unknown']
    171    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]: View Source

    174@lru_cache(maxsize=None)
    175def get_shortnames(
    176    discipline: Optional[Union[int, str]] = None,
    177    parmcat: Optional[Union[int, str]] = None,
    178    parmnum: Optional[Union[int, str]] = None,
    179    isNDFD: bool = False,
    180) -> List[str]:
    181    """
    182    Return a list of variable shortNames.
    183
    184    If all 3 args are None, then shortNames from all disciplines, parameter
    185    categories, and numbers will be returned.
    186
    187    Parameters
    188    ----------
    189    discipline
    190        GRIB2 discipline code value.
    191    parmcat
    192        GRIB2 parameter category value.
    193    parmnum
    194        Parameter Number value of a GRIB2 message.
    195    isNDFD: optional
    196        If `True`, signals function to try to get variable information from the
    197        supplemental NDFD tables.
    198
    199    Returns
    200    -------
    201    get_shortnames
    202        list of GRIB2 shortNames.
    203    """
    204    shortnames = list()
    205    if discipline is None:
    206        discipline = GRIB2_DISCIPLINES
    207    else:
    208        discipline = [discipline]
    209    if parmcat is None:
    210        parmcat = list()
    211        for d in discipline:
    212            parmcat += list(get_table(f'4.1.{d}').keys())
    213    else:
    214        parmcat = [parmcat]
    215    if parmnum is None:
    216        parmnum = list(range(256))
    217    else:
    218        parmnum = [parmnum]
    219    for d in discipline:
    220
    221        for pc in parmcat:
    222            for pn in parmnum:
    223                shortnames.append(get_varinfo_from_table(d,pc,pn,isNDFD)[2])
    224
    225    shortnames = sorted(set(shortnames))
    226    try:
    227        shortnames.remove('unknown')
    228        shortnames.remove('Unknown')
    229    except(ValueError):
    230        pass
    231    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): View Source

    234@lru_cache(maxsize=None)
    235def get_metadata_from_shortname(shortname: str):
    236    """
    237    Provide GRIB2 variable metadata attributes given a GRIB2 shortName.
    238
    239    Parameters
    240    ----------
    241    shortname
    242        GRIB2 variable shortName.
    243
    244    Returns
    245    -------
    246    get_metadata_from_shortname
    247        list of dictionary items where each dictionary item contains the
    248        variable metadata key:value pairs.
    249
    250        NOTE: Some variable shortNames will exist in multiple parameter
    251        category/number tables according to the GRIB2 discipline.
    252    """
    253    metadata = []
    254    for d in GRIB2_DISCIPLINES:
    255        parmcat = list(get_table(f'4.1.{d}').keys())
    256        for pc in parmcat:
    257            for pn in range(256):
    258                varinfo = get_varinfo_from_table(d,pc,pn,False)
    259                if shortname == varinfo[2]:
    260                    metadata.append(dict(discipline=d,parameterCategory=pc,parameterNumber=pn,
    261                                         fullName=varinfo[0],units=varinfo[1]))
    262    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: View Source

    265def get_wgrib2_level_string(pdtn: int, pdt: ArrayLike) -> str:
    266    """
    267    Return a string that describes the level or layer of the GRIB2 message.
    268
    269    The format and language of the string is an exact replica of how wgrib2
    270    produces the level/layer string in its inventory output.
    271
    272    Contents of wgrib2 source,
    273    [Level.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Level.c),
    274    were converted into a Python dictionary and stored in grib2io as table
    275    'wgrib2_level_string'.
    276
    277    Parameters
    278    ----------
    279    pdtn
    280        GRIB2 Product Definition Template Number
    281    pdt
    282        Sequence containing GRIB2 Product Definition Template (Section 4).
    283
    284    Returns
    285    -------
    286    get_wgrib2_level_string
    287        wgrib2-formatted level/layer string.
    288    """
    289    lvlstr = ''
    290    if pdtn == 32:
    291        return 'no_level'
    292    elif pdtn == 48:
    293        idxs = slice(20,26)
    294    else:
    295        idxs = slice(9,15)
    296    type1, sfac1, sval1, type2, sfac2, sval2 = map(int,pdt[idxs])
    297    val1 = sval1/10**sfac1
    298    if type1 in [100,108]: val1 *= 0.01
    299    if type2 != 255:
    300        # Layer
    301        #assert type2 == type1, "Surface types are not equal: %g - %g" % (type1,type2)
    302        val2 = sval2/10**sfac2
    303        if type2 in [100,108]: val2 *= 0.01
    304        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[1]
    305        vals = (val1,val2)
    306    else:
    307        # Level
    308        lvlstr = get_value_from_table(type1,table='wgrib2_level_string')[0]
    309        vals = (val1)
    310    if '%g' in lvlstr: lvlstr %= vals
    311    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: View Source

    418@lru_cache(maxsize=None)
    419def get_table_names(var_tables: bool=False) -> tuple:
    420    """
    421    Return the names of available GRIB2 tables.
    422
    423    The table dictionaries as they exist in grib2io are prefixed
    424    with "table_". When accessing a table through the available
    425    functions, the prefix is not necessary.
    426
    427    Parameters
    428    ----------
    429    var_tables : bool, optional
    430        If True, include names of variable tables.
    431        If False (default), include only non-variable tables.
    432
    433    Returns
    434    -------
    435    tuple of str
    436        A tuple sorted names of available tables.
    437    """
    438    tables = [
    439        name.replace("table_","") for name, val in globals().items()
    440        if isinstance(val, dict) and name.startswith("table_")
    441    ]
    442
    443    tables = [
    444        t.replace("_",".") if t.startswith(tuple("0123456789")) else t for t in tables
    445    ]
    446
    447    if var_tables:
    448        for d in GRIB2_DISCIPLINES:
    449            modname = f'.section4_discipline{d}'
    450            _load_varinfo_tables(modname)
    451        vt = [t.replace("table_","").replace("_",".") for t in _varinfo_tables_datastore.keys()]
    452        tables.extend(vt)
    453
    454    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.