# How to Visualize xarray Outputs with Temperature, Wind, and Geopotential Fields in WeatherNext

> Learn to visualize xarray outputs for temperature wind and geopotential fields using WeatherNext and Matplotlib. Explore atmospheric forecasts effectively.

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

---

**WeatherNext stores atmospheric forecasts as nested xarray.Dataset structures that you can visualize using standard xarray plotting methods combined with Matplotlib.**

The WeatherNext repository from Google DeepMind outputs weather predictions as **xarray** datasets containing standard meteorological variables. This guide shows you how to extract and plot temperature, wind, and geopotential fields using the repository's built-in utilities and the standard scientific Python stack.

---

## Understanding WeatherNext's xarray Output Structure

WeatherNext packages its model forecasts as `xarray.Dataset` objects. Each dataset contains atmospheric variables as separate `xarray.DataArray` objects:

- `t` — Temperature in Kelvin
- `u` — Zonal wind component in m/s
- `v` — Meridional wind component in m/s
- `z` — Geopotential height in m²/s²

The repository provides a specialized wrapper in **[`weathernext/utils/xarray_tree.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/xarray_tree.py)** that treats every leaf node of a dataset as an independent `DataArray` while preserving the ability to reconstruct the original `Dataset` after processing. This utility is essential when working with WeatherNext's potentially non-uniform coordinate structures.

---

## Loading and Extracting WeatherNext Forecast Data

Start by loading your NetCDF output and extracting the three fields you need to visualize.

```python
import xarray as xr

# Load WeatherNext forecast output

ds = xr.open_dataset("forecast_output.nc")

# Extract individual DataArrays

temp = ds["t"]          # Temperature

u_wind = ds["u"]        # Zonal wind

v_wind = ds["v"]        # Meridional wind

geopot = ds["z"]        # Geopotential height

```

WeatherNext follows **CF conventions**, so coordinate variables (latitude, longitude, pressure level, time) attach automatically to each field.

---

## Visualizing Temperature with xarray pcolormesh

Temperature fields display effectively as filled color maps. The xarray `plot.pcolormesh` method provides automatic coordinate handling and color bar generation.

```python
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(10, 6))

temp.plot.pcolormesh(
    ax=ax,
    cmap="coolwarm",
    add_colorbar=True,
    cbar_kwargs={"label": "Temperature (K)"},
)
ax.set_title("Temperature Field")
ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")

```

The `coolwarm` colormap emphasizes both warm and cold anomalies symmetrically around neutral tones.

---

## Plotting Wind Vectors with quiver

Wind requires combining both components into vector arrows. Subsampling prevents overcrowding in high-resolution WeatherNext outputs.

```python
fig, ax = plt.subplots(figsize=(10, 6))

# Subsample every 5th grid point for clarity

step = 5
u_sub = u_wind[::step, ::step]
v_sub = v_wind[::step, ::step]

# Optional: background shading for context

temp[::step, ::step].plot.pcolormesh(ax=ax, cmap="Greys", alpha=0.3)

ax.quiver(
    u_sub["lon"], u_sub["lat"],
    u_sub.values, v_sub.values,
    scale=700,
    width=0.002,
    color="k"
)
ax.set_title("Wind Vectors")
ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")

```

Adjust the `scale` parameter to control arrow length. Larger values produce shorter arrows.

---

## Displaying Geopotential Height with contour

Geopotential height fields work best as contour lines, emphasizing pressure-level topology and wave patterns.

```python
fig, ax = plt.subplots(figsize=(10, 6))

geopot.plot.contour(
    ax=ax,
    colors="black",
    linewidths=0.8,
    add_colorbar=False,
    levels=12,
)
ax.set_title("Geopotential Height")
ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")

```

Specify `levels` to control contour density. Twelve levels typically resolve synoptic-scale features without excessive clutter.

---

## Combining All Three Fields in a Multi-Panel Figure

For comparative analysis, arrange temperature, wind, and geopotential plots side by side using Matplotlib subplots.

```python
import xarray as xr
import matplotlib.pyplot as plt

# Load WeatherNext dataset

ds = xr.open_dataset("forecast_output.nc")
temp = ds["t"]
u_wind, v_wind = ds["u"], ds["v"]
geopot = ds["z"]

# Create figure with three panels

fig, axs = plt.subplots(1, 3, figsize=(18, 5))

# Panel 1: Temperature pcolormesh

temp.plot.pcolormesh(
    ax=axs[0],
    cmap="coolwarm",
    cbar_kwargs={"label": "Temperature (K)"},
)
axs[0].set_title("Temperature")

# Panel 2: Wind quiver with temperature background

step = 5
axs[1].pcolormesh(
    temp["lon"][::step], temp["lat"][::step],
    temp[::step, ::step],
    cmap="Greys", alpha=0.3
)
axs[1].quiver(
    u_wind["lon"][::step], u_wind["lat"][::step],
    u_wind[::step, ::step], v_wind[::step, ::step],
    scale=700, width=0.002, color="k"
)
axs[1].set_title("Wind Vectors")

# Panel 3: Geopotential contours

geopot.plot.contour(
    ax=axs[2],
    colors="black",
    linewidths=0.8,
    levels=12,
)
axs[2].set_title("Geopotential Height")

plt.tight_layout()
plt.show()

```

This layout enables direct visual comparison of thermal structure, flow patterns, and geopotential topography.

---

## Pre-Processing with xarray_tree.map_structure

Before visualization, you may need to apply transformations uniformly across all variables. The **`xarray_tree.map_structure`** function in [`weathernext/utils/xarray_tree.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/xarray_tree.py) safely applies functions to every `DataArray` leaf while preserving dataset structure.

```python
from weathernext.utils import xarray_tree

# Convert temperature from Kelvin to Celsius

def kelvin_to_celsius(arr):
    if arr.name == "t":
        return arr - 273.15
    return arr

processed_ds = xarray_tree.map_structure(kelvin_to_celsius, ds)

```

If coordinates mismatch across variables—a possibility in WeatherNext outputs—`map_structure` automatically falls back to a plain dictionary representation rather than failing. This behavior is implemented in lines [54-65 of xarray_tree.py](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/xarray_tree.py#L54-L65).

---

## Dependencies and Repository Structure

WeatherNext declares **Matplotlib** as a dependency in [[`setup.py`](https://github.com/google-deepmind/weathernext/blob/main/setup.py)](https://github.com/google-deepmind/weathernext/blob/main/setup.py), ensuring visualization tools install automatically with the package.

| File | Purpose |
|------|---------|
| [`weathernext/utils/xarray_tree.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/xarray_tree.py) | Dataset traversal and transformation utilities |
| [`weathernext/utils/data_modalities.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/data_modalities.py) | Canonical variable names (`t`, `u`, `v`, `z`) |
| [`setup.py`](https://github.com/google-deepmind/weathernext/blob/main/setup.py) | Matplotlib dependency declaration |

The canonical variable naming scheme in [`data_modalities.py`](https://github.com/google-deepmind/weathernext/blob/main/data_modalities.py) ensures consistency across WeatherNext's data loading, processing, and visualization pipelines.

---

## Summary

- **WeatherNext outputs standard xarray.Dataset objects** containing temperature, wind components, and geopotential height as separate DataArrays.
- **Extract fields by name** (`ds["t"]`, `ds["u"]`, `ds["v"]`, `ds["z"]`) for individual visualization.
- **Use xarray's built-in plotting**: `pcolormesh` for temperature, `quiver` for wind vectors, and `contour` for geopotential height.
- **Apply `xarray_tree.map_structure`** from [`weathernext/utils/xarray_tree.py`](https://github.com/google-deepmind/weathernext/blob/main/weathernext/utils/xarray_tree.py) for uniform pre-processing across all dataset variables.
- **Subsample wind fields** to prevent visual clutter in high-resolution outputs.

---

## Frequently Asked Questions

### What coordinate system does WeatherNext use for its xarray outputs?

WeatherNext follows **CF (Climate and Forecast) conventions**, attaching latitude, longitude, pressure level, and time coordinates to all output variables. These coordinates propagate automatically through xarray selection and plotting operations.

### Can I visualize multiple forecast timesteps simultaneously?

Yes. WeatherNext datasets include a time dimension. Use xarray's `.isel(time=...)` or `.sel(time=...)` to select specific lead times, or create animation loops iterating over the time coordinate with `matplotlib.animation.FuncAnimation`.

### How do I handle missing or masked values in WeatherNext outputs?

Apply `xarray_tree.map_structure` with a masking function before visualization. The utility preserves NaN values in xarray's standard representation, which Matplotlib automatically excludes from plots.

### Why does my wind quiver plot appear as solid black?

Your grid resolution exceeds the visualization capacity. Apply subsampling with slice notation (`[::5, ::5]`) or increase the `scale` parameter in `quiver()` to shorten arrow lengths.