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 decimal import Decimal, localcontext
  9from typing import Dict, List, Optional, Tuple, Type, Union
 10
 11import numpy as np
 12from numpy.typing import ArrayLike
 13
 14from .. import iplib
 15from .. import tables
 16from .. import templates
 17
 18
 19def decimal_to_scaled_int(
 20    value: Union[float, str, int],
 21    scale_factor: Optional[int] = None,
 22) -> Tuple[int, int]:
 23    """
 24    Convert a float-like value to a scaled integer using the minimal decimal scaling factor.
 25
 26    The input value is internally converted to a `Decimal` to ensure precise scaling.
 27
 28    Parameters
 29    ----------
 30    value : float, str, or int
 31        The numeric value to scale.
 32    scaled_value : int
 33        The integer result of scaling the original value by `10**scale_factor`.
 34
 35    Returns
 36    -------
 37    scale_factor : int
 38        The smallest power of 10 such that `value * 10**scale_factor` is an exact integer.
 39    scaled_value : int
 40        The integer result of scaling the original value by `10**scale_factor`.
 41    """
 42    dec_value = Decimal(str(value))  # Preserve exact decimal representation
 43
 44    with localcontext() as ctx:
 45        ctx.prec = 28
 46
 47        if scale_factor is not None:
 48            scaled = dec_value * (10 ** scale_factor)
 49            if scaled != scaled.to_integral_value():
 50                raise ValueError(
 51                    f"Value {value} cannot be exactly scaled by 10^{scale_factor}"
 52                )
 53            return scale_factor, int(scaled)
 54        else:
 55            scale_factor = 0
 56            while dec_value != dec_value.to_integral_value():
 57                dec_value *= 10
 58                scale_factor += 1
 59                if scale_factor > 20:
 60                    raise ValueError(
 61                        f"Could not find exact scale factor for value {value} within bounds."
 62                    )
 63            return scale_factor, int(dec_value)
 64
 65
 66def int2bin(i: int, nbits: int=8, output: Union[Type[str], Type[List]]=str):
 67    """
 68    Convert integer to binary string or list
 69
 70    The struct module unpack using ">i" will unpack a 32-bit integer from a
 71    binary string.
 72
 73    Parameters
 74    ----------
 75    i
 76        Integer value to convert to binary representation.
 77    nbits : default=8
 78        Number of bits to return.  Valid values are 8 [DEFAULT], 16, 32, and
 79        64.
 80    output : default=str
 81        Return data as `str` [DEFAULT] or `list` (list of ints).
 82
 83    Returns
 84    -------
 85    int2bin
 86        `str` or `list` (list of ints) of binary representation of the integer
 87        value.
 88    """
 89    i = int(i) if not isinstance(i,int) else i
 90    assert nbits in [8,16,32,64]
 91    bitstr = "{0:b}".format(i).zfill(nbits)
 92    if output is str:
 93        return bitstr
 94    elif output is list:
 95        return [int(b) for b in bitstr]
 96
 97
 98def ieee_float_to_int(f):
 99    """
100    Convert an IEEE 754 32-bit float to a 32-bit integer.
101
102    Parameters
103    ----------
104    f : float
105        Floating-point value.
106
107    Returns
108    -------
109    ieee_float_to_int
110        `numpy.int32` representation of an IEEE 32-bit float.
111    """
112    i = struct.unpack('>i',struct.pack('>f',np.float32(f)))[0]
113    return np.int32(i)
114
115
116def ieee_int_to_float(i):
117    """
118    Convert a 32-bit integer to an IEEE 32-bit float.
119
120    Parameters
121    ----------
122    i : int
123        Integer value.
124
125    Returns
126    -------
127    ieee_int_to_float
128        `numpy.float32` representation of a 32-bit int.
129    """
130    f = struct.unpack('>f',struct.pack('>i',np.int32(i)))[0]
131    return np.float32(f)
132
133
134def get_leadtime(pdtn: int, pdt: ArrayLike) -> datetime.timedelta:
135    """
136    Compute lead time as a datetime.timedelta object.
137
138    Using information from GRIB2 Product Definition Template
139    Number, and Product Definition Template (Section 4).
140
141    Parameters
142    ----------
143    pdtn
144        GRIB2 Product Definition Template Number
145    pdt
146        Sequence containing GRIB2 Product Definition Template (Section 4).
147
148    Returns
149    -------
150    leadTime
151        datetime.timedelta object representing the lead time of the GRIB2 message.
152    """
153    lt = tables.get_value_from_table(pdt[templates.UnitOfForecastTime._key[pdtn]], 'scale_time_seconds')
154    lt *= pdt[templates.ValueOfForecastTime._key[pdtn]]
155    return datetime.timedelta(seconds=int(lt))
156
157
158def get_duration(pdtn: int, pdt: ArrayLike) -> datetime.timedelta:
159    """
160    Compute a time duration as a datetime.timedelta.
161
162    Uses information from Product Definition Template Number, and Product
163    Definition Template (Section 4).
164
165    Parameters
166    ----------
167    pdtn
168        GRIB2 Product Definition Template Number
169    pdt
170        Sequence containing GRIB2 Product Definition Template (Section 4).
171
172    Returns
173    -------
174    get_duration
175        datetime.timedelta object representing the time duration of the GRIB2
176        message.
177    """
178    if pdtn in templates._timeinterval_pdtns:
179        ntime = pdt[templates.NumberOfTimeRanges._key[pdtn]]
180        duration_unit = tables.get_value_from_table(
181            pdt[templates.UnitOfTimeRangeOfStatisticalProcess._key[pdtn]],
182            'scale_time_seconds')
183        d = ntime * duration_unit * pdt[
184            templates.TimeRangeOfStatisticalProcess._key[pdtn]]
185    else:
186        d = 0
187    return datetime.timedelta(seconds=int(d))
188
189
190def decode_wx_strings(lus: bytes) -> Dict[int, str]:
191    """
192    Decode GRIB2 Local Use Section to obtain NDFD/MDL Weather Strings.
193
194    The decode procedure is defined
195    [here](https://vlab.noaa.gov/web/mdl/nbm-gmos-grib2-wx-info).
196
197    Parameters
198    ----------
199    lus
200        GRIB2 Local Use Section containing NDFD weather strings.
201
202    Returns
203    -------
204    decode_wx_strings
205        Dict of NDFD/MDL weather strings. Keys are an integer value that
206        represent the sequential order of the key in the packed local use
207        section and the value is the weather key.
208    """
209    assert lus[0] == 1
210    # Unpack information related to the simple packing method
211    # the packed weather string data.
212    ngroups = struct.unpack('>H',lus[1:3])[0]
213    nvalues = struct.unpack('>i',lus[3:7])[0]
214    refvalue = struct.unpack('>i',lus[7:11])[0]
215    dsf = struct.unpack('>h',lus[11:13])[0]
216    nbits = lus[13]
217    datatype = lus[14]
218    if datatype == 0: # Floating point
219        refvalue = np.float32(ieee_int_to_float(refvalue)*10**-dsf)
220    elif datatype == 1: # Integer
221        refvalue = np.int32(ieee_int_to_float(refvalue)*10**-dsf)
222    # Upack each byte starting at byte 15 to end of the local use
223    # section, create a binary string and append to the full
224    # binary string.
225    b = ''
226    for i in range(15,len(lus)):
227        iword = struct.unpack('>B',lus[i:i+1])[0]
228        b += bin(iword).split('b')[1].zfill(8)
229    # Iterate over the binary string (b). For each nbits
230    # chunk, convert to an integer, including the refvalue,
231    # and then convert the int to an ASCII character, then
232    # concatenate to wxstring.
233    wxstring = ''
234    for i in range(0,len(b),nbits):
235        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
236    # Return string as list, split by null character.
237    #return list(filter(None,wxstring.split('\0')))
238    return {n:k for n,k in enumerate(list(filter(None,wxstring.split('\0'))))}
239
240
241def get_wgrib2_prob_string(
242    probtype: int,
243    sfacl: int,
244    svall: int,
245    sfacu: int,
246    svalu: int,
247) -> str:
248    """
249    Return a wgrib2-styled string of probabilistic threshold information.
250
251    Logic from wgrib2 source,
252    [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
253    is replicated here.
254
255    Parameters
256    ----------
257    probtype
258        Type of probability (Code Table 4.9).
259    sfacl
260        Scale factor of lower limit.
261    svall
262        Scaled value of lower limit.
263    sfacu
264        Scale factor of upper limit.
265    svalu
266        Scaled value of upper limit.
267
268    Returns
269    -------
270    get_wgrib2_prob_string
271        wgrib2-formatted string of probability threshold.
272    """
273    probstr = ''
274    if sfacl < 0: sfacl = 0
275    if sfacu < 0: sfacu = 0
276    lower = svall/(10**sfacl)
277    upper = svalu/(10**sfacu)
278    if probtype == 0:
279        probstr = 'prob <%g' % (lower)
280    elif probtype == 1:
281        probstr = 'prob >%g' % (upper)
282    elif probtype == 2:
283        if lower == upper:
284            probstr = 'prob =%g' % (lower)
285        else:
286            probstr = 'prob >=%g <%g' % (lower,upper)
287    elif probtype == 3:
288        probstr = 'prob >%g' % (lower)
289    elif probtype == 4:
290        probstr = 'prob <%g' % (upper)
291    else:
292        probstr = ''
293    return probstr
294
295
296def latlon_to_ij(
297    gdtn,
298    gdt,
299    lats,
300    lons,
301    missing_value = np.nan,
302):
303    """
304    Convert latitude/longitude coordinates to grid (i, j) indices using the
305    GRIB2 Grid Definition Section (GDS).
306
307    This function calls the grib2io iplib Cython extension module function,
308    `grib2io.iplib.latlon_to_ij`.
309
310    Parameters
311    ----------
312    gdtn : int
313        GRIB2 grid definition template number.
314    gdt : ndarray of int32
315        GRIB2 grid definition template values.
316    lats : numpy.ndarray or list
317        Latitude coordinates in degrees.
318    lons : numpy.ndarray or list
319        Longitude coordinates in degrees.
320    missing_value : float, optional
321        Missing value to represent when latitude/longitude coordinate is
322        outside the grid domain.
323
324    Returns
325    -------
326    xpts : ndarray of float32
327        Grid x-coordinates (i-indices) corresponding to the input
328        latitude/longitude points.
329    ypts : ndarray of float32
330        Grid y-coordinates (j-indices) corresponding to the input
331        latitude/longitude points.
332    """
333    # Check lats and lons
334    if isinstance(lats,list):
335        nlats = len(lats)
336    elif isinstance(lats,np.ndarray) and len(lats.shape) == 1:
337        nlats = lats.shape[0]
338    else:
339        raise ValueError("Latitudes must be a list or 1-D NumPy array.")
340    if isinstance(lons,list):
341        nlons = len(lons)
342    elif isinstance(lons,np.ndarray) and len(lons.shape) == 1:
343        nlons = lons.shape[0]
344    else:
345        raise ValueError("Longitudes must be a list or 1-D NumPy array.")
346    if nlats != nlons:
347        raise ValueError("Latitudes and longitudes same length.")
348    return iplib.latlon_to_ij(
349        gdtn.astype(np.int32),
350        gdt.astype(np.int32),
351        np.array(lats, dtype=np.float32),
352        np.array(lons, dtype=np.float32),
353        missing_value,
354    )
def decimal_to_scaled_int( value: Union[float, str, int], scale_factor: Optional[int] = None) -> Tuple[int, int]:
20def decimal_to_scaled_int(
21    value: Union[float, str, int],
22    scale_factor: Optional[int] = None,
23) -> Tuple[int, int]:
24    """
25    Convert a float-like value to a scaled integer using the minimal decimal scaling factor.
26
27    The input value is internally converted to a `Decimal` to ensure precise scaling.
28
29    Parameters
30    ----------
31    value : float, str, or int
32        The numeric value to scale.
33    scaled_value : int
34        The integer result of scaling the original value by `10**scale_factor`.
35
36    Returns
37    -------
38    scale_factor : int
39        The smallest power of 10 such that `value * 10**scale_factor` is an exact integer.
40    scaled_value : int
41        The integer result of scaling the original value by `10**scale_factor`.
42    """
43    dec_value = Decimal(str(value))  # Preserve exact decimal representation
44
45    with localcontext() as ctx:
46        ctx.prec = 28
47
48        if scale_factor is not None:
49            scaled = dec_value * (10 ** scale_factor)
50            if scaled != scaled.to_integral_value():
51                raise ValueError(
52                    f"Value {value} cannot be exactly scaled by 10^{scale_factor}"
53                )
54            return scale_factor, int(scaled)
55        else:
56            scale_factor = 0
57            while dec_value != dec_value.to_integral_value():
58                dec_value *= 10
59                scale_factor += 1
60                if scale_factor > 20:
61                    raise ValueError(
62                        f"Could not find exact scale factor for value {value} within bounds."
63                    )
64            return scale_factor, int(dec_value)

Convert a float-like value to a scaled integer using the minimal decimal scaling factor.

The input value is internally converted to a Decimal to ensure precise scaling.

Parameters
  • value (float, str, or int): The numeric value to scale.
  • scaled_value (int): The integer result of scaling the original value by 10**scale_factor.
Returns
  • scale_factor (int): The smallest power of 10 such that value * 10**scale_factor is an exact integer.
  • scaled_value (int): The integer result of scaling the original value by 10**scale_factor.
def int2bin( i: int, nbits: int = 8, output: Union[Type[str], Type[List]] = <class 'str'>):
67def int2bin(i: int, nbits: int=8, output: Union[Type[str], Type[List]]=str):
68    """
69    Convert integer to binary string or list
70
71    The struct module unpack using ">i" will unpack a 32-bit integer from a
72    binary string.
73
74    Parameters
75    ----------
76    i
77        Integer value to convert to binary representation.
78    nbits : default=8
79        Number of bits to return.  Valid values are 8 [DEFAULT], 16, 32, and
80        64.
81    output : default=str
82        Return data as `str` [DEFAULT] or `list` (list of ints).
83
84    Returns
85    -------
86    int2bin
87        `str` or `list` (list of ints) of binary representation of the integer
88        value.
89    """
90    i = int(i) if not isinstance(i,int) else i
91    assert nbits in [8,16,32,64]
92    bitstr = "{0:b}".format(i).zfill(nbits)
93    if output is str:
94        return bitstr
95    elif output is list:
96        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] or list (list of ints).
Returns
  • int2bin: str or list (list of ints) of binary representation of the integer value.
def ieee_float_to_int(f):
 99def ieee_float_to_int(f):
100    """
101    Convert an IEEE 754 32-bit float to a 32-bit integer.
102
103    Parameters
104    ----------
105    f : float
106        Floating-point value.
107
108    Returns
109    -------
110    ieee_float_to_int
111        `numpy.int32` representation of an IEEE 32-bit float.
112    """
113    i = struct.unpack('>i',struct.pack('>f',np.float32(f)))[0]
114    return np.int32(i)

Convert an IEEE 754 32-bit float to a 32-bit integer.

Parameters
  • f (float): Floating-point value.
Returns
  • ieee_float_to_int: numpy.int32 representation of an IEEE 32-bit float.
def ieee_int_to_float(i):
117def ieee_int_to_float(i):
118    """
119    Convert a 32-bit integer to an IEEE 32-bit float.
120
121    Parameters
122    ----------
123    i : int
124        Integer value.
125
126    Returns
127    -------
128    ieee_int_to_float
129        `numpy.float32` representation of a 32-bit int.
130    """
131    f = struct.unpack('>f',struct.pack('>i',np.int32(i)))[0]
132    return np.float32(f)

Convert a 32-bit integer to an IEEE 32-bit float.

Parameters
  • i (int): Integer value.
Returns
  • ieee_int_to_float: numpy.float32 representation of a 32-bit int.
def get_leadtime( 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]]) -> datetime.timedelta:
135def get_leadtime(pdtn: int, pdt: ArrayLike) -> datetime.timedelta:
136    """
137    Compute lead time as a datetime.timedelta object.
138
139    Using information from GRIB2 Product Definition Template
140    Number, and Product Definition Template (Section 4).
141
142    Parameters
143    ----------
144    pdtn
145        GRIB2 Product Definition Template Number
146    pdt
147        Sequence containing GRIB2 Product Definition Template (Section 4).
148
149    Returns
150    -------
151    leadTime
152        datetime.timedelta object representing the lead time of the GRIB2 message.
153    """
154    lt = tables.get_value_from_table(pdt[templates.UnitOfForecastTime._key[pdtn]], 'scale_time_seconds')
155    lt *= pdt[templates.ValueOfForecastTime._key[pdtn]]
156    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.
def get_duration( 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]]) -> datetime.timedelta:
159def get_duration(pdtn: int, pdt: ArrayLike) -> datetime.timedelta:
160    """
161    Compute a time duration as a datetime.timedelta.
162
163    Uses information from Product Definition Template Number, and Product
164    Definition Template (Section 4).
165
166    Parameters
167    ----------
168    pdtn
169        GRIB2 Product Definition Template Number
170    pdt
171        Sequence containing GRIB2 Product Definition Template (Section 4).
172
173    Returns
174    -------
175    get_duration
176        datetime.timedelta object representing the time duration of the GRIB2
177        message.
178    """
179    if pdtn in templates._timeinterval_pdtns:
180        ntime = pdt[templates.NumberOfTimeRanges._key[pdtn]]
181        duration_unit = tables.get_value_from_table(
182            pdt[templates.UnitOfTimeRangeOfStatisticalProcess._key[pdtn]],
183            'scale_time_seconds')
184        d = ntime * duration_unit * pdt[
185            templates.TimeRangeOfStatisticalProcess._key[pdtn]]
186    else:
187        d = 0
188    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.
def decode_wx_strings(lus: bytes) -> Dict[int, str]:
191def decode_wx_strings(lus: bytes) -> Dict[int, str]:
192    """
193    Decode GRIB2 Local Use Section to obtain NDFD/MDL Weather Strings.
194
195    The decode procedure is defined
196    [here](https://vlab.noaa.gov/web/mdl/nbm-gmos-grib2-wx-info).
197
198    Parameters
199    ----------
200    lus
201        GRIB2 Local Use Section containing NDFD weather strings.
202
203    Returns
204    -------
205    decode_wx_strings
206        Dict of NDFD/MDL weather strings. Keys are an integer value that
207        represent the sequential order of the key in the packed local use
208        section and the value is the weather key.
209    """
210    assert lus[0] == 1
211    # Unpack information related to the simple packing method
212    # the packed weather string data.
213    ngroups = struct.unpack('>H',lus[1:3])[0]
214    nvalues = struct.unpack('>i',lus[3:7])[0]
215    refvalue = struct.unpack('>i',lus[7:11])[0]
216    dsf = struct.unpack('>h',lus[11:13])[0]
217    nbits = lus[13]
218    datatype = lus[14]
219    if datatype == 0: # Floating point
220        refvalue = np.float32(ieee_int_to_float(refvalue)*10**-dsf)
221    elif datatype == 1: # Integer
222        refvalue = np.int32(ieee_int_to_float(refvalue)*10**-dsf)
223    # Upack each byte starting at byte 15 to end of the local use
224    # section, create a binary string and append to the full
225    # binary string.
226    b = ''
227    for i in range(15,len(lus)):
228        iword = struct.unpack('>B',lus[i:i+1])[0]
229        b += bin(iword).split('b')[1].zfill(8)
230    # Iterate over the binary string (b). For each nbits
231    # chunk, convert to an integer, including the refvalue,
232    # and then convert the int to an ASCII character, then
233    # concatenate to wxstring.
234    wxstring = ''
235    for i in range(0,len(b),nbits):
236        wxstring += chr(int(b[i:i+nbits],2)+refvalue)
237    # Return string as list, split by null character.
238    #return list(filter(None,wxstring.split('\0')))
239    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.
def get_wgrib2_prob_string(probtype: int, sfacl: int, svall: int, sfacu: int, svalu: int) -> str:
242def get_wgrib2_prob_string(
243    probtype: int,
244    sfacl: int,
245    svall: int,
246    sfacu: int,
247    svalu: int,
248) -> str:
249    """
250    Return a wgrib2-styled string of probabilistic threshold information.
251
252    Logic from wgrib2 source,
253    [Prob.c](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2/blob/develop/wgrib2/Prob.c),
254    is replicated here.
255
256    Parameters
257    ----------
258    probtype
259        Type of probability (Code Table 4.9).
260    sfacl
261        Scale factor of lower limit.
262    svall
263        Scaled value of lower limit.
264    sfacu
265        Scale factor of upper limit.
266    svalu
267        Scaled value of upper limit.
268
269    Returns
270    -------
271    get_wgrib2_prob_string
272        wgrib2-formatted string of probability threshold.
273    """
274    probstr = ''
275    if sfacl < 0: sfacl = 0
276    if sfacu < 0: sfacu = 0
277    lower = svall/(10**sfacl)
278    upper = svalu/(10**sfacu)
279    if probtype == 0:
280        probstr = 'prob <%g' % (lower)
281    elif probtype == 1:
282        probstr = 'prob >%g' % (upper)
283    elif probtype == 2:
284        if lower == upper:
285            probstr = 'prob =%g' % (lower)
286        else:
287            probstr = 'prob >=%g <%g' % (lower,upper)
288    elif probtype == 3:
289        probstr = 'prob >%g' % (lower)
290    elif probtype == 4:
291        probstr = 'prob <%g' % (upper)
292    else:
293        probstr = ''
294    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.
def latlon_to_ij(gdtn, gdt, lats, lons, missing_value=nan):
297def latlon_to_ij(
298    gdtn,
299    gdt,
300    lats,
301    lons,
302    missing_value = np.nan,
303):
304    """
305    Convert latitude/longitude coordinates to grid (i, j) indices using the
306    GRIB2 Grid Definition Section (GDS).
307
308    This function calls the grib2io iplib Cython extension module function,
309    `grib2io.iplib.latlon_to_ij`.
310
311    Parameters
312    ----------
313    gdtn : int
314        GRIB2 grid definition template number.
315    gdt : ndarray of int32
316        GRIB2 grid definition template values.
317    lats : numpy.ndarray or list
318        Latitude coordinates in degrees.
319    lons : numpy.ndarray or list
320        Longitude coordinates in degrees.
321    missing_value : float, optional
322        Missing value to represent when latitude/longitude coordinate is
323        outside the grid domain.
324
325    Returns
326    -------
327    xpts : ndarray of float32
328        Grid x-coordinates (i-indices) corresponding to the input
329        latitude/longitude points.
330    ypts : ndarray of float32
331        Grid y-coordinates (j-indices) corresponding to the input
332        latitude/longitude points.
333    """
334    # Check lats and lons
335    if isinstance(lats,list):
336        nlats = len(lats)
337    elif isinstance(lats,np.ndarray) and len(lats.shape) == 1:
338        nlats = lats.shape[0]
339    else:
340        raise ValueError("Latitudes must be a list or 1-D NumPy array.")
341    if isinstance(lons,list):
342        nlons = len(lons)
343    elif isinstance(lons,np.ndarray) and len(lons.shape) == 1:
344        nlons = lons.shape[0]
345    else:
346        raise ValueError("Longitudes must be a list or 1-D NumPy array.")
347    if nlats != nlons:
348        raise ValueError("Latitudes and longitudes same length.")
349    return iplib.latlon_to_ij(
350        gdtn.astype(np.int32),
351        gdt.astype(np.int32),
352        np.array(lats, dtype=np.float32),
353        np.array(lons, dtype=np.float32),
354        missing_value,
355    )

Convert latitude/longitude coordinates to grid (i, j) indices using the GRIB2 Grid Definition Section (GDS).

This function calls the grib2io iplib Cython extension module function, grib2io.iplib.latlon_to_ij.

Parameters
  • gdtn (int): GRIB2 grid definition template number.
  • gdt (ndarray of int32): GRIB2 grid definition template values.
  • lats (numpy.ndarray or list): Latitude coordinates in degrees.
  • lons (numpy.ndarray or list): Longitude coordinates in degrees.
  • missing_value (float, optional): Missing value to represent when latitude/longitude coordinate is outside the grid domain.
Returns
  • xpts (ndarray of float32): Grid x-coordinates (i-indices) corresponding to the input latitude/longitude points.
  • ypts (ndarray of float32): Grid y-coordinates (j-indices) corresponding to the input latitude/longitude points.