Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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/208.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added Transient Climate Response to Cumulative CO2 Emissions (TCRE) 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.tcre import TransientClimateResponseEmissions

__all__ = [
"EquilibriumClimateSensitivity",
"GlobalMeanTimeseries",
"TransientClimateResponse",
"TransientClimateResponseEmissions",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
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 TransientClimateResponseEmissions(ESMValToolMetric):
"""
Calculate the global mean Transient Climate Response to Cumulative CO2 Emissions.
"""

name = "Transient Climate Response to Cumulative CO2 Emissions"
slug = "esmvaltool-transient-climate-response-emissions"
base_recipe = "recipe_tcre.yml"

experiments = (
"esm-1pctCO2",
"esm-piControl",
)
variables = (
"tas",
"fco2antt",
)
data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": variables,
"frequency": "mon",
"experiment_id": experiments,
},
),
FacetFilter(
facets={
"variable_id": "fco2antt",
"experiment_id": "esm-piControl",
},
keep=False,
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireFacets("experiment_id", experiments),
RequireFacets("variable_id", variables),
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 three
# datasets, "tas" and "fco2antt" for the "esm-1pctCO2" and just "tas"
# for the "esm-piControl" experiment.
recipe_variables = dataframe_to_recipe(input_files)
tas_esm_1pctCO2 = next(
ds for ds in recipe_variables["tas"]["additional_datasets"] if ds["exp"] == "esm-1pctCO2"
)
fco2antt_esm_1pctCO2 = next(
ds for ds in recipe_variables["fco2antt"]["additional_datasets"] if ds["exp"] == "esm-1pctCO2"
)
tas_esm_piControl = next(
ds for ds in recipe_variables["tas"]["additional_datasets"] if ds["exp"] == "esm-piControl"
)
tas_esm_piControl["timerange"] = tas_esm_1pctCO2["timerange"]

recipe["diagnostics"]["tcre"]["variables"] = {
"tas_esm-1pctCO2": {
"short_name": "tas",
"preprocessor": "global_annual_mean_anomaly",
"additional_datasets": [tas_esm_1pctCO2],
},
"tas_esm-piControl": {
"short_name": "tas",
"preprocessor": "global_annual_mean_anomaly",
"additional_datasets": [tas_esm_piControl],
},
"fco2antt": {
"preprocessor": "global_cumulative_sum",
"additional_datasets": [fco2antt_esm_1pctCO2],
},
}
recipe["diagnostics"].pop("barplot")

@staticmethod
def format_result(result_dir: Path) -> OutputBundle:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now have concrete types cmip_ref_core.pycmec.output.CMECOutput and cmip_ref_core.pycmec.output.CMECMetric instead of this loose type hint.
The content here is also representative of a metrics bundle, not an output bundle.

The output bundle contains references to plots and datafiles, where as the metric bundle contains the calculated scalars. The output bundle content is not currently implemented for ESMValTool (see packages/ref-metrics-pmp/src/cmip_ref_metrics_pmp/pmp_driver.py for an example of including data and plots in an output bundle).

I'd recommend fixing this up in a follow-up PR as is will impact all of the ESMValTool metrics

"""Format the result."""
tcre_file = result_dir / "work/tcre/calculate_tcre/tcre.nc"
tcre = xarray.open_dataset(tcre_file)

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

return cmec_output
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,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_tcre.yml 4668e357e00c515a8264ac75cb319ce558289689e10189e6f9e982886c414c94
Loading