-
Notifications
You must be signed in to change notification settings - Fork 33
Open
Description
Hi all,
I can't seem to get reasonable looking 2m temperature forecasts using graphcast. In all cases, the predicted temperatures inevitably get extreme (> 100 C ), and if you visualize the forecast there are both visible hard boundaries (very hot on one side of a line and very cold on another), as well as a visible icosahedral pattern. Please see the attached forecast image, as well as steps to reproduce it.
Reproduction steps
- First make forecast grib file:
$ ai-models --date 20250130 graphcast --download-assets --lead-time 360 --path 20250130_graphcast_control.grib
- Use the following script to generate an animated png:
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import os
import imageio.v3 as iio
from apng import APNG
forecast_grib_file = "20250130_graphcast_control.grib"
ds = xr.load_dataset(forecast_grib_file, filter_by_keys={"cfVarName": "t2m"})
temperature = ds["t2m"] - 273.15
lat = ds.latitude
lon = ds.longitude
time_steps = temperature["step"]
# Projection and plot extent (Europe bounding box)
projection = ccrs.PlateCarree()
extent = [-12, 35, 34, 72]
# Temporary folder setup
frame_folder = "hd_frames"
os.makedirs(frame_folder, exist_ok=True)
filenames = []
dpi = 200
fig_width = 3840 / dpi # 3840 pixels width
fig_height = 2160 / dpi # 2160 pixels height
for i, step in enumerate(time_steps):
fig = plt.figure(figsize=(fig_width, fig_height), dpi=dpi)
ax = plt.axes(projection=projection)
ax.set_extent(extent)
# map features
ax.add_feature(cfeature.COASTLINE.with_scale("50m"), linewidth=0.7)
ax.add_feature(cfeature.BORDERS.with_scale("50m"), linestyle=":", linewidth=0.5)
# temperature plot
temp_plot = ax.pcolormesh(
lon,
lat,
temperature.sel(step=step),
cmap="coolwarm",
shading="auto",
vmin=-40,
vmax=50,
)
# Title and colorbar adjustments
cb = plt.colorbar(temp_plot, orientation="vertical", pad=0.02, shrink=0.7)
cb.set_label("2m Temperature (°C)", fontsize=20)
cb.ax.tick_params(labelsize=18)
plt.title(
f"2m Temperature (°C) - Step: {np.array(6*int(step)/21600000000000)} hours",
fontsize=24,
pad=15,
)
# Save the frame
filename = f"{frame_folder}/frame_{i:03d}.png"
plt.savefig(filename, bbox_inches="tight")
filenames.append(filename)
plt.close()
output_file = "temperature_europe_4k.mp4"
fps = 3 # frames per second (~0.3 sec/frame)
# Read frames and determine video size
frames = [iio.imread(filename) for filename in filenames]
# Save as MP4
iio.imwrite(output_file, frames, fps=fps, codec="libx264", quality=8)
# Clean up
for filename in filenames:
os.remove(filename)
os.rmdir(frame_folder)
I then downsampled to 720p with ffmpeg to fit within github upload restraints
20250130_graphcast_t2m.mp4
Metadata
Metadata
Assignees
Labels
No labels