# How to Initialize WeatherNext Models from HRES Operational Data vs ERA5 Reanalysis

> Learn to initialize WeatherNext models using HRES operational data or ERA5 reanalysis. Understand the differences in data loading, normalization, and checkpoints for optimal model setup.

- Repository: [Google DeepMind/weathernext](https://github.com/google-deepmind/weathernext)
- Tags: how-to-guide
- Published: 2026-08-12

---

**Initialize WeatherNext models from ERA5 by loading full reanalysis data including precipitation, or from HRES by loading fc0 snapshots without precipitation and using HRES-specific normalization and checkpoints.**

WeatherNext models from **google-deepmind/weathernext** support two distinct initialization paths depending on your data source. ERA5-based models require complete reanalysis fields with 6-hour accumulated precipitation, while HRES-based models are fine-tuned on ECMWF operational forecasts and initialize directly from HRES fc0 snapshots that exclude precipitation. Both paths use the same core architecture in [`weathernext/weathernext2/fgn.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/weathernext2/fgn.py), but diverge in data preprocessing, normalization statistics, and checkpoint selection.

---

## Key Differences Between ERA5 and HRES Initialization

The **WeatherNext** codebase distinguishes data sources through three primary components:

| Component | ERA5 Path | HRES Path |
|-----------|-----------|-----------|
| **Data loader** ([`weathernext/utils/data_utils.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/data_utils.py)) | `weatherbench2.readers.era5` | `weatherbench2.readers.hres` |
| **Pressure levels** ([`weathernext/utils/variables.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/variables.py)) | `PRESSURE_LEVELS_ERA5_25` | `PRESSURE_LEVELS_HRES_25` |
| **Precipitation input** | Required (`tp` variable) | **Not required** (model predicts without input) |
| **Normalization** | ERA5-derived statistics | HRES-fc0-derived statistics |
| **Checkpoint** | Base training checkpoint | HRES-fine-tuned checkpoint |

The critical architectural insight: the `FGN` model class itself is **data-agnostic**. The `_maybe_init` lazy initialization in `graphcast._maybe_init` (lines 368-376 in [`weathernext/weathernext1_graph/graphcast.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/weathernext1_graph/graphcast.py)) inspects latitude/longitude grids from the input `xarray.Dataset` and configures the Icosahedral mesh automatically.

---

## Initializing from ERA5 Reanalysis

ERA5 initialization requires the complete variable set including **6-hour accumulated precipitation** (`tp`). This matches how the base models were trained on the ERA5 reanalysis dataset.

### Step-by-Step ERA5 Initialization

```python
import weatherbench2 as wb2
from weathernext.utils import data_utils, model_utils

# 1. Load ERA5 Zarr with full variable list including precipitation

era5_ds = wb2.load_zarr(
    "era5",
    variables=[
        "t2m", "u10", "v10", "sp", "msl",
        "tcwv", "u", "v", "z", "t",
        "q", "r", "tcc", "tp",  # precipitation required

    ],
    levels=data_utils.PRESSURE_LEVELS_ERA5_25,
    xarray_kwargs=dict(chunks="auto"),
)

# 2. Normalize using ERA5 training statistics

norm_era5 = data_utils.normalize(era5_ds, source="era5")

# 3. Load base checkpoint (not HRES-fine-tuned)

ckpt = model_utils.load_checkpoint(
    "gs://dm_graphcast/WeatherNext2_2025.npz"
)

# 4. Build FGN model instance

from weathernext.weathernext2.fgn import FGN
model = FGN(
    config_path="weathernext/weathernext2/configs/WeatherNext2.json",
    checkpoint=ckpt
)

# 5. First forward call triggers mesh initialization from grid shape

forecast = model(norm_era5.isel(time=0))

```

The `tp` variable serves as both input channel and training target. The model learns predictive representations directly from observed precipitation fields during training.

---

## Initializing from HRES Operational Data

HRES initialization omits precipitation from inputs. The model variant—described in the README as being **"fine-tuned on ECMWF HRES data and designed to be initialized directly from operational HRES initial conditions"**—learns to predict precipitation without receiving it as input.

### Step-by-Step HRES Initialization

```python
import weatherbench2 as wb2
from weathernext.utils import data_utils, model_utils

# 1. Load HRES-fc0 Zarr (lead-time 0 initial conditions)

hres_ds = wb2.load_zarr(
    "hres_fc0",
    variables=[
        "t2m", "u10", "v10", "sp", "msl",
        "tcwv", "u", "v", "z", "t",
        "q", "r", "tcc",
        # Note: NO precipitation variable

    ],
    levels=data_utils.PRESSURE_LEVELS_HRES_25,  # Different constant

    xarray_kwargs=dict(chunks="auto"),
)

# 2. Normalize using HRES-fc0 statistics (no precipitation needed)

norm_hres = data_utils.normalize(hres_ds, source="hres")

# 3. Load HRES-fine-tuned checkpoint

ckpt = model_utils.load_checkpoint(
    "gs://dm_graphcast/WeatherNext2_2025_hres.npz"
)

# 4. Same FGN class, same config

from weathernext.weathernext2.fgn import FGN
model = FGN(
    config_path="weathernext/weathernext2/configs/WeatherNext2.json",
    checkpoint=ckpt
)

# 5. Mesh auto-configures to 0.25° HRES grid

forecast = model(norm_hres.isel(time=0))

```

As noted in [`docs/weathernext1_graph/README.md`](https://github.com/google-deepmind/weathernext/blob/main/docs/weathernext1_graph/README.md) (lines 21-23): *"models marked as `ERA5-HRES` do not take precipitation as input and are specifically trained to take HRES-fc0 as input."*

---

## Critical Implementation Details

### Pressure Level Ordering

The vertical coordinate ordering differs between sources. The constant definitions in [`weathernext/utils/variables.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/variables.py) (lines 23-33) specify:

```python

# ERA5: specific level ordering for reanalysis

PRESSURE_LEVELS_ERA5_25 = [...]

# HRES: same 25 levels but different coordinate alignment

PRESSURE_LEVELS_HRES_25 = [...]  # See source for exact ordering

```

Always use the source-appropriate constant to ensure correct vertical dimension alignment.

### Precipitation Handling

The `docs/weathernext1_graph/graphcast_demo.ipynb` (lines 350-354) clarifies: HRES operational data **lacks precipitation fields entirely**. The HRES-fine-tuned model learns this mapping during fine-tuning, using ERA5 precipitation **only as ground-truth for evaluation**, never as input.

### Mesh Initialization Behavior

The lazy `_maybe_init` mechanism in the GraphCast-style models:

- Detects grid resolution from input `xarray.Dataset` coordinates
- Constructs Icosahedral mesh appropriate to 0.5° (ERA5 coarse) or 0.25° (HRES/ERA5 high-res)
- Caches mesh structure for subsequent rollout steps

This enables the same `FGN` class to handle both data sources without explicit configuration changes.

---

## Checkpoint Selection Reference

| Model Variant | Checkpoint Pattern | Initialization Source |
|-------------|-------------------|----------------------|
| WeatherNext-2 Base | `WeatherNext2_2025.npz` | ERA5 reanalysis |
| WeatherNext-2 HRES | `WeatherNext2_2025_hres.npz` | HRES fc0 operational |
| Cyclones variants | Similar `_hres` suffix pattern | Context-dependent |

Always match checkpoint training data to your initialization source. Using an ERA5 checkpoint with HRES inputs (or vice versa) produces undefined behavior due to mismatched normalization statistics and learned precipitation representations.

---

## Summary

- **ERA5 initialization** requires precipitation (`tp`) as input variable, uses `PRESSURE_LEVELS_ERA5_25`, normalizes with ERA5 statistics, and loads base training checkpoints
- **HRES initialization** excludes precipitation from inputs, uses `PRESSURE_LEVELS_HRES_25`, normalizes with HRES-fc0 statistics, and requires HRES-fine-tuned checkpoints
- Both paths use identical `FGN` class from [`weathernext/weathernext2/fgn.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/weathernext2/fgn.py) with automatic mesh configuration via `_maybe_init`
- The `source` parameter in `data_utils.normalize()` selects appropriate statistics; never mix normalization sources with mismatched checkpoints

---

## Frequently Asked Questions

### What happens if I use ERA5 precipitation with an HRES checkpoint?

The model will fail or produce invalid forecasts. HRES-fine-tuned checkpoints expect input tensors without the precipitation channel. Including `tp` violates the expected input shape and normalizes with incompatible statistics.

### Can I initialize the same model instance with both ERA5 and HRES data sequentially?

No. While the `FGN` class supports both via lazy initialization, the mesh structure and checkpoint weights are fixed after first call. Instantiate separate model objects for each data source, or reload checkpoints between initializations.

### Why does HRES use the same 25 pressure levels as ERA5 with "different ordering"?

The ECMWF operational system and ERA5 reanalysis share vertical level definitions but may differ in coordinate metadata conventions. The `PRESSURE_LEVELS_HRES_25` constant in [`weathernext/utils/variables.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/variables.py) ensures correct alignment with how WeatherBench2 serves HRES-fc0 data.

### Where is precipitation ground-truth for HRES model evaluation?

ERA5 precipitation remains the evaluation standard even for HRES-initialized models. The fine-tuning process uses ERA5 precipitation as targets despite HRES inputs lacking precipitation, enabling fair skill comparisons across initialization strategies.