Python module for reading/writing GRIB files using ECMWF ECCODES library
—
Functionality for extracting meteorological data arrays, coordinate grids, and metadata from GRIB messages. Handles various grid types and supports data subsetting.
Extract meteorological data values from GRIB messages as NumPy arrays.
class gribmessage:
def __getitem__(self, key):
"""
Get GRIB key values, including special 'values' key for data.
Parameters:
- key: str, GRIB key name
Special keys:
- 'values': returns data array (numpy.ndarray)
- any GRIB key: returns metadata value
Returns:
Value depends on key - numpy array for 'values', various types for metadata
"""
def expand_grid(self, expand_reduced: bool):
"""
Control whether reduced grids are expanded to regular grids.
Parameters:
- expand_reduced: bool
True: expand reduced grids to regular grids (default)
False: keep data on unstructured reduced grid (1D array)
"""Usage example:
grbs = pygrib.open('weather.grb')
grb = grbs.select(shortName='t', level=500)[0]
# Get data array (default: expanded to regular grid)
data = grb['values'] # 2D numpy array
print(f"Data shape: {data.shape}")
print(f"Temperature range: {data.min():.1f} to {data.max():.1f} K")
# Control grid expansion
grb.expand_grid(False) # Keep as reduced grid
data_1d = grb['values'] # 1D numpy array
print(f"Reduced grid shape: {data_1d.shape}")Extract latitude and longitude coordinate arrays corresponding to the data grid.
class gribmessage:
def latlons(self):
"""
Get latitude/longitude coordinate arrays for the grid.
Supports regular lat/lon, Gaussian, Mercator, stereographic,
Lambert conformal, Albers equal-area, space-view, azimuthal
equidistant, reduced Gaussian, reduced lat/lon, Lambert
azimuthal equal-area, rotated lat/lon and rotated Gaussian grids.
Returns:
Tuple of (lats, lons) where:
- lats: numpy.ndarray, latitude values in degrees
- lons: numpy.ndarray, longitude values in degrees
Arrays have same shape as data grid (when expanded)
Raises:
ValueError: If grid type is unsupported
"""Usage example:
grb = grbs.select(shortName='t', level=500)[0]
# Get coordinate grids
lats, lons = grb.latlons()
print(f"Lat range: {lats.min():.1f} to {lats.max():.1f} degrees")
print(f"Lon range: {lons.min():.1f} to {lons.max():.1f} degrees")
print(f"Grid shape: {lats.shape}")
# Use with data for geographic analysis
data = grb['values']
import matplotlib.pyplot as plt
plt.contourf(lons, lats, data)
plt.colorbar()Extract data for specific geographic regions by latitude/longitude bounds.
class gribmessage:
def data(self, lat1=None, lat2=None, lon1=None, lon2=None):
"""
Extract data subset for specified lat/lon boundaries.
Parameters:
- lat1: float, optional, southern boundary latitude
- lat2: float, optional, northern boundary latitude
- lon1: float, optional, western boundary longitude
- lon2: float, optional, eastern boundary longitude
Returns:
Tuple of (data_subset, lats_subset, lons_subset):
- data_subset: numpy.ndarray, data values in region
- lats_subset: numpy.ndarray, latitude coordinates
- lons_subset: numpy.ndarray, longitude coordinates
"""Usage example:
grb = grbs.select(shortName='t', level=500)[0]
# Extract data for North America region
data_subset, lats_subset, lons_subset = grb.data(
lat1=25, # Southern boundary
lat2=70, # Northern boundary
lon1=220, # Western boundary (260W = 220E)
lon2=320 # Eastern boundary (40W = 320E)
)
print(f"Subset shape: {data_subset.shape}")
print(f"Lat bounds: {lats_subset.min():.1f} to {lats_subset.max():.1f}")
print(f"Lon bounds: {lons_subset.min():.1f} to {lons_subset.max():.1f}")Query GRIB keys and metadata from messages.
class gribmessage:
def keys(self):
"""
Get list of available GRIB keys for this message.
Returns:
List of str, all available GRIB key names
"""
def has_key(self, key: str) -> bool:
"""
Check if GRIB key exists in message.
Parameters:
- key: str, GRIB key name
Returns:
bool, True if key exists
"""
def valid_key(self, key: str) -> bool:
"""
Check if GRIB key is valid and accessible.
Parameters:
- key: str, GRIB key name
Returns:
bool, True if key is valid and can be accessed
"""
def is_missing(self, key: str) -> bool:
"""
Check if GRIB key value is missing/undefined.
Parameters:
- key: str, GRIB key name
Returns:
bool, True if key value is missing
"""Usage example:
grb = grbs.select(shortName='t', level=500)[0]
# Explore available keys
all_keys = grb.keys()
print(f"Total keys: {len(all_keys)}")
print(f"First 10 keys: {all_keys[:10]}")
# Check key availability
print(f"Has temperature data: {grb.has_key('values')}")
print(f"Has forecast time: {grb.has_key('forecastTime')}")
print(f"Valid shortName: {grb.valid_key('shortName')}")
# Check for missing values
print(f"Missing bitmap: {grb.is_missing('bitmap')}")
# Access common metadata
metadata = {
'parameter': grb['shortName'],
'level': grb['level'],
'units': grb['units'],
'forecast_time': grb['forecastTime'],
'valid_date': grb.validDate,
'analysis_date': grb.analDate
}
print(metadata)Access computed attributes that pygrib adds to GRIB messages.
class gribmessage:
@property
def messagenumber(self) -> int:
"""Message number in the file"""
@property
def projparams(self) -> dict:
"""Proj4 projection parameters (None for unsupported grids)"""
@property
def expand_reduced(self) -> bool:
"""Whether reduced grids are expanded to regular grids"""
@property
def fcstimeunits(self) -> str:
"""Forecast time units string"""
@property
def analDate(self):
"""Analysis date as datetime object"""
@property
def validDate(self):
"""Valid forecast date as datetime object"""Usage example:
grb = grbs.select(shortName='t', level=500)[0]
# Message position info
print(f"Message number: {grb.messagenumber}")
# Date/time information
print(f"Analysis date: {grb.analDate}")
print(f"Valid date: {grb.validDate}")
print(f"Forecast time units: {grb.fcstimeunits}")
# Projection information
if grb.projparams:
print(f"Projection: {grb.projparams}")
else:
print("Unsupported or simple lat/lon grid")
# Grid expansion setting
print(f"Expand reduced grids: {grb.expand_reduced}")GRIB keys can be accessed as object attributes for convenience.
class gribmessage:
def __getattr__(self, item):
"""Access GRIB keys as attributes"""
def __setattr__(self, name, value):
"""Set GRIB keys as attributes"""Usage example:
grb = grbs.select(shortName='t', level=500)[0]
# Access via attributes (equivalent to grb['key'])
param_name = grb.shortName
level_value = grb.level
units = grb.units
forecast_hour = grb.forecastTime
print(f"{param_name} at {level_value} {grb.typeOfLevel}")
print(f"Units: {units}")
print(f"Forecast: +{forecast_hour} hours")
# Set via attributes (equivalent to grb['key'] = value)
grb.forecastTime = 120
grb.parameterNumber = 11 # Change parameterInstall with Tessl CLI
npx tessl i tessl/pypi-pygrib