Note
Go to the end to download the full example code.
HealDA Global Data Assimilation#
Producing a global weather analysis from satellite and in-situ observations.
This example demonstrates how to use the HealDA data assimilation model to produce a global weather analysis on a HEALPix grid from sparse in-situ (conventional) and satellite radiance observations sourced from the NOAA UFS replay archive. Three runs are compared: conventional observations only, satellite observations only, and both combined to illustrate the impact of each observation type.
In this example you will learn:
How to load and initialise the HealDA data assimilation model
Fetching UFS conventional and satellite observation DataFrames
Running the model with different observation combinations
Comparing the assimilated global fields against ERA5 data
# /// script
# dependencies = [
# "earth2studio[da-healda] @ git+https://github.com/NVIDIA/earth2studio.git",
# "cartopy",
# ]
# ///
Set Up#
This example requires the following components:
Assimilation Model: HealDA
earth2studio.models.da.HealDA.Datasource (conv): UFS conventional observations
earth2studio.data.UFSObsConv.Datasource (sat): UFS satellite observations
earth2studio.data.UFSObsSat.
HealDA is a stateless neural-network-based data assimilation model that ingests conventional (radiosonde, surface station, GPS-RO, etc.) and satellite radiance observations and produces a single global weather analysis on a HEALPix level-6 grid.
import os
os.makedirs("outputs", exist_ok=True)
from dotenv import load_dotenv
load_dotenv() # TODO: make common example prep function
from datetime import timedelta
import numpy as np
import torch
from loguru import logger
from tqdm import tqdm
logger.remove()
logger.add(lambda msg: tqdm.write(msg, end=""), colorize=True)
from earth2studio.data import NCAR_ERA5, UFSObsConv, UFSObsSat, fetch_dataframe
from earth2studio.models.da import HealDA
# Load the default model package (downloads checkpoint from HuggingFace)
# Setting lat_lon=True regrids the native HEALPix output to a regular lat-lon grid.
package = HealDA.load_default_package()
model = HealDA.load_model(package, lat_lon=True)
model = model.to("cuda:0")
Downloading config.json: 0%| | 0.00/25.0 [00:00<?, ?B/s]
Downloading config.json: 100%|██████████| 25.0/25.0 [00:00<00:00, 103B/s]
Downloading config.json: 100%|██████████| 25.0/25.0 [00:00<00:00, 102B/s]
Downloading healda_ufs_era5.mdlus: 0%| | 0.00/1.22G [00:00<?, ?B/s]
Downloading healda_ufs_era5.mdlus: 1%| | 10.0M/1.22G [00:00<00:55, 23.5MB/s]
Downloading healda_ufs_era5.mdlus: 2%|▏ | 20.0M/1.22G [00:00<00:31, 40.8MB/s]
Downloading healda_ufs_era5.mdlus: 2%|▏ | 30.0M/1.22G [00:00<00:23, 53.4MB/s]
Downloading healda_ufs_era5.mdlus: 3%|▎ | 40.0M/1.22G [00:00<00:20, 62.7MB/s]
Downloading healda_ufs_era5.mdlus: 4%|▍ | 50.0M/1.22G [00:00<00:18, 69.4MB/s]
Downloading healda_ufs_era5.mdlus: 5%|▍ | 60.0M/1.22G [00:01<00:16, 74.0MB/s]
Downloading healda_ufs_era5.mdlus: 6%|▌ | 70.0M/1.22G [00:01<00:15, 77.2MB/s]
Downloading healda_ufs_era5.mdlus: 6%|▋ | 80.0M/1.22G [00:01<00:15, 79.9MB/s]
Downloading healda_ufs_era5.mdlus: 7%|▋ | 90.0M/1.22G [00:01<00:14, 81.2MB/s]
Downloading healda_ufs_era5.mdlus: 8%|▊ | 100M/1.22G [00:01<00:14, 82.1MB/s]
Downloading healda_ufs_era5.mdlus: 9%|▉ | 110M/1.22G [00:01<00:14, 83.4MB/s]
Downloading healda_ufs_era5.mdlus: 10%|▉ | 120M/1.22G [00:01<00:14, 83.8MB/s]
Downloading healda_ufs_era5.mdlus: 10%|█ | 130M/1.22G [00:01<00:13, 84.2MB/s]
Downloading healda_ufs_era5.mdlus: 11%|█ | 140M/1.22G [00:02<00:13, 84.2MB/s]
Downloading healda_ufs_era5.mdlus: 12%|█▏ | 150M/1.22G [00:02<00:13, 84.4MB/s]
Downloading healda_ufs_era5.mdlus: 13%|█▎ | 160M/1.22G [00:02<00:13, 85.0MB/s]
Downloading healda_ufs_era5.mdlus: 14%|█▎ | 170M/1.22G [00:02<00:13, 85.1MB/s]
Downloading healda_ufs_era5.mdlus: 14%|█▍ | 180M/1.22G [00:02<00:13, 84.9MB/s]
Downloading healda_ufs_era5.mdlus: 15%|█▌ | 190M/1.22G [00:02<00:13, 85.3MB/s]
Downloading healda_ufs_era5.mdlus: 16%|█▌ | 200M/1.22G [00:02<00:12, 85.1MB/s]
Downloading healda_ufs_era5.mdlus: 17%|█▋ | 210M/1.22G [00:02<00:12, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 18%|█▊ | 220M/1.22G [00:03<00:12, 85.3MB/s]
Downloading healda_ufs_era5.mdlus: 18%|█▊ | 230M/1.22G [00:03<00:12, 85.4MB/s]
Downloading healda_ufs_era5.mdlus: 19%|█▉ | 240M/1.22G [00:03<00:12, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 20%|██ | 250M/1.22G [00:03<00:12, 84.8MB/s]
Downloading healda_ufs_era5.mdlus: 21%|██ | 260M/1.22G [00:03<00:12, 84.9MB/s]
Downloading healda_ufs_era5.mdlus: 22%|██▏ | 270M/1.22G [00:03<00:12, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 22%|██▏ | 280M/1.22G [00:03<00:12, 82.3MB/s]
Downloading healda_ufs_era5.mdlus: 23%|██▎ | 290M/1.22G [00:03<00:11, 86.0MB/s]
Downloading healda_ufs_era5.mdlus: 24%|██▍ | 300M/1.22G [00:04<00:11, 85.9MB/s]
Downloading healda_ufs_era5.mdlus: 25%|██▍ | 310M/1.22G [00:04<00:11, 85.6MB/s]
Downloading healda_ufs_era5.mdlus: 26%|██▌ | 320M/1.22G [00:04<00:11, 85.6MB/s]
Downloading healda_ufs_era5.mdlus: 26%|██▋ | 330M/1.22G [00:04<00:11, 85.6MB/s]
Downloading healda_ufs_era5.mdlus: 27%|██▋ | 340M/1.22G [00:04<00:11, 85.3MB/s]
Downloading healda_ufs_era5.mdlus: 28%|██▊ | 350M/1.22G [00:04<00:11, 85.3MB/s]
Downloading healda_ufs_era5.mdlus: 29%|██▉ | 360M/1.22G [00:04<00:10, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 30%|██▉ | 370M/1.22G [00:04<00:10, 85.4MB/s]
Downloading healda_ufs_era5.mdlus: 30%|███ | 380M/1.22G [00:05<00:10, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 31%|███ | 390M/1.22G [00:05<00:10, 85.3MB/s]
Downloading healda_ufs_era5.mdlus: 32%|███▏ | 400M/1.22G [00:05<00:10, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 33%|███▎ | 410M/1.22G [00:05<00:10, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 34%|███▎ | 420M/1.22G [00:05<00:10, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 34%|███▍ | 430M/1.22G [00:05<00:10, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 35%|███▌ | 440M/1.22G [00:05<00:09, 85.0MB/s]
Downloading healda_ufs_era5.mdlus: 36%|███▌ | 450M/1.22G [00:05<00:09, 84.7MB/s]
Downloading healda_ufs_era5.mdlus: 37%|███▋ | 460M/1.22G [00:05<00:09, 85.7MB/s]
Downloading healda_ufs_era5.mdlus: 38%|███▊ | 470M/1.22G [00:06<00:09, 85.6MB/s]
Downloading healda_ufs_era5.mdlus: 38%|███▊ | 480M/1.22G [00:06<00:16, 49.1MB/s]
Downloading healda_ufs_era5.mdlus: 39%|███▉ | 490M/1.22G [00:06<00:14, 56.3MB/s]
Downloading healda_ufs_era5.mdlus: 40%|████ | 500M/1.22G [00:06<00:12, 62.4MB/s]
Downloading healda_ufs_era5.mdlus: 41%|████ | 510M/1.22G [00:06<00:11, 68.1MB/s]
Downloading healda_ufs_era5.mdlus: 42%|████▏ | 520M/1.22G [00:07<00:10, 72.5MB/s]
Downloading healda_ufs_era5.mdlus: 42%|████▏ | 530M/1.22G [00:07<00:09, 75.8MB/s]
Downloading healda_ufs_era5.mdlus: 43%|████▎ | 540M/1.22G [00:07<00:09, 77.6MB/s]
Downloading healda_ufs_era5.mdlus: 44%|████▍ | 550M/1.22G [00:07<00:09, 80.0MB/s]
Downloading healda_ufs_era5.mdlus: 45%|████▍ | 560M/1.22G [00:07<00:08, 82.2MB/s]
Downloading healda_ufs_era5.mdlus: 46%|████▌ | 570M/1.22G [00:07<00:08, 82.6MB/s]
Downloading healda_ufs_era5.mdlus: 46%|████▋ | 580M/1.22G [00:07<00:08, 83.7MB/s]
Downloading healda_ufs_era5.mdlus: 47%|████▋ | 590M/1.22G [00:07<00:08, 84.0MB/s]
Downloading healda_ufs_era5.mdlus: 48%|████▊ | 600M/1.22G [00:08<00:08, 84.6MB/s]
Downloading healda_ufs_era5.mdlus: 49%|████▉ | 610M/1.22G [00:08<00:08, 81.0MB/s]
Downloading healda_ufs_era5.mdlus: 50%|████▉ | 620M/1.22G [00:08<00:08, 82.2MB/s]
Downloading healda_ufs_era5.mdlus: 50%|█████ | 630M/1.22G [00:08<00:07, 87.1MB/s]
Downloading healda_ufs_era5.mdlus: 51%|█████▏ | 640M/1.22G [00:08<00:07, 83.6MB/s]
Downloading healda_ufs_era5.mdlus: 52%|█████▏ | 650M/1.22G [00:08<00:07, 86.8MB/s]
Downloading healda_ufs_era5.mdlus: 53%|█████▎ | 660M/1.22G [00:08<00:07, 84.6MB/s]
Downloading healda_ufs_era5.mdlus: 54%|█████▎ | 670M/1.22G [00:08<00:07, 82.9MB/s]
Downloading healda_ufs_era5.mdlus: 54%|█████▍ | 680M/1.22G [00:08<00:06, 87.4MB/s]
Downloading healda_ufs_era5.mdlus: 55%|█████▌ | 690M/1.22G [00:09<00:06, 86.8MB/s]
Downloading healda_ufs_era5.mdlus: 56%|█████▌ | 700M/1.22G [00:09<00:06, 86.3MB/s]
Downloading healda_ufs_era5.mdlus: 57%|█████▋ | 710M/1.22G [00:09<00:06, 86.0MB/s]
Downloading healda_ufs_era5.mdlus: 58%|█████▊ | 720M/1.22G [00:09<00:06, 85.4MB/s]
Downloading healda_ufs_era5.mdlus: 58%|█████▊ | 730M/1.22G [00:09<00:06, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 59%|█████▉ | 740M/1.22G [00:09<00:06, 85.5MB/s]
Downloading healda_ufs_era5.mdlus: 60%|██████ | 750M/1.22G [00:09<00:06, 85.4MB/s]
Downloading healda_ufs_era5.mdlus: 61%|██████ | 760M/1.22G [00:09<00:05, 85.5MB/s]
Downloading healda_ufs_era5.mdlus: 62%|██████▏ | 770M/1.22G [00:10<00:05, 85.2MB/s]
Downloading healda_ufs_era5.mdlus: 62%|██████▏ | 780M/1.22G [00:10<00:05, 83.9MB/s]
Downloading healda_ufs_era5.mdlus: 63%|██████▎ | 790M/1.22G [00:10<00:05, 80.1MB/s]
Downloading healda_ufs_era5.mdlus: 64%|██████▍ | 800M/1.22G [00:10<00:06, 72.8MB/s]
Downloading healda_ufs_era5.mdlus: 65%|██████▍ | 810M/1.22G [00:10<00:06, 73.9MB/s]
Downloading healda_ufs_era5.mdlus: 66%|██████▋ | 830M/1.22G [00:10<00:04, 93.8MB/s]
Downloading healda_ufs_era5.mdlus: 67%|██████▋ | 840M/1.22G [00:11<00:05, 80.5MB/s]
Downloading healda_ufs_era5.mdlus: 69%|██████▉ | 860M/1.22G [00:11<00:04, 91.7MB/s]
Downloading healda_ufs_era5.mdlus: 70%|██████▉ | 870M/1.22G [00:11<00:06, 62.8MB/s]
Downloading healda_ufs_era5.mdlus: 70%|███████ | 880M/1.22G [00:11<00:06, 62.0MB/s]
Downloading healda_ufs_era5.mdlus: 71%|███████▏ | 890M/1.22G [00:11<00:06, 57.1MB/s]
Downloading healda_ufs_era5.mdlus: 72%|███████▏ | 900M/1.22G [00:12<00:07, 49.1MB/s]
Downloading healda_ufs_era5.mdlus: 73%|███████▎ | 910M/1.22G [00:12<00:07, 46.0MB/s]
Downloading healda_ufs_era5.mdlus: 75%|███████▌ | 940M/1.22G [00:12<00:04, 74.6MB/s]
Downloading healda_ufs_era5.mdlus: 78%|███████▊ | 970M/1.22G [00:12<00:02, 110MB/s]
Downloading healda_ufs_era5.mdlus: 79%|███████▉ | 990M/1.22G [00:13<00:02, 109MB/s]
Downloading healda_ufs_era5.mdlus: 81%|████████ | 0.99G/1.22G [00:13<00:02, 100MB/s]
Downloading healda_ufs_era5.mdlus: 83%|████████▎ | 1.01G/1.22G [00:13<00:02, 95.4MB/s]
Downloading healda_ufs_era5.mdlus: 84%|████████▍ | 1.03G/1.22G [00:13<00:02, 92.3MB/s]
Downloading healda_ufs_era5.mdlus: 85%|████████▍ | 1.04G/1.22G [00:13<00:02, 91.0MB/s]
Downloading healda_ufs_era5.mdlus: 86%|████████▌ | 1.04G/1.22G [00:14<00:02, 90.0MB/s]
Downloading healda_ufs_era5.mdlus: 87%|████████▋ | 1.05G/1.22G [00:14<00:01, 88.8MB/s]
Downloading healda_ufs_era5.mdlus: 87%|████████▋ | 1.06G/1.22G [00:14<00:01, 88.0MB/s]
Downloading healda_ufs_era5.mdlus: 88%|████████▊ | 1.07G/1.22G [00:14<00:01, 87.3MB/s]
Downloading healda_ufs_era5.mdlus: 89%|████████▉ | 1.08G/1.22G [00:14<00:01, 86.7MB/s]
Downloading healda_ufs_era5.mdlus: 90%|████████▉ | 1.09G/1.22G [00:14<00:01, 86.3MB/s]
Downloading healda_ufs_era5.mdlus: 91%|█████████ | 1.10G/1.22G [00:14<00:01, 84.3MB/s]
Downloading healda_ufs_era5.mdlus: 91%|█████████▏| 1.11G/1.22G [00:14<00:01, 86.3MB/s]
Downloading healda_ufs_era5.mdlus: 92%|█████████▏| 1.12G/1.22G [00:14<00:01, 85.8MB/s]
Downloading healda_ufs_era5.mdlus: 93%|█████████▎| 1.13G/1.22G [00:15<00:01, 85.4MB/s]
Downloading healda_ufs_era5.mdlus: 94%|█████████▎| 1.14G/1.22G [00:15<00:00, 85.7MB/s]
Downloading healda_ufs_era5.mdlus: 95%|█████████▍| 1.15G/1.22G [00:15<00:00, 75.6MB/s]
Downloading healda_ufs_era5.mdlus: 95%|█████████▌| 1.16G/1.22G [00:15<00:00, 77.0MB/s]
Downloading healda_ufs_era5.mdlus: 96%|█████████▌| 1.17G/1.22G [00:15<00:00, 79.2MB/s]
Downloading healda_ufs_era5.mdlus: 97%|█████████▋| 1.18G/1.22G [00:15<00:00, 80.8MB/s]
Downloading healda_ufs_era5.mdlus: 98%|█████████▊| 1.19G/1.22G [00:15<00:00, 81.6MB/s]
Downloading healda_ufs_era5.mdlus: 99%|█████████▊| 1.20G/1.22G [00:16<00:00, 82.5MB/s]
Downloading healda_ufs_era5.mdlus: 99%|█████████▉| 1.21G/1.22G [00:16<00:00, 70.5MB/s]
Downloading healda_ufs_era5.mdlus: 100%|██████████| 1.22G/1.22G [00:16<00:00, 66.7MB/s]
Downloading healda_ufs_era5.mdlus: 100%|██████████| 1.22G/1.22G [00:16<00:00, 79.8MB/s]
Downloading condition_hpx6_padxy.npy: 0%| | 0.00/384k [00:00<?, ?B/s]
Downloading condition_hpx6_padxy.npy: 100%|██████████| 384k/384k [00:00<00:00, 881kB/s]
Downloading condition_hpx6_padxy.npy: 100%|██████████| 384k/384k [00:00<00:00, 878kB/s]
Downloading atms_normalizations.csv: 0%| | 0.00/2.78k [00:00<?, ?B/s]
Downloading atms_normalizations.csv: 100%|██████████| 2.78k/2.78k [00:00<00:00, 13.4kB/s]
Downloading atms_normalizations.csv: 100%|██████████| 2.78k/2.78k [00:00<00:00, 13.3kB/s]
Downloading mhs_normalizations.csv: 0%| | 0.00/1.28k [00:00<?, ?B/s]
Downloading mhs_normalizations.csv: 100%|██████████| 1.28k/1.28k [00:00<00:00, 6.58kB/s]
Downloading mhs_normalizations.csv: 100%|██████████| 1.28k/1.28k [00:00<00:00, 6.54kB/s]
Downloading amsua_normalizations.csv: 0%| | 0.00/4.67k [00:00<?, ?B/s]
Downloading amsua_normalizations.csv: 100%|██████████| 4.67k/4.67k [00:00<00:00, 22.7kB/s]
Downloading amsua_normalizations.csv: 100%|██████████| 4.67k/4.67k [00:00<00:00, 22.5kB/s]
Downloading amsub_normalizations.csv: 0%| | 0.00/675 [00:00<?, ?B/s]
Downloading amsub_normalizations.csv: 100%|██████████| 675/675 [00:00<00:00, 2.36kB/s]
Downloading amsub_normalizations.csv: 100%|██████████| 675/675 [00:00<00:00, 2.35kB/s]
Downloading conv_normalizations.csv: 0%| | 0.00/632 [00:00<?, ?B/s]
Downloading conv_normalizations.csv: 100%|██████████| 632/632 [00:00<00:00, 2.25kB/s]
Downloading conv_normalizations.csv: 100%|██████████| 632/632 [00:00<00:00, 2.24kB/s]
Downloading era5_13_levels_stats.csv: 0%| | 0.00/3.36k [00:00<?, ?B/s]
Downloading era5_13_levels_stats.csv: 100%|██████████| 3.36k/3.36k [00:00<00:00, 16.2kB/s]
Downloading era5_13_levels_stats.csv: 100%|██████████| 3.36k/3.36k [00:00<00:00, 16.1kB/s]
Fetch Observations#
Pull conventional and satellite observation DataFrames for the analysis time.
The UFS data sources return pandas DataFrames that match the schemas expected by
HealDA.input_coords(). We use
earth2studio.data.fetch_dataframe() which attaches request_time
metadata required by the model. The time_tolerance parameter defines a time
window around the analysis time so that observations will be retrieved for.
analysis_time = np.array([np.datetime64("2024-01-01T00:00")])
conv_source = UFSObsConv(time_tolerance=(timedelta(hours=-21), timedelta(hours=3)))
conv_schema, sat_schema = model.input_coords()
conv_df = fetch_dataframe(
conv_source,
time=analysis_time,
variable=np.array(conv_schema["variable"]),
fields=np.array(list(conv_schema.keys())),
)
logger.info(f"Fetched {len(conv_df)} conventional observations")
sat_source = UFSObsSat(time_tolerance=(timedelta(hours=-21), timedelta(hours=3)))
sat_df = fetch_dataframe(
sat_source,
time=analysis_time,
variable=np.array(sat_schema["variable"]),
fields=np.array(list(sat_schema.keys())),
)
logger.info(f"Fetched {len(sat_df)} satellite observations")
Fetching GSI files: 0%| | 0/25 [00:00<?, ?it/s]
Fetching GSI files: 4%|▍ | 1/25 [00:00<00:12, 1.86it/s]
Fetching GSI files: 12%|█▏ | 3/25 [00:00<00:04, 4.90it/s]
Fetching GSI files: 24%|██▍ | 6/25 [00:00<00:02, 9.25it/s]
Fetching GSI files: 36%|███▌ | 9/25 [00:01<00:01, 11.14it/s]
Fetching GSI files: 48%|████▊ | 12/25 [00:01<00:00, 14.48it/s]
Fetching GSI files: 64%|██████▍ | 16/25 [00:01<00:00, 18.08it/s]
Fetching GSI files: 80%|████████ | 20/25 [00:01<00:00, 21.57it/s]
Fetching GSI files: 92%|█████████▏| 23/25 [00:01<00:00, 20.91it/s]
Fetching GSI files: 100%|██████████| 25/25 [00:01<00:00, 13.90it/s]
2026-05-18 02:42:28.329 | INFO | __main__:<module>:108 - Fetched 8515112 conventional observations
Fetching GSI files: 0%| | 0/90 [00:00<?, ?it/s]
2026-05-18 02:42:28.662 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsub_n16_ges.2023123112_control.nc4 not found
Fetching GSI files: 0%| | 0/90 [00:00<?, ?it/s]
Fetching GSI files: 1%| | 1/90 [00:00<00:24, 3.65it/s]
2026-05-18 02:42:28.668 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsub_n16_ges.2023123100_control.nc4 not found
Fetching GSI files: 1%| | 1/90 [00:00<00:24, 3.65it/s]
2026-05-18 02:42:28.735 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsua_n17_ges.2024010100_control.nc4 not found
Fetching GSI files: 1%| | 1/90 [00:00<00:24, 3.65it/s]
Fetching GSI files: 4%|▍ | 4/90 [00:00<00:17, 4.83it/s]
2026-05-18 02:42:29.329 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsub_n15_ges.2023123118_control.nc4 not found
Fetching GSI files: 4%|▍ | 4/90 [00:00<00:17, 4.83it/s]
Fetching GSI files: 10%|█ | 9/90 [00:00<00:06, 11.89it/s]
2026-05-18 02:42:29.400 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_mhs_metop-a_ges.2023123112_control.nc4 not found
Fetching GSI files: 10%|█ | 9/90 [00:01<00:06, 11.89it/s]
2026-05-18 02:42:29.406 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsub_n16_ges.2024010100_control.nc4 not found
Fetching GSI files: 10%|█ | 9/90 [00:01<00:06, 11.89it/s]
2026-05-18 02:42:29.412 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsua_n16_ges.2023123100_control.nc4 not found
Fetching GSI files: 10%|█ | 9/90 [00:01<00:06, 11.89it/s]
Fetching GSI files: 14%|█▍ | 13/90 [00:01<00:04, 16.19it/s]
2026-05-18 02:42:29.469 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsua_n17_ges.2023123112_control.nc4 not found
Fetching GSI files: 14%|█▍ | 13/90 [00:01<00:04, 16.19it/s]
2026-05-18 02:42:29.486 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsua_metop-a_ges.2023123106_control.nc4 not found
Fetching GSI files: 14%|█▍ | 13/90 [00:01<00:04, 16.19it/s]
2026-05-18 02:42:29.545 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsub_n17_ges.2023123106_control.nc4 not found
Fetching GSI files: 14%|█▍ | 13/90 [00:01<00:04, 16.19it/s]
2026-05-18 02:42:29.546 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_mhs_n18_ges.2023123106_control.nc4 not found
Fetching GSI files: 14%|█▍ | 13/90 [00:01<00:04, 16.19it/s]
2026-05-18 02:42:29.613 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsua_n17_ges.2023123106_control.nc4 not found
Fetching GSI files: 14%|█▍ | 13/90 [00:01<00:04, 16.19it/s]
Fetching GSI files: 23%|██▎ | 21/90 [00:01<00:02, 26.48it/s]
2026-05-18 02:42:29.615 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_mhs_n18_ges.2023123112_control.nc4 not found
Fetching GSI files: 23%|██▎ | 21/90 [00:01<00:02, 26.48it/s]
2026-05-18 02:42:29.619 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsua_metop-a_ges.2023123118_control.nc4 not found
Fetching GSI files: 23%|██▎ | 21/90 [00:01<00:02, 26.48it/s]
2026-05-18 02:42:29.688 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsua_n16_ges.2023123112_control.nc4 not found
Fetching GSI files: 23%|██▎ | 21/90 [00:01<00:02, 26.48it/s]
2026-05-18 02:42:29.693 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsub_n16_ges.2023123118_control.nc4 not found
Fetching GSI files: 23%|██▎ | 21/90 [00:01<00:02, 26.48it/s]
Fetching GSI files: 31%|███ | 28/90 [00:01<00:01, 33.72it/s]
2026-05-18 02:42:29.742 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsub_n17_ges.2023123112_control.nc4 not found
Fetching GSI files: 31%|███ | 28/90 [00:01<00:01, 33.72it/s]
2026-05-18 02:42:29.772 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_mhs_metop-a_ges.2024010100_control.nc4 not found
Fetching GSI files: 31%|███ | 28/90 [00:01<00:01, 33.72it/s]
2026-05-18 02:42:29.809 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsua_n16_ges.2023123118_control.nc4 not found
Fetching GSI files: 31%|███ | 28/90 [00:01<00:01, 33.72it/s]
Fetching GSI files: 40%|████ | 36/90 [00:01<00:01, 42.53it/s]
2026-05-18 02:42:29.898 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsua_n16_ges.2024010100_control.nc4 not found
Fetching GSI files: 40%|████ | 36/90 [00:01<00:01, 42.53it/s]
2026-05-18 02:42:29.924 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsub_n17_ges.2023123118_control.nc4 not found
Fetching GSI files: 40%|████ | 36/90 [00:01<00:01, 42.53it/s]
Fetching GSI files: 47%|████▋ | 42/90 [00:01<00:01, 37.08it/s]
2026-05-18 02:42:30.083 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_mhs_n18_ges.2024010100_control.nc4 not found
Fetching GSI files: 47%|████▋ | 42/90 [00:01<00:01, 37.08it/s]
2026-05-18 02:42:30.103 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsua_metop-a_ges.2023123100_control.nc4 not found
Fetching GSI files: 47%|████▋ | 42/90 [00:01<00:01, 37.08it/s]
2026-05-18 02:42:30.143 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_mhs_metop-a_ges.2023123100_control.nc4 not found
Fetching GSI files: 47%|████▋ | 42/90 [00:01<00:01, 37.08it/s]
2026-05-18 02:42:30.176 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsub_n15_ges.2023123112_control.nc4 not found
Fetching GSI files: 47%|████▋ | 42/90 [00:01<00:01, 37.08it/s]
Fetching GSI files: 56%|█████▌ | 50/90 [00:01<00:00, 44.90it/s]
2026-05-18 02:42:30.213 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_mhs_n18_ges.2023123100_control.nc4 not found
Fetching GSI files: 56%|█████▌ | 50/90 [00:01<00:00, 44.90it/s]
2026-05-18 02:42:30.218 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_mhs_metop-a_ges.2023123118_control.nc4 not found
Fetching GSI files: 56%|█████▌ | 50/90 [00:01<00:00, 44.90it/s]
2026-05-18 02:42:30.282 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_mhs_metop-a_ges.2023123106_control.nc4 not found
Fetching GSI files: 56%|█████▌ | 50/90 [00:01<00:00, 44.90it/s]
Fetching GSI files: 62%|██████▏ | 56/90 [00:01<00:00, 47.57it/s]
2026-05-18 02:42:30.299 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_mhs_n18_ges.2023123118_control.nc4 not found
Fetching GSI files: 62%|██████▏ | 56/90 [00:01<00:00, 47.57it/s]
2026-05-18 02:42:30.313 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsua_n16_ges.2023123106_control.nc4 not found
Fetching GSI files: 62%|██████▏ | 56/90 [00:01<00:00, 47.57it/s]
2026-05-18 02:42:30.353 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsub_n15_ges.2024010100_control.nc4 not found
Fetching GSI files: 62%|██████▏ | 56/90 [00:01<00:00, 47.57it/s]
2026-05-18 02:42:30.370 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsub_n16_ges.2023123106_control.nc4 not found
Fetching GSI files: 62%|██████▏ | 56/90 [00:01<00:00, 47.57it/s]
Fetching GSI files: 69%|██████▉ | 62/90 [00:02<00:00, 46.78it/s]
2026-05-18 02:42:30.444 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsub_n17_ges.2024010100_control.nc4 not found
Fetching GSI files: 69%|██████▉ | 62/90 [00:02<00:00, 46.78it/s]
2026-05-18 02:42:30.513 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsua_metop-a_ges.2024010100_control.nc4 not found
Fetching GSI files: 69%|██████▉ | 62/90 [00:02<00:00, 46.78it/s]
Fetching GSI files: 76%|███████▌ | 68/90 [00:02<00:00, 49.65it/s]
2026-05-18 02:42:30.523 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsua_n17_ges.2023123118_control.nc4 not found
Fetching GSI files: 76%|███████▌ | 68/90 [00:02<00:00, 49.65it/s]
2026-05-18 02:42:30.586 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsua_metop-a_ges.2023123112_control.nc4 not found
Fetching GSI files: 76%|███████▌ | 68/90 [00:02<00:00, 49.65it/s]
2026-05-18 02:42:30.588 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsub_n17_ges.2023123100_control.nc4 not found
Fetching GSI files: 76%|███████▌ | 68/90 [00:02<00:00, 49.65it/s]
2026-05-18 02:42:30.594 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsub_n15_ges.2023123106_control.nc4 not found
Fetching GSI files: 76%|███████▌ | 68/90 [00:02<00:00, 49.65it/s]
2026-05-18 02:42:30.662 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsua_n17_ges.2023123100_control.nc4 not found
Fetching GSI files: 76%|███████▌ | 68/90 [00:02<00:00, 49.65it/s]
Fetching GSI files: 84%|████████▍ | 76/90 [00:02<00:00, 51.56it/s]
2026-05-18 02:42:30.764 | WARNING | earth2studio.data.ufs:_handle_missing_file:758 - File s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsub_n15_ges.2023123100_control.nc4 not found
Fetching GSI files: 84%|████████▍ | 76/90 [00:02<00:00, 51.56it/s]
Fetching GSI files: 91%|█████████ | 82/90 [00:02<00:00, 46.39it/s]
Fetching GSI files: 97%|█████████▋| 87/90 [00:02<00:00, 40.46it/s]
Fetching GSI files: 100%|██████████| 90/90 [00:02<00:00, 33.85it/s]
2026-05-18 02:42:33.550 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_mhs_metop-a_ges.2023123100_control.nc4
2026-05-18 02:42:33.550 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_mhs_metop-a_ges.2023123106_control.nc4
2026-05-18 02:42:33.550 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_mhs_metop-a_ges.2023123112_control.nc4
2026-05-18 02:42:33.550 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_mhs_metop-a_ges.2023123118_control.nc4
2026-05-18 02:42:33.550 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_mhs_metop-a_ges.2024010100_control.nc4
2026-05-18 02:42:35.241 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_mhs_n18_ges.2023123100_control.nc4
2026-05-18 02:42:35.241 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_mhs_n18_ges.2023123106_control.nc4
2026-05-18 02:42:35.241 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_mhs_n18_ges.2023123112_control.nc4
2026-05-18 02:42:35.241 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_mhs_n18_ges.2023123118_control.nc4
2026-05-18 02:42:35.241 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_mhs_n18_ges.2024010100_control.nc4
2026-05-18 02:42:36.066 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsua_metop-a_ges.2023123100_control.nc4
2026-05-18 02:42:36.066 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsua_metop-a_ges.2023123106_control.nc4
2026-05-18 02:42:36.066 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsua_metop-a_ges.2023123112_control.nc4
2026-05-18 02:42:36.066 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsua_metop-a_ges.2023123118_control.nc4
2026-05-18 02:42:36.066 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsua_metop-a_ges.2024010100_control.nc4
2026-05-18 02:42:38.856 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsua_n16_ges.2023123100_control.nc4
2026-05-18 02:42:38.856 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsua_n16_ges.2023123106_control.nc4
2026-05-18 02:42:38.856 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsua_n16_ges.2023123112_control.nc4
2026-05-18 02:42:38.856 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsua_n16_ges.2023123118_control.nc4
2026-05-18 02:42:38.857 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsua_n16_ges.2024010100_control.nc4
2026-05-18 02:42:38.857 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsua_n17_ges.2023123100_control.nc4
2026-05-18 02:42:38.857 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsua_n17_ges.2023123106_control.nc4
2026-05-18 02:42:38.857 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsua_n17_ges.2023123112_control.nc4
2026-05-18 02:42:38.857 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsua_n17_ges.2023123118_control.nc4
2026-05-18 02:42:38.857 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsua_n17_ges.2024010100_control.nc4
2026-05-18 02:42:40.761 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsub_n15_ges.2023123100_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsub_n15_ges.2023123106_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsub_n15_ges.2023123112_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsub_n15_ges.2023123118_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsub_n15_ges.2024010100_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsub_n16_ges.2023123100_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsub_n16_ges.2023123106_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsub_n16_ges.2023123112_control.nc4
2026-05-18 02:42:40.762 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsub_n16_ges.2023123118_control.nc4
2026-05-18 02:42:40.763 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsub_n16_ges.2024010100_control.nc4
2026-05-18 02:42:40.763 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123100/gsi/diag_amsub_n17_ges.2023123100_control.nc4
2026-05-18 02:42:40.763 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123106/gsi/diag_amsub_n17_ges.2023123106_control.nc4
2026-05-18 02:42:40.763 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123112/gsi/diag_amsub_n17_ges.2023123112_control.nc4
2026-05-18 02:42:40.763 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2023/12/2023123118/gsi/diag_amsub_n17_ges.2023123118_control.nc4
2026-05-18 02:42:40.763 | WARNING | earth2studio.data.ufs:_compile_dataframe:218 - Cached file missing for s3://noaa-ufs-gefsv13replay-pds/2024/01/2024010100/gsi/diag_amsub_n17_ges.2024010100_control.nc4
2026-05-18 02:42:40.922 | INFO | __main__:<module>:117 - Fetched 4378286 satellite observations
Observation Locations#
Plot the spatial distribution of conventional and satellite observations to visualise their coverage before running the assimilation. There are 12-14 million observations typically for the model’s 24-hour time window.
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
plt.close("all")
fig, axes = plt.subplots(
1,
2,
subplot_kw={"projection": ccrs.Robinson()},
figsize=(16, 4),
)
# Conventional observations
ax = axes[0]
ax.set_global()
ax.coastlines(linewidth=0.5)
ax.gridlines(linewidth=0.3, alpha=0.5)
ax.scatter(
conv_df["lon"].values[::10],
conv_df["lat"].values[::10],
s=0.1,
alpha=0.3,
c="tab:blue",
transform=ccrs.PlateCarree(),
)
ax.set_title(f"Conventional obs (n={len(conv_df):,})", fontsize=13)
# Satellite observations
ax = axes[1]
ax.set_global()
ax.coastlines(linewidth=0.5)
ax.gridlines(linewidth=0.3, alpha=0.5)
ax.scatter(
sat_df["lon"].values[::10],
sat_df["lat"].values[::10],
s=0.1,
alpha=0.3,
c="tab:orange",
transform=ccrs.PlateCarree(),
)
ax.set_title(f"Satellite obs (n={len(sat_df):,})", fontsize=13)
fig.suptitle(
f"Observation Locations {str(analysis_time[0])[:16]} UTC",
fontsize=15,
)
plt.tight_layout()
plt.savefig("outputs/22_healda_obs_locations.jpg", dpi=150)

DA models can be called directly for stateless inference or via
create_generator() for stateful (iterative)
assimilation workflows. Here we use the direct call API to invoke the model.
HealDA is designed to work with the (-21, 3) hour observation window from the UFS replay archive using both conventional and satellite observations. However, the DA model interface is flexible enough to accept different time windows and observation sources. Below we test three configurations - conventional only, satellite only, and proper combined - to illustrate the impact each observation type has on the analysis.
torch.manual_seed(42)
result_both = model(conv_obs=conv_df, sat_obs=sat_df)
logger.info(f"Combined analysis shape: {result_both.shape}")
2026-05-18 02:42:55.196 | INFO | __main__:<module>:188 - Combined analysis shape: (1, 74, 181, 360)
torch.manual_seed(42)
result_sat = model(sat_obs=sat_df)
logger.info(f"Sat-only analysis shape: {result_sat.shape}")
2026-05-18 02:42:58.523 | INFO | __main__:<module>:193 - Sat-only analysis shape: (1, 74, 181, 360)
torch.manual_seed(42)
result_conv = model(conv_obs=conv_df)
logger.info(f"Conv-only analysis shape: {result_conv.shape}")
2026-05-18 02:43:03.006 | INFO | __main__:<module>:198 - Conv-only analysis shape: (1, 74, 181, 360)
Post Processing#
Because we loaded the model with lat_lon=True the output is already on a
regular equiangular lat-lon grid, so no manual regridding is needed.
Compare the three runs for surface temperature (t2m) and geopotential 500 hPa
(z500). Each row shows a different observation configuration.
plt.close("all")
plot_vars = ["t2m", "z500"]
titles = ["Conv + Sat", "Sat only", "Conv only"]
results = [result_both, result_sat, result_conv]
projection = ccrs.Robinson()
fig, axes = plt.subplots(
len(results),
len(plot_vars),
subplot_kw={"projection": projection},
figsize=(14, 8),
)
fig.subplots_adjust(wspace=0.02, hspace=0.08, left=0.1, right=0.9)
lat = results[0].coords["lat"].values
lon = results[0].coords["lon"].values
cmaps = ["Spectral_r", "PRGn"]
def to_numpy(arr):
"""CuPy / Numpy helper function"""
return arr.get() if hasattr(arr, "get") else arr
for row, (title, da) in enumerate(zip(titles, results)):
for col, var in enumerate(plot_vars):
ax = axes[row, col]
field = to_numpy(da.sel(variable=var).data[0])
im = ax.pcolormesh(
lon,
lat,
field,
transform=ccrs.PlateCarree(),
cmap=cmaps[col],
)
ax.coastlines(linewidth=0.5)
ax.gridlines(linewidth=0.3, alpha=0.5)
fig.colorbar(im, ax=ax, shrink=0.6)
if row == 0:
ax.set_title(var, fontsize=14)
if col == 0:
ax.text(
-0.05,
0.5,
title,
fontsize=12,
va="bottom",
ha="center",
rotation="vertical",
rotation_mode="anchor",
transform=ax.transAxes,
)
fig.suptitle(f"HealDA Analysis {str(analysis_time[0])[:16]} UTC", fontsize=18, y=0.97)
plt.tight_layout()
plt.savefig("outputs/22_healda_analysis.jpg", dpi=150)

HealDA vs ERA5#
Next fetch ERA5 reanalysis at 0.25° resolution from the NCAR archive to compare against the assimilated fields. HealDA outputs standard Earth2Studio variable names so we can query ERA5 with the same identifiers. We expect the runs that are missing an observation source to show larger errors, while the combined run yields the most accurate global prediction.
era5_ds = NCAR_ERA5()
era5_da = era5_ds(analysis_time, plot_vars)
era5_interp = era5_da.interp(lat=lat, lon=lon, method="nearest")
Fetching NCAR ERA5 data: 0%| | 0/2 [00:00<?, ?it/s]
2026-05-18 02:43:32.683 | DEBUG | earth2studio.data.ncar:fetch_array:389 - Fetching NCAR ERA5 variable: 2T in file s3://nsf-ncar-era5/e5.oper.an.sfc/202401/e5.oper.an.sfc.128_167_2t.ll025sc.2024010100_2024013123.nc
Fetching NCAR ERA5 data: 0%| | 0/2 [00:00<?, ?it/s]
2026-05-18 02:43:32.684 | DEBUG | earth2studio.data.ncar:fetch_array:389 - Fetching NCAR ERA5 variable: Z in file s3://nsf-ncar-era5/e5.oper.an.pl/202401/e5.oper.an.pl.128_129_z.ll025sc.2024010100_2024010123.nc
Fetching NCAR ERA5 data: 0%| | 0/2 [00:00<?, ?it/s]
Fetching NCAR ERA5 data: 50%|█████ | 1/2 [00:07<00:07, 7.22s/it]
Fetching NCAR ERA5 data: 100%|██████████| 2/2 [00:07<00:00, 3.65s/it]
diff_titles = ["Conv+Sat - ERA5", "Sat - ERA5", "Conv - ERA5"]
diff_results = [result_both, result_sat, result_conv]
for title, da_pred in zip(diff_titles, diff_results):
for var in plot_vars:
field_pred = to_numpy(da_pred.sel(variable=var).data[0])
field_era5 = to_numpy(era5_interp.sel(variable=var).data[0])
mae = float(np.abs(field_pred - field_era5).mean())
logger.info(f"{title} | {var} MAE: {mae:.4f}")
2026-05-18 02:43:40.039 | INFO | __main__:<module>:288 - Conv+Sat - ERA5 | t2m MAE: 1.4210
2026-05-18 02:43:40.040 | INFO | __main__:<module>:288 - Conv+Sat - ERA5 | z500 MAE: 208.3272
2026-05-18 02:43:40.042 | INFO | __main__:<module>:288 - Sat - ERA5 | t2m MAE: 1.6925
2026-05-18 02:43:40.043 | INFO | __main__:<module>:288 - Sat - ERA5 | z500 MAE: 536.9377
2026-05-18 02:43:40.044 | INFO | __main__:<module>:288 - Conv - ERA5 | t2m MAE: 4.3268
2026-05-18 02:43:40.046 | INFO | __main__:<module>:288 - Conv - ERA5 | z500 MAE: 560.6304
plt.close("all")
diff_ranges = {"t2m": (-10, 10), "z500": (-500, 500)}
fig, axes = plt.subplots(
len(diff_results),
len(plot_vars),
subplot_kw={"projection": projection},
figsize=(14, 8),
)
fig.subplots_adjust(wspace=0.02, hspace=0.08, left=0.1, right=0.9)
for row, (title, da_pred) in enumerate(zip(diff_titles, diff_results)):
for col, var in enumerate(plot_vars):
ax = axes[row, col]
field_pred = to_numpy(da_pred.sel(variable=var).data[0])
field_era5 = to_numpy(era5_interp.sel(variable=var).data[0])
diff = field_pred - field_era5
im = ax.pcolormesh(
lon,
lat,
diff,
transform=ccrs.PlateCarree(),
cmap="RdBu_r",
vmin=diff_ranges[var][0],
vmax=diff_ranges[var][1],
)
ax.coastlines(linewidth=0.5)
ax.gridlines(linewidth=0.3, alpha=0.5)
fig.colorbar(im, ax=ax, shrink=0.6)
if row == 0:
ax.set_title(var, fontsize=14)
if col == 0:
bbox = ax.get_position()
ax.text(
-0.05,
0.5,
title,
fontsize=12,
va="bottom",
ha="center",
rotation="vertical",
rotation_mode="anchor",
transform=ax.transAxes,
)
fig.suptitle(
f"HealDA Analysis Error {str(analysis_time[0])[:16]} UTC",
fontsize=18,
y=0.97,
)
plt.savefig("outputs/22_healda_differences.jpg", dpi=150, bbox_inches="tight")

Total running time of the script: (2 minutes 11.650 seconds)