class ZeroEmissionCommitment(ESMValToolDiagnostic):
"""
Calculate the global mean Zero Emission Commitment (ZEC) temperature.
"""
name = "Zero Emission Commitment"
slug = "zero-emission-commitment"
base_recipe = "recipe_zec.yml"
experiments = (
"1pctCO2",
"esm-1pct-brch-1000PgC",
)
data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": ("tas",),
"experiment_id": experiments,
"table_id": "Amon",
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireContiguousTimerange(group_by=("instance_id",)),
RequireOverlappingTimerange(group_by=("instance_id",)),
RequireFacets("experiment_id", experiments),
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
),
),
)
facets = ("grid_label", "member_id", "source_id", "region", "metric")
series = (
SeriesDefinition(
file_pattern="work/zec/zec/zec.nc",
sel={"dim0": 0},
dimensions={
"statistic": "zec",
},
values_name="zec",
index_name="time",
attributes=[],
),
)
@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
) -> None:
"""Update the recipe."""
# Prepare updated datasets section in recipe. It contains two
# datasets, one for the "esm-1pct-brch-1000PgC" and one for the "piControl"
# experiment.
datasets = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])["tas"]["additional_datasets"]
base_dataset = next(ds for ds in datasets if ds["exp"] == "1pctCO2")
dataset = next(ds for ds in datasets if ds["exp"] == "esm-1pct-brch-1000PgC")
start = dataset["timerange"].split("/")[0]
base_start = f"{int(start[:4]) - 10:04d}{start[4:]}"
base_end = f"{int(start[:4]) + 10:04d}{start[4:]}"
base_dataset["timerange"] = f"{base_start}/{base_end}"
variables = recipe["diagnostics"]["zec"]["variables"]
variables["tas_base"] = {
"short_name": "tas",
"preprocessor": "anomaly_base",
"additional_datasets": [base_dataset],
}
variables["tas"] = {
"preprocessor": "spatial_mean",
"additional_datasets": [dataset],
}
@classmethod
def format_result(
cls,
result_dir: Path,
execution_dataset: ExecutionDatasetCollection,
metric_args: MetricBundleArgs,
output_args: OutputBundleArgs,
) -> tuple[CMECMetric, CMECOutput]:
"""Format the result."""
zec_ds = xarray.open_dataset(result_dir / "work" / "zec" / "zec" / "zec_50.nc")
zec = float(fillvalues_to_nan(zec_ds["zec"].values)[0])
# Update the diagnostic bundle arguments with the computed diagnostics.
metric_args[MetricCV.DIMENSIONS.value] = {
"json_structure": ["region", "metric"],
"region": {"global": {}},
"metric": {"zec": {}},
}
metric_args[MetricCV.RESULTS.value] = {
"global": {
"zec": zec,
},
}
return CMECMetric.model_validate(metric_args), CMECOutput.model_validate(output_args)