Python module for reading/writing GRIB files using ECMWF ECCODES library
—
High-performance indexing system for fast message searching and retrieval. Creates optimized indexes on GRIB keys for efficient filtering of large files.
Create indexes on GRIB keys for fast message searching.
class index:
def __init__(self, filename, *args):
"""
Create GRIB index for fast message searching.
Parameters:
- filename: str, GRIB filename or saved index filename
- *args: str, GRIB key names to index on
If no keys provided, filename is treated as saved index file
Key types can be specified by appending type:
- 'key:l' for long/integer values
- 'key:s' for string values
- 'key:d' for double/float values
"""Usage example:
# Create index on multiple keys
grbindx = pygrib.index('weather.grb', 'shortName', 'typeOfLevel', 'level')
# Create index with typed keys
grbindx = pygrib.index('weather.grb', 'shortName:s', 'level:l', 'step:l')
# Open previously saved index (no keys specified)
grbindx = pygrib.index('weather.grb.idx')Access information about the created index.
class index:
@property
def keys(self) -> list:
"""
List of indexed key names.
None when opening a saved index file.
"""
@property
def types(self) -> list:
"""
List of key type declarations ('l', 's', 'd').
None when opening a saved index file.
"""Usage example:
grbindx = pygrib.index('weather.grb', 'shortName', 'level', 'step')
print(f"Indexed keys: {grbindx.keys}")
print(f"Key types: {grbindx.types}")
# For saved index files
saved_idx = pygrib.index('weather.grb.idx')
print(f"Saved index keys: {saved_idx.keys}") # Returns NoneSelect messages using the index for high-performance filtering.
class index:
def select(self, **kwargs):
"""
Select messages matching key/value criteria using index.
Much faster than open.select() for large files.
Parameters:
- **kwargs: GRIB key/value pairs
Only exact matches supported (no sequences or functions)
Returns:
List of gribmessage objects matching criteria
"""
def __call__(self, **kwargs):
"""Alias for select() method"""Usage example:
grbindx = pygrib.index('weather.grb', 'shortName', 'typeOfLevel', 'level')
# Fast selection using index
temp_500 = grbindx.select(shortName='t', typeOfLevel='isobaricInhPa', level=500)
wind_250 = grbindx.select(shortName='u', typeOfLevel='isobaricInhPa', level=250)
# Using __call__ method (equivalent)
geopotential = grbindx(shortName='gh', level=500)
# Process results
for grb in temp_500:
data = grb['values']
print(f"Temperature at 500mb: {data.min():.1f} to {data.max():.1f} K")Save and reload indexes for reuse across sessions.
class index:
def write(self, filename: str):
"""
Save index to file for later reuse.
Parameters:
- filename: str, output filename for saved index
"""
def close(self):
"""Close and deallocate index resources"""Usage example:
# Create and use index
grbindx = pygrib.index('weather.grb', 'shortName', 'typeOfLevel', 'level')
selected = grbindx.select(shortName='t', level=500)
# Save index for later use
grbindx.write('weather.grb.idx')
grbindx.close()
# Later session - reload saved index
grbindx = pygrib.index('weather.grb.idx') # No keys needed
selected = grbindx.select(shortName='t', level=500)
grbindx.close()Examples showing performance differences between index and sequential search.
import time
# Sequential search (slower for large files)
grbs = pygrib.open('large_file.grb')
start = time.time()
temp_msgs = grbs.select(shortName='t', level=500)
seq_time = time.time() - start
grbs.close()
# Index search (much faster)
grbindx = pygrib.index('large_file.grb', 'shortName', 'level')
start = time.time()
temp_msgs = grbindx.select(shortName='t', level=500)
idx_time = time.time() - start
grbindx.close()
print(f"Sequential search: {seq_time:.3f} seconds")
print(f"Index search: {idx_time:.3f} seconds")
print(f"Speed improvement: {seq_time/idx_time:.1f}x faster")Important: Indexes cannot search within multi-field GRIB messages and may return incorrect results. This commonly affects NCEP files where u/v wind components are stored in single multi-field messages.
# Check for multi-field messages
grbs = pygrib.open('ncep_file.grb')
if grbs.has_multi_field_msgs:
print("Warning: File contains multi-field messages")
print("Use open.select() instead of index for reliable results")
# Use sequential search for multi-field files
wind_data = grbs.select(shortName=['u', 'v'], level=250)
else:
# Safe to use index
grbindx = pygrib.index('ncep_file.grb', 'shortName', 'level')
wind_data = grbindx.select(shortName='u', level=250)Unlike open.select(), index selection has limitations:
grbindx = pygrib.index('weather.grb', 'shortName', 'level')
# Supported: exact value matching
temp_500 = grbindx.select(shortName='t', level=500)
# NOT supported with indexes:
# - Sequence matching: level=(500, 700, 850)
# - Function matching: level=lambda l: l > 500
# - Multiple values for same key
# Use open.select() for complex criteria
grbs = pygrib.open('weather.grb')
multi_level = grbs.select(shortName='t', level=(500, 700, 850))
conditional = grbs.select(shortName='t', level=lambda l: l > 500)Select keys that you'll frequently use for filtering:
# Good key choices for meteorological data
common_idx = pygrib.index('weather.grb',
'shortName', # Parameter name
'typeOfLevel', # Level type
'level', # Level value
'step') # Forecast step
# Analysis-specific indexing
analysis_idx = pygrib.index('analysis.grb',
'paramId', # Parameter ID
'dataDate', # Analysis date
'dataTime') # Analysis time
# Forecast-specific indexing
forecast_idx = pygrib.index('forecast.grb',
'shortName',
'validityDate', # Valid date
'validityTime') # Valid timeInstall with Tessl CLI
npx tessl i tessl/pypi-pygrib