How to Handle Different GRIB2 Product Types in Herbie: Surface, Pressure, and Native Grids

Use Herbie's model templates to select GRIB2 product types via the product parameter, then filter inventory and download subsets using the search parameter to isolate specific variables like surface pressure or native-level fields.

Herbie is an open-source Python library that simplifies downloading and reading numerical weather prediction (NWP) model output from various sources. When working with GRIB2 files—particularly from high-resolution models like HRRR, GFS, or RRFS—you must specify the product type (surface, pressure-level, or native-level) to access the correct vertical coordinate system and variables.

Understanding GRIB2 Product Types in Herbie

The Template-Based Architecture

Every NWP model in Herbie is defined by a template module that specifies available product types through a PRODUCTS dictionary mapping keys to descriptions, and a SOURCES dictionary defining URL patterns.

In src/herbie/core.py, the Herbie class validates your selection against these definitions during initialization. The _validate method checks that self.product in self.PRODUCTS (lines 184-190), ensuring you request a supported configuration before attempting downloads.

Key Product Categories

  • Surface (sfc): Variables at ground level (2-meter temperature, surface pressure)
  • Pressure levels (prs or pgrb2): Data interpolated to standard pressure surfaces (500 hPa, 850 hPa)
  • Native levels (nat or natlev): Model's original vertical coordinate system (eta or hybrid levels)

Selecting Product Types for Different Models

HRRR Native-Level Fields

The HRRR model template in src/herbie/models/hrrr.py defines the native-level product as "nat" (lines 77-82), representing 3-km resolution fields on the model's native vertical coordinate. Access these by setting product="nat":

from herbie import Herbie

H = Herbie(
    date="2023-09-15 12:00",
    model="hrrr",
    product="nat",
    fxx=0
)

GFS Pressure-Level Products

For global models like GFS, pressure-level data typically uses product keys like pgrb2.0p25 as defined in src/herbie/models/gfs.py (lines 42-49). This provides standard pressure-level variables at 0.25-degree resolution:

G = Herbie(
    date="2023-09-15 00:00",
    model="gfs",
    product="pgrb2.0p25",
    fxx=6
)

RRFS Native Level Transformations

The RRFS template in src/herbie/models/rrfs.py demonstrates product key transformations, converting "nat" to "natlev" internally (lines 38-42) to match the specific file naming conventions of the Rapid Refresh Forecast System.

Filtering Inventory by Product Type

Once you've selected a product, use the inventory() method to inspect available variables. The method parses .idx files using wgrib2 (via src/herbie/wgrib2.py, lines 46-55) and returns a searchable pandas DataFrame.

To isolate specific fields like surface pressure from native grids:


# Search for surface pressure in native-level data

df = H.inventory(search=":SLP:")
print(df[["variable", "level", "valid_time"]])

The search parameter applies regex filtering to the search_this column (lines 276-285 in core.py), allowing you to distinguish between surface fields and upper-air variables within the same product file.

Downloading and Converting Specific Product Data

Subsetting by Byte Ranges

Herbie enables efficient partial downloads by reading the inventory index and retrieving only the byte ranges matching your search criteria. The download() method (lines 334-382 in core.py) accepts a search parameter to fetch specific variables without downloading the entire GRIB2 file:


# Download only surface pressure messages

slp_file = H.download(search=":SLP:")

Loading into xarray

Convert any product type to an xarray.Dataset using the xarray() method (lines 1249-1285 in core.py), which uses cfgrib as the backend engine. Native-level coordinates are preserved automatically:

ds = H.xarray(search=":SLP:")
ds.SLP.sel(valid_time=ds.valid_time[0]).plot()

This workflow applies uniformly across all product types—whether accessing surface grids, pressure levels, or native coordinates—because the template architecture abstracts model-specific file structures.

Summary

  • Herbie uses model templates to define valid GRIB2 product types via the PRODUCTS dictionary in each model module.
  • Set the product parameter when instantiating Herbie to select surface (sfc), pressure-level (prs), or native-level (nat) grids.
  • The _validate method in src/herbie/core.py ensures your selected product exists for the chosen model and date.
  • Use inventory(search="...") to filter variables within a product type before downloading.
  • Download subsets efficiently by specifying search criteria, then load into xarray with cfgrib to preserve native vertical coordinates.

Frequently Asked Questions

What is the difference between native-level and pressure-level GRIB2 products?

Native-level products (nat or natlev) contain data on the model's original vertical coordinate system (such as eta or hybrid sigma-pressure levels), preserving the full vertical resolution of the forecast system. Pressure-level products (prs or pgrb2) interpolate these fields to standard pressure surfaces (e.g., 850 hPa, 500 hPa) for easier comparison across different models and observations. According to the Herbie source code, you access these by specifying different product keys in the model template.

How do I find which product types are available for a specific model?

Each model template in src/herbie/models/ defines a PRODUCTS dictionary mapping available keys to descriptions. For example, src/herbie/models/hrrr.py lists "nat" for native levels, "sfc" for surface, and "prs" for pressure levels. You can inspect this dictionary programmatically by importing the template module or checking the model documentation in the repository.

Can I download variables from multiple product types simultaneously?

No, Herbie instances are bound to a single product type per initialization. To access variables from different vertical coordinates (e.g., surface pressure from sfc and geopotential height from prs), create separate Herbie objects with different product parameters, then merge the resulting xarray Datasets manually using xarray.merge() or concatenation methods.

Why does the RRFS model use "natlev" instead of "nat" for native levels?

The RRFS template in src/herbie/models/rrfs.py performs an internal transformation (lines 38-42) that maps the user-facing "nat" key to the backend file identifier "natlev". This accommodates the specific file naming conventions used by the Rapid Refresh Forecast System while maintaining a consistent interface across Herbie's supported models.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →