Single Case
Running EWB across all 337 default cases is the standard workflow, but
sometimes you only need to evaluate one specific event — to debug a
result, inspect a forecast failure, or prototype a new metric. This
recipe shows two approaches: filtering from the default case list, and
defining a custom IndividualCase from scratch. See
Usage for the full multi-case evaluation workflow.
Approach 1 — Filter from the default case list
Load all EWB cases, then keep only the one you care about using its
case_id_number or any other field on IndividualCase:
import extremeweatherbench as ewb
all_cases = ewb.load_cases()
# Keep only case 28 (inspect the full list to find your case)
single_case = [c for c in all_cases if c.case_id_number == 28]
target = ewb.ERA5(variables=["surface_air_temperature"])
forecast = ewb.ZarrForecast(
source="gs://weatherbench2/datasets/hres/2016-2022-0012-1440x721.zarr",
name="HRES",
variable_mapping=ewb.HRES_metadata_variable_mapping,
storage_options={"remote_options": {"anon": True}},
)
eval_objects = [
ewb.EvaluationObject(
event_type="heat_wave",
metric_list=[
ewb.metrics.MeanAbsoluteError(
forecast_variable="surface_air_temperature",
target_variable="surface_air_temperature",
),
ewb.metrics.MaximumMeanAbsoluteError(
forecast_variable="surface_air_temperature",
target_variable="surface_air_temperature",
),
],
target=target,
forecast=forecast,
),
]
runner = ewb.evaluation(
case_metadata=single_case,
evaluation_objects=eval_objects,
)
outputs = runner.run_evaluation()
print(outputs)
Detailed Explanation:
ewb.load_cases()returns a list ofIndividualCaseobjects. Each object hascase_id_number,title,start_date,end_date,location, andevent_typeattributes. Passing a single-element list toewb.evaluationis identical to running all cases — the evaluation engine is a loop over that list.
Approach 2 — Define a case from scratch
Use IndividualCase directly when you want to evaluate an event that
is not in the EWB default set, or when you want full control over the
spatial bounds and date range:
import datetime
import extremeweatherbench as ewb
from extremeweatherbench.cases import IndividualCase
from extremeweatherbench.regions import BoundingBoxRegion
# June 2021 Pacific Northwest heat dome
pnw_heat_dome = IndividualCase(
case_id_number=9999,
title="2021 Pacific Northwest Heat Dome",
start_date=datetime.datetime(2021, 6, 26),
end_date=datetime.datetime(2021, 7, 2),
location=BoundingBoxRegion.create_region(
latitude_min=42.0,
latitude_max=52.0,
longitude_min=234.0, # 126 °W in 0–360
longitude_max=247.0, # 113 °W in 0–360
),
event_type="heat_wave",
)
target = ewb.ERA5(variables=["surface_air_temperature"])
forecast = ewb.ZarrForecast(
source="gs://weatherbench2/datasets/hres/2016-2022-0012-1440x721.zarr",
name="HRES",
variable_mapping=ewb.HRES_metadata_variable_mapping,
storage_options={"remote_options": {"anon": True}},
)
eval_objects = [
ewb.EvaluationObject(
event_type="heat_wave",
metric_list=[
ewb.metrics.MeanAbsoluteError(
forecast_variable="surface_air_temperature",
target_variable="surface_air_temperature",
),
ewb.metrics.MaximumMeanAbsoluteError(
forecast_variable="surface_air_temperature",
target_variable="surface_air_temperature",
),
],
target=target,
forecast=forecast,
),
]
runner = ewb.evaluation(
case_metadata=[pnw_heat_dome],
evaluation_objects=eval_objects,
)
outputs = runner.run_evaluation()
Detailed Explanation:
BoundingBoxRegion.create_regionacceptslatitude_min,latitude_max,longitude_min, andlongitude_max. Longitudes must be in the 0–360 convention to match EWB's internal coordinate system. You can convert from −180–180 withewb.convert_longitude_to_360. Theevent_typefield must match theevent_typeon at least oneEvaluationObject; otherwise, the case is skipped by the pipeline.
Loading cases from a custom YAML file
If you maintain your own YAML of case definitions (same schema as EWB's
events.yaml), load them directly:
import extremeweatherbench as ewb
my_cases = ewb.load_individual_cases_from_yaml("path/to/my_cases.yaml")
single_case = [c for c in my_cases if c.case_id_number == 1]
runner = ewb.evaluation(
case_metadata=single_case,
evaluation_objects=eval_objects,
)
The YAML schema for a single case entry:
- case_id_number: 1
title: My Custom Event
start_date: 2022-08-10 00:00:00
end_date: 2022-08-14 00:00:00
location:
type: bounded_region
parameters:
latitude_min: 30.0
latitude_max: 45.0
longitude_min: 260.0
longitude_max: 280.0
event_type: heat_wave
Complete Example
A custom case (2021 Pacific Northwest heat dome) evaluated against ERA5 with no filtering of the default case list required.
import datetime
import extremeweatherbench as ewb
from extremeweatherbench.cases import IndividualCase
from extremeweatherbench.regions import BoundingBoxRegion
demo_case = IndividualCase(
case_id_number=9008,
title="2021 Pacific NW Heat Dome (demo)",
start_date=datetime.datetime(2021, 6, 27),
end_date=datetime.datetime(2021, 6, 30),
location=BoundingBoxRegion.create_region(
latitude_min=44.0,
latitude_max=50.0,
longitude_min=235.0,
longitude_max=241.0,
),
event_type="heat_wave",
)
cases = [demo_case]
forecast = ewb.ZarrForecast(
source="gs://weatherbench2/datasets/hres/2016-2022-0012-1440x721.zarr",
name="HRES",
variable_mapping=ewb.HRES_metadata_variable_mapping,
storage_options={"remote_options": {"anon": True}},
)
target = ewb.ERA5(variables=["surface_air_temperature"])
eval_objects = [
ewb.EvaluationObject(
event_type="heat_wave",
metric_list=[
ewb.metrics.MeanAbsoluteError(
forecast_variable="surface_air_temperature",
target_variable="surface_air_temperature",
),
ewb.metrics.MaximumMeanAbsoluteError(
forecast_variable="surface_air_temperature",
target_variable="surface_air_temperature",
),
],
target=target,
forecast=forecast,
),
]
runner = ewb.evaluation(
case_metadata=cases,
evaluation_objects=eval_objects,
)
outputs = runner.run_evaluation()
print(outputs)