Python module for reading/writing GRIB files using ECMWF ECCODES library
—
Helper functions for coordinate transformations, date/time conversions, grid operations, and library configuration.
__version__: str = "2.1.6"
"""pygrib package version string"""Usage example:
import pygrib
print(f"Using pygrib version: {pygrib.__version__}")Convert between different grid representations and coordinate systems.
def redtoreg(redgrid_data, lonsperlat, missval=None):
"""
Convert reduced Gaussian grid data to regular Gaussian grid.
Uses linear interpolation to expand reduced grid data to a regular grid
with the same number of latitudes and max(lonsperlat) longitudes.
Parameters:
- redgrid_data: array-like, 1D data array on reduced grid
- lonsperlat: array-like, number of longitudes at each latitude
- missval: float, optional, missing value (default: numpy.nan)
Returns:
numpy.ndarray, 2D array on regular grid (nlats, nlons)
"""Usage example:
import pygrib
import numpy as np
# Example reduced grid parameters
nlats = 48 # Number of latitude circles
lonsperlat = np.array([20, 25, 32, 40, 45, 48, 50, 52, ...]) # Lons per lat
# Simulated reduced grid data (in practice, from GRIB message)
total_points = lonsperlat.sum()
redgrid_data = np.random.randn(total_points)
# Convert to regular grid
reggrid_data = pygrib.redtoreg(redgrid_data, lonsperlat)
print(f"Regular grid shape: {reggrid_data.shape}") # (nlats, max(lonsperlat))
# Handle missing values
redgrid_with_missing = redgrid_data.copy()
redgrid_with_missing[100:110] = -999.0 # Insert missing values
reggrid_data = pygrib.redtoreg(redgrid_with_missing, lonsperlat, missval=-999.0)Convert between Julian day numbers and Python datetime objects.
def julian_to_datetime(jd):
"""
Convert Julian day number to Python datetime object.
Parameters:
- jd: float, Julian day number
Returns:
datetime.datetime object
"""
def datetime_to_julian(d):
"""
Convert Python datetime object to Julian day number.
Parameters:
- d: datetime.datetime, datetime object
Returns:
float, Julian day number
"""Usage example:
import pygrib
from datetime import datetime
# Convert Julian day to datetime
julian_day = 2459580.5 # Example Julian day
dt = pygrib.julian_to_datetime(julian_day)
print(f"Julian day {julian_day} = {dt}")
# Convert datetime to Julian day
dt = datetime(2022, 1, 15, 12, 0, 0)
jd = pygrib.datetime_to_julian(dt)
print(f"DateTime {dt} = Julian day {jd}")
# Round-trip conversion
original_dt = datetime(2023, 6, 15, 18, 30, 0)
julian = pygrib.datetime_to_julian(original_dt)
converted_dt = pygrib.julian_to_datetime(julian)
print(f"Original: {original_dt}")
print(f"Converted: {converted_dt}")Calculate Gaussian latitudes for meteorological grids.
def gaulats(nlats):
"""
Compute Gaussian latitudes for specified number of latitude circles.
Returns the latitudes of a Gaussian grid with nlats latitude circles
between the poles. Used in global meteorological models.
Parameters:
- nlats: int, number of latitude circles
Returns:
numpy.ndarray, Gaussian latitudes in degrees (north to south)
"""Usage example:
import pygrib
import numpy as np
# Calculate Gaussian latitudes for different resolutions
for n in [32, 64, 96, 128]:
lats = pygrib.gaulats(n)
print(f"N{n} grid: {n} latitudes from {lats[0]:.2f}° to {lats[-1]:.2f}°")
# Use with reduced Gaussian grid
nlats = 48
gaussian_lats = pygrib.gaulats(nlats)
lonsperlat = np.full(nlats, 96) # 96 longitudes at each latitude
# Create coordinate meshgrid for plotting
lons = np.linspace(0, 360, 96, endpoint=False)
lon_grid, lat_grid = np.meshgrid(lons, gaussian_lats)
print(f"Grid shape: {lat_grid.shape}")Control how pygrib handles malformed or problematic GRIB files.
def tolerate_badgrib_on():
"""Enable tolerance for malformed GRIB files"""
def tolerate_badgrib_off():
"""Disable tolerance for malformed GRIB files (default)"""Usage example:
import pygrib
# Enable tolerance for bad GRIB files
pygrib.tolerate_badgrib_on()
try:
# This might work even with slightly corrupted files
grbs = pygrib.open('potentially_bad_file.grb')
for grb in grbs:
print(grb)
grbs.close()
except Exception as e:
print(f"Even with tolerance, file is too corrupted: {e}")
# Disable tolerance (restore strict checking)
pygrib.tolerate_badgrib_off()Control handling of multi-field GRIB messages (messages containing multiple parameters).
def multi_support_on():
"""Enable multi-field message support"""
def multi_support_off():
"""Disable multi-field message support"""Usage example:
import pygrib
# Enable multi-field support for files that contain them
pygrib.multi_support_on()
grbs = pygrib.open('multi_field_file.grb')
print(f"Multi-field messages: {grbs.has_multi_field_msgs}")
# Process multi-field messages (use with caution with indexes)
for grb in grbs:
print(f"Message {grb.messagenumber}: {grb}")
grbs.close()
# Disable multi-field support if not needed
pygrib.multi_support_off()Configure paths and settings for the underlying ECCODES library.
def set_definitions_path(eccodes_definition_path):
"""
Set path to ECCODES definition files.
Parameters:
- eccodes_definition_path: str, path to ECCODES definitions directory
"""
def get_definitions_path():
"""
Get current path to ECCODES definition files.
Returns:
str, path to ECCODES definitions directory
"""Usage example:
import pygrib
import os
# Check current definitions path
current_path = pygrib.get_definitions_path()
print(f"Current ECCODES definitions path: {current_path}")
# Set custom definitions path (if needed)
custom_path = "/usr/local/share/eccodes/definitions"
if os.path.exists(custom_path):
pygrib.set_definitions_path(custom_path)
print(f"Set definitions path to: {pygrib.get_definitions_path()}")
else:
print("Custom path not found, using default")Set computed date/time attributes on GRIB messages.
def setdates(grb):
"""
Set analDate and validDate attributes on gribmessage.
Computes analysis and valid dates from GRIB keys like
julianDay, forecastTime, and fcstimeunits.
Parameters:
- grb: gribmessage, message to update
Modifies message in-place by setting analDate and validDate attributes
"""Usage example:
import pygrib
grbs = pygrib.open('forecast.grb')
grb = grbs.readline()
# Check if dates are already set
print(f"Analysis date before: {getattr(grb, 'analDate', 'Not set')}")
print(f"Valid date before: {getattr(grb, 'validDate', 'Not set')}")
# Set computed dates
pygrib.setdates(grb)
# Check computed dates
print(f"Analysis date: {grb.analDate}")
print(f"Valid date: {grb.validDate}")
print(f"Forecast time: {grb['forecastTime']} {grb.fcstimeunits}")import pygrib
grbs = pygrib.open('mixed_grids.grb')
for grb in grbs:
grid_type = grb['gridType']
if grid_type == 'reduced_gg':
# Handle reduced Gaussian grid
print(f"Reduced Gaussian: {grb['name']}")
# Get reduced grid info
lonsperlat = grb['pl'] # Points per latitude
data_1d = grb['values'] # 1D data array
# Convert to regular grid if needed
reggrid_data = pygrib.redtoreg(data_1d, lonsperlat)
print(f"Expanded to regular grid: {reggrid_data.shape}")
elif grid_type == 'regular_ll':
# Handle regular lat/lon grid
print(f"Regular lat/lon: {grb['name']}")
data_2d = grb['values'] # Already 2D
lats, lons = grb.latlons()
elif grid_type == 'lambert':
# Handle Lambert conformal grid
print(f"Lambert conformal: {grb['name']}")
if grb.projparams:
print(f"Projection: {grb.projparams}")import pygrib
from datetime import datetime, timedelta
# Process forecast file and standardize dates
grbs = pygrib.open('forecast.grb')
reference_time = datetime(2023, 1, 1, 0, 0)
processed_messages = []
for grb in grbs:
# Ensure dates are computed
pygrib.setdates(grb)
# Calculate time difference from reference
if grb.validDate:
time_diff = grb.validDate - reference_time
hours_diff = time_diff.total_seconds() / 3600
# Add custom time information
grb['hoursFromReference'] = int(hours_diff)
processed_messages.append(grb)
print(f"Processed: {grb['shortName']} at +{grb['forecastTime']}h")
grbs.close()Install with Tessl CLI
npx tessl i tessl/pypi-pygrib