Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/204.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added Zero Emission Commitment (ZEC) metric to the ESMValTool metrics package.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
from cmip_ref_metrics_esmvaltool.metrics.ecs import EquilibriumClimateSensitivity
from cmip_ref_metrics_esmvaltool.metrics.example import GlobalMeanTimeseries
from cmip_ref_metrics_esmvaltool.metrics.tcr import TransientClimateResponse
from cmip_ref_metrics_esmvaltool.metrics.zec import ZeroEmissionCommitment

__all__ = [
"EquilibriumClimateSensitivity",
"GlobalMeanTimeseries",
"TransientClimateResponse",
"ZeroEmissionCommitment",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
from pathlib import Path

import pandas
import xarray

from cmip_ref_core.constraints import (
AddSupplementaryDataset,
RequireContiguousTimerange,
RequireFacets,
RequireOverlappingTimerange,
)
from cmip_ref_core.datasets import FacetFilter, SourceDatasetType
from cmip_ref_core.metrics import DataRequirement
from cmip_ref_metrics_esmvaltool.metrics.base import ESMValToolMetric
from cmip_ref_metrics_esmvaltool.recipe import dataframe_to_recipe
from cmip_ref_metrics_esmvaltool.types import OutputBundle, Recipe


class ZeroEmissionCommitment(ESMValToolMetric):
"""
Calculate the global mean Zero Emission Commitment (ZEC) temperature.
"""

name = "Zero Emission Commitment"
slug = "esmvaltool-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,
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireFacets("experiment_id", experiments),
RequireContiguousTimerange(group_by=("instance_id",)),
RequireOverlappingTimerange(group_by=("instance_id",)),
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
),
),
)

@staticmethod
def update_recipe(recipe: Recipe, input_files: 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)["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],
}

@staticmethod
def format_result(result_dir: Path) -> OutputBundle:
"""Format the result."""
zec_file = result_dir / "work/zec/zec/zec_50.nc"
zec = xarray.open_dataset(zec_file)

source_id = zec.dataset.values[0].decode("utf-8").strip()
cmec_output = {
"DIMENSIONS": {
"model": {source_id: {}},
"region": {"global": {}},
"metric": {"zec": {}},
"json_structure": [
"model",
"region",
"metric",
],
},
"RESULTS": {
source_id: {"global": {"zec": float(zec.zec.values[0])}},
},
}

return cmec_output
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def as_timerange(group: pd.DataFrame) -> str | None:
-------
A timerange.
"""
# TODO: apply some rounding to avoid problems?
# https://github.com/ESMValGroup/ESMValCore/issues/2048
start_times = group.start_time.dropna()
if start_times.empty:
return None
Expand Down Expand Up @@ -113,12 +115,15 @@ def dataframe_to_recipe(files: pd.DataFrame) -> dict[str, Any]:
return variables


_ESMVALTOOL_VERSION = "2.11.0"
_ESMVALTOOL_VERSION = "2.13.0.dev10+g7883d411e"
_ESMVALTOOL_COMMIT = _ESMVALTOOL_VERSION.split("+")[1][1:]

_RECIPES = pooch.create(
path=pooch.os_cache("cmip_ref_metrics_esmvaltool"),
base_url="https://raw.githubusercontent.com/ESMValGroup/ESMValTool/refs/tags/v{version}/esmvaltool/recipes/",
version=_ESMVALTOOL_VERSION,
# TODO: use a released version
# base_url="https://raw.githubusercontent.com/ESMValGroup/ESMValTool/refs/tags/v{version}/esmvaltool/recipes/",
# version=_ESMVALTOOL_VERSION,
base_url=f"https://raw.githubusercontent.com/ESMValGroup/ESMValTool/{_ESMVALTOOL_COMMIT}/esmvaltool/recipes/",
env="REF_METRICS_ESMVALTOOL_DATA_DIR",
)
_RECIPES.load_registry(importlib.resources.open_binary("cmip_ref_metrics_esmvaltool", "recipes.txt"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
examples/recipe_python.yml ab3f06d269bb2c1368f4dc39da9bcb232fb2adb1fa556ba769e6c16294ffb4a3
recipe_ecs.yml 0cc57034fcb64e32015b4ff949ece5df8cdb8c6f493618b50ceded119fb37918
recipe_tcr.yml 35f9ef035a4e71aff5cac5dd26c49da2162fc00291bf3b0bd16b661b7b2f606b
recipe_zec.yml b0af7f789b7610ab3f29a6617124aa40c40866ead958204fc199eaf82863de51
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
{
"start_time":{
"215":"0168-01-16T12:00:00.000",
"118":"0101-01-16T12:00:00.000",
"216":null,
"119":null
},
"end_time":{
"215":"0268-12-16T12:00:00.000",
"118":"0250-12-16T12:00:00.000",
"216":null,
"119":null
},
"path":{
"215":"\/home\/bandela\/climate_data\/CMIP6\/C4MIP\/CSIRO\/ACCESS-ESM1-5\/esm-1pct-brch-1000PgC\/r1i1p1f1\/Amon\/tas\/gn\/v20191206\/tas_Amon_ACCESS-ESM1-5_esm-1pct-brch-1000PgC_r1i1p1f1_gn_016801-026812.nc",
"118":"\/home\/bandela\/climate_data\/CMIP6\/CMIP\/CSIRO\/ACCESS-ESM1-5\/1pctCO2\/r1i1p1f1\/Amon\/tas\/gn\/v20191115\/tas_Amon_ACCESS-ESM1-5_1pctCO2_r1i1p1f1_gn_010101-025012.nc",
"216":"\/home\/bandela\/climate_data\/CMIP6\/C4MIP\/CSIRO\/ACCESS-ESM1-5\/esm-1pct-brch-1000PgC\/r1i1p1f1\/fx\/areacella\/gn\/v20191206\/areacella_fx_ACCESS-ESM1-5_esm-1pct-brch-1000PgC_r1i1p1f1_gn.nc",
"119":"\/home\/bandela\/climate_data\/CMIP6\/CMIP\/CSIRO\/ACCESS-ESM1-5\/1pctCO2\/r1i1p1f1\/fx\/areacella\/gn\/v20191115\/areacella_fx_ACCESS-ESM1-5_1pctCO2_r1i1p1f1_gn.nc"
},
"activity_id":{
"215":"C4MIP CDRMIP",
"118":"CMIP",
"216":"C4MIP CDRMIP",
"119":"CMIP"
},
"branch_method":{
"215":"standard",
"118":"standard",
"216":"standard",
"119":"standard"
},
"branch_time_in_child":{
"215":24471.0,
"118":0.0,
"216":24471.0,
"119":0.0
},
"branch_time_in_parent":{
"215":24471.0,
"118":0.0,
"216":24471.0,
"119":0.0
},
"experiment":{
"215":"zero emissions simulation branched from 1% run after 1000 PgC cumulative emission",
"118":"1 percent per year increase in CO2",
"216":"zero emissions simulation branched from 1% run after 1000 PgC cumulative emission",
"119":"1 percent per year increase in CO2"
},
"experiment_id":{
"215":"esm-1pct-brch-1000PgC",
"118":"1pctCO2",
"216":"esm-1pct-brch-1000PgC",
"119":"1pctCO2"
},
"frequency":{
"215":"mon",
"118":"mon",
"216":"fx",
"119":"fx"
},
"grid":{
"215":"native atmosphere N96 grid (145x192 latxlon)",
"118":"native atmosphere N96 grid (145x192 latxlon)",
"216":"native atmosphere N96 grid (145x192 latxlon)",
"119":"native atmosphere N96 grid (145x192 latxlon)"
},
"grid_label":{
"215":"gn",
"118":"gn",
"216":"gn",
"119":"gn"
},
"institution_id":{
"215":"CSIRO",
"118":"CSIRO",
"216":"CSIRO",
"119":"CSIRO"
},
"nominal_resolution":{
"215":"250 km",
"118":"250 km",
"216":"250 km",
"119":"250 km"
},
"parent_activity_id":{
"215":"CMIP",
"118":"CMIP",
"216":"CMIP",
"119":"CMIP"
},
"parent_experiment_id":{
"215":"1pctCO2",
"118":"piControl",
"216":"1pctCO2",
"119":"piControl"
},
"parent_source_id":{
"215":"ACCESS-ESM1-5",
"118":"ACCESS-ESM1-5",
"216":"ACCESS-ESM1-5",
"119":"ACCESS-ESM1-5"
},
"parent_time_units":{
"215":"days since 0101-01-01",
"118":"days since 0101-01-01",
"216":"days since 0101-01-01",
"119":"days since 0101-01-01"
},
"parent_variant_label":{
"215":"r1i1p1f1",
"118":"r1i1p1f1",
"216":"r1i1p1f1",
"119":"r1i1p1f1"
},
"product":{
"215":"model-output",
"118":"model-output",
"216":"model-output",
"119":"model-output"
},
"realm":{
"215":"atmos",
"118":"atmos",
"216":"atmos",
"119":"atmos"
},
"source_id":{
"215":"ACCESS-ESM1-5",
"118":"ACCESS-ESM1-5",
"216":"ACCESS-ESM1-5",
"119":"ACCESS-ESM1-5"
},
"source_type":{
"215":"AOGCM BGC",
"118":"AOGCM",
"216":"AOGCM BGC",
"119":"AOGCM"
},
"sub_experiment":{
"215":"none",
"118":"none",
"216":"none",
"119":"none"
},
"sub_experiment_id":{
"215":"none",
"118":"none",
"216":"none",
"119":"none"
},
"table_id":{
"215":"Amon",
"118":"Amon",
"216":"fx",
"119":"fx"
},
"variable_id":{
"215":"tas",
"118":"tas",
"216":"areacella",
"119":"areacella"
},
"variant_label":{
"215":"r1i1p1f1",
"118":"r1i1p1f1",
"216":"r1i1p1f1",
"119":"r1i1p1f1"
},
"member_id":{
"215":"r1i1p1f1",
"118":"r1i1p1f1",
"216":"r1i1p1f1",
"119":"r1i1p1f1"
},
"standard_name":{
"215":"air_temperature",
"118":"air_temperature",
"216":"cell_area",
"119":"cell_area"
},
"long_name":{
"215":"Near-Surface Air Temperature",
"118":"Near-Surface Air Temperature",
"216":"Grid-Cell Area for Atmospheric Grid Variables",
"119":"Grid-Cell Area for Atmospheric Grid Variables"
},
"units":{
"215":"K",
"118":"K",
"216":"m2",
"119":"m2"
},
"vertical_levels":{
"215":1,
"118":1,
"216":1,
"119":1
},
"init_year":{
"215":null,
"118":null,
"216":null,
"119":null
},
"version":{
"215":"v20191206",
"118":"v20191115",
"216":"v20191206",
"119":"v20191115"
},
"instance_id":{
"215":"CMIP6.C4MIP CDRMIP.CSIRO.ACCESS-ESM1-5.esm-1pct-brch-1000PgC.r1i1p1f1.Amon.tas.gn.v20191206",
"118":"CMIP6.CMIP.CSIRO.ACCESS-ESM1-5.1pctCO2.r1i1p1f1.Amon.tas.gn.v20191115",
"216":"CMIP6.C4MIP CDRMIP.CSIRO.ACCESS-ESM1-5.esm-1pct-brch-1000PgC.r1i1p1f1.fx.areacella.gn.v20191206",
"119":"CMIP6.CMIP.CSIRO.ACCESS-ESM1-5.1pctCO2.r1i1p1f1.fx.areacella.gn.v20191115"
}
}
Loading