From bc3e87f5e63635c9cdc457f54c3fe135883a2987 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 15:15:10 +0200 Subject: [PATCH 01/13] Update ESMValTool commit hash and recipe --- .../climate_ref_esmvaltool/diagnostics/tcr.py | 47 ++++++------------- .../src/climate_ref_esmvaltool/recipe.py | 2 +- .../src/climate_ref_esmvaltool/recipes.txt | 2 +- 3 files changed, 16 insertions(+), 35 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py index a7bd3e3e8..22e678886 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py @@ -7,7 +7,6 @@ AddParentDataset, AddSupplementaryDataset, RequireContiguousTimerange, - RequireFacets, ) from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType from climate_ref_core.diagnostics import DataRequirement @@ -32,7 +31,7 @@ class TransientClimateResponse(ESMValToolDiagnostic): name = "Transient Climate Response" slug = "transient-climate-response" - base_recipe = "recipe_tcr.yml" + base_recipe = "ref/recipe_ref_tcr.yml" experiments = ( "1pctCO2", @@ -67,7 +66,7 @@ class TransientClimateResponse(ESMValToolDiagnostic): FacetFilter( facets={ "branded_variable": "tas_tavg-h2m-hxy-u", - "experiment_id": experiments, + "experiment_id": "1pctCO2", "frequency": "mon", "region": "glb", }, @@ -75,8 +74,8 @@ class TransientClimateResponse(ESMValToolDiagnostic): ), group_by=("source_id", "variant_label", "grid_label"), constraints=( + AddParentDataset.from_defaults(SourceDatasetType.CMIP7), RequireContiguousTimerange(group_by=("instance_id",)), - RequireFacets("experiment_id", experiments), AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP7), ), ), @@ -156,27 +155,8 @@ def update_recipe( input_files: dict[SourceDatasetType, pandas.DataFrame], ) -> None: """Update the recipe.""" - # Only run the diagnostic that computes TCR for a single model. - recipe["diagnostics"] = { - "tcr": { - "description": "Calculate TCR.", - "variables": { - "tas": { - "preprocessor": "spatial_mean", - }, - }, - "scripts": { - "calculate": { - "script": "climate_metrics/tcr.py", - "calculate_mmm": False, - }, - }, - }, - } - - # Prepare updated datasets section in recipe. It contains two - # datasets, one for the "1pctCO2" and one for the "piControl" - # experiment. + # Prepare updated datasets section in recipe. It contains two datasets, + # one for the "1pctCO2" and one for the "piControl" experiment. cmip_source = get_cmip_source_type(input_files) df = input_files[cmip_source] recipe["datasets"] = get_child_and_parent_dataset( @@ -187,14 +167,15 @@ def update_recipe( parent_duration_in_years=140, ) - # Remove keys from the recipe that are only used for YAML anchors - keys_to_remove = [ - "TCR", - "SCATTERPLOT", - "VAR_SETTING", - ] - for key in keys_to_remove: - recipe.pop(key, None) + # Delete branding suffixes from dataset entries because they are + # variable-specific + for dataset in recipe["datasets"]: + dataset.pop("branding_suffix", None) + + # For CMIP6, delete all appearances of branding suffixes + if cmip_source == SourceDatasetType.CMIP6: + for variable in recipe["diagnostics"]["tcr"]["variables"].values(): + variable.pop("branding_suffix", None) @staticmethod def format_result( diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py index 9a03162c3..2e09370ff 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py @@ -296,7 +296,7 @@ def get_child_and_parent_dataset( return [child_dataset, parent_dataset] -_ESMVALTOOL_COMMIT = "dead90ca848d3892ed90785b3940909d58d27780" +_ESMVALTOOL_COMMIT = "26d114a716e113b43a77b2663595edc60f08f173" _ESMVALTOOL_VERSION = f"2.14.0.dev65+g{_ESMVALTOOL_COMMIT[:9]}" _ESMVALTOOL_URL = f"git+https://github.com/ESMValGroup/ESMValTool.git@{_ESMVALTOOL_COMMIT}" diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt index 54ac7b692..c65ef2beb 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt @@ -3,7 +3,6 @@ recipe_calculate_gwl_exceedance_stats.yml 9f28304b85f7043fb76eb29ee84da46e0849 recipe_ecs.yml 0cc57034fcb64e32015b4ff949ece5df8cdb8c6f493618b50ceded119fb37918 recipe_seaice_sensitivity.yml 07270818ebf04a58713dc989720cc9ace77f28d42b1ea189c3bdaf22f5d64577 recipe_tcr.yml 35f9ef035a4e71aff5cac5dd26c49da2162fc00291bf3b0bd16b661b7b2f606b -recipe_tcre.yml 48fc9e3baf541bbcef7491853ea3a774053771dca33352b41466425faeaa38af recipe_zec.yml b0af7f789b7610ab3f29a6617124aa40c40866ead958204fc199eaf82863de51 ref/recipe_enso_basicclimatology.yml 9ea7deb7ee668e39ac44618b96496d898bd82285c22dcee4fce4695e0c9fa82b ref/recipe_enso_characteristics.yml 34c2518b138068ac96d212910b979d54a8fcedee2c0089b5acd56a42c41dc3e4 @@ -13,5 +12,6 @@ ref/recipe_ref_fire.yml 2ad82effaca4e742d8abe6a0aa07bb46e1e9 ref/recipe_ref_ozone.yml 388aaf01721c0856ab7143b47b9d2f1efeaaae4ef57e11572c1e133b49aad0a6 ref/recipe_ref_sea_ice_area_basic.yml 7d01a8527880663ca28284772f83a8356d9972fb4f022a4000e50a56ce044b09 ref/recipe_ref_scatterplot.yml b99d1736e16256d161847b025811d7088ad9f892d4887fb009fa99c4079135a0 +ref/recipe_ref_tcre.yml 13ae406bbb96fa31e137f62fa44e455927902b9e50765da56a247cd82e4cbe5a ref/recipe_ref_timeseries_region.yml deee4403ea25867401e163f6c9d7fcc4fee09d3088009007fcad6a29d01247a8 ref/recipe_ref_trend_regions.yml 18fe246a51474bd12172ab1ba141efac999a247de7774822f77ae6ef144645fe From db3185c36ad133a469cca14600b6f03bdfcfae7d Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 15:15:40 +0200 Subject: [PATCH 02/13] Revert tcr.py --- .../climate_ref_esmvaltool/diagnostics/tcr.py | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py index 22e678886..a7bd3e3e8 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcr.py @@ -7,6 +7,7 @@ AddParentDataset, AddSupplementaryDataset, RequireContiguousTimerange, + RequireFacets, ) from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType from climate_ref_core.diagnostics import DataRequirement @@ -31,7 +32,7 @@ class TransientClimateResponse(ESMValToolDiagnostic): name = "Transient Climate Response" slug = "transient-climate-response" - base_recipe = "ref/recipe_ref_tcr.yml" + base_recipe = "recipe_tcr.yml" experiments = ( "1pctCO2", @@ -66,7 +67,7 @@ class TransientClimateResponse(ESMValToolDiagnostic): FacetFilter( facets={ "branded_variable": "tas_tavg-h2m-hxy-u", - "experiment_id": "1pctCO2", + "experiment_id": experiments, "frequency": "mon", "region": "glb", }, @@ -74,8 +75,8 @@ class TransientClimateResponse(ESMValToolDiagnostic): ), group_by=("source_id", "variant_label", "grid_label"), constraints=( - AddParentDataset.from_defaults(SourceDatasetType.CMIP7), RequireContiguousTimerange(group_by=("instance_id",)), + RequireFacets("experiment_id", experiments), AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP7), ), ), @@ -155,8 +156,27 @@ def update_recipe( input_files: dict[SourceDatasetType, pandas.DataFrame], ) -> None: """Update the recipe.""" - # Prepare updated datasets section in recipe. It contains two datasets, - # one for the "1pctCO2" and one for the "piControl" experiment. + # Only run the diagnostic that computes TCR for a single model. + recipe["diagnostics"] = { + "tcr": { + "description": "Calculate TCR.", + "variables": { + "tas": { + "preprocessor": "spatial_mean", + }, + }, + "scripts": { + "calculate": { + "script": "climate_metrics/tcr.py", + "calculate_mmm": False, + }, + }, + }, + } + + # Prepare updated datasets section in recipe. It contains two + # datasets, one for the "1pctCO2" and one for the "piControl" + # experiment. cmip_source = get_cmip_source_type(input_files) df = input_files[cmip_source] recipe["datasets"] = get_child_and_parent_dataset( @@ -167,15 +187,14 @@ def update_recipe( parent_duration_in_years=140, ) - # Delete branding suffixes from dataset entries because they are - # variable-specific - for dataset in recipe["datasets"]: - dataset.pop("branding_suffix", None) - - # For CMIP6, delete all appearances of branding suffixes - if cmip_source == SourceDatasetType.CMIP6: - for variable in recipe["diagnostics"]["tcr"]["variables"].values(): - variable.pop("branding_suffix", None) + # Remove keys from the recipe that are only used for YAML anchors + keys_to_remove = [ + "TCR", + "SCATTERPLOT", + "VAR_SETTING", + ] + for key in keys_to_remove: + recipe.pop(key, None) @staticmethod def format_result( From ea75fa59c18f62c21ca01f83f8218e5872931931 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 15:16:00 +0200 Subject: [PATCH 03/13] Update recipe in TCRE diagnostic --- .../src/climate_ref_esmvaltool/diagnostics/tcre.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index dfff19d2d..c5f8cf961 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -32,7 +32,7 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): name = "Transient Climate Response to Cumulative CO2 Emissions" slug = "transient-climate-response-emissions" - base_recipe = "recipe_tcre.yml" + base_recipe = "ref/recipe_ref_tcre.yml" variables = ( "tas", From f6b8e7f04bedef04d1e69e2b462e91ba7283b09b Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 16:29:35 +0200 Subject: [PATCH 04/13] Use latest ESMValTool main commit --- .../climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py index 2e09370ff..3336bd95f 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py @@ -296,7 +296,7 @@ def get_child_and_parent_dataset( return [child_dataset, parent_dataset] -_ESMVALTOOL_COMMIT = "26d114a716e113b43a77b2663595edc60f08f173" +_ESMVALTOOL_COMMIT = "0a9a986bd598f6d9334d8f480e03d57e456c3bb4" _ESMVALTOOL_VERSION = f"2.14.0.dev65+g{_ESMVALTOOL_COMMIT[:9]}" _ESMVALTOOL_URL = f"git+https://github.com/ESMValGroup/ESMValTool.git@{_ESMVALTOOL_COMMIT}" From 2824c87026dae02aedb8fed2c23dc321ec49e33e Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 16:48:20 +0200 Subject: [PATCH 05/13] Update ozone recipe hash --- .../src/climate_ref_esmvaltool/recipes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt index c65ef2beb..11342a8c6 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt @@ -9,7 +9,7 @@ ref/recipe_enso_characteristics.yml 34c2518b138068ac96d212910b979d54a8fc ref/recipe_ref_annual_cycle_region.yml 88e0c2f07a76c4de4276547badcc74091516e03840eddb1f0e62469c67a0a86d ref/recipe_ref_cre.yml 4375f262479c3b3e1b348b71080a6d758e195bda76516a591182045a3a29aa32 ref/recipe_ref_fire.yml 2ad82effaca4e742d8abe6a0aa07bb46e1e92ef0d2d240760f7623b0ba045926 -ref/recipe_ref_ozone.yml 388aaf01721c0856ab7143b47b9d2f1efeaaae4ef57e11572c1e133b49aad0a6 +ref/recipe_ref_ozone.yml 09ded4946ecd762ba000916c9f8618120a2e6269930427ae5129da466165f3e5. ref/recipe_ref_sea_ice_area_basic.yml 7d01a8527880663ca28284772f83a8356d9972fb4f022a4000e50a56ce044b09 ref/recipe_ref_scatterplot.yml b99d1736e16256d161847b025811d7088ad9f892d4887fb009fa99c4079135a0 ref/recipe_ref_tcre.yml 13ae406bbb96fa31e137f62fa44e455927902b9e50765da56a247cd82e4cbe5a From 620ee1ce7a07a7d568953541e43aff488cb897c1 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 16:48:49 +0200 Subject: [PATCH 06/13] Use esm-flat10 experiment to calculate TCRE for CMIP7 models --- .../diagnostics/tcre.py | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index c5f8cf961..71d40f501 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -84,7 +84,7 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): "fco2antt_tavg-u-hxy-u", "tas_tavg-h2m-hxy-u", ), - "experiment_id": "esm-1pctCO2", + "experiment_id": "esm-flat10", "frequency": "mon", "region": "glb", }, @@ -101,7 +101,7 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): group_by=("source_id", "variant_label", "grid_label"), constraints=( RequireContiguousTimerange(group_by=("instance_id",)), - RequireFacets("experiment_id", ("esm-1pctCO2", "esm-piControl")), + RequireFacets("experiment_id", ("esm-flat10", "esm-piControl")), RequireFacets("variable_id", variables), AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP7), ), @@ -147,7 +147,7 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): CMIP7Request( slug="cmip7", facets={ - "experiment_id": ["esm-1pctCO2", "esm-piControl"], + "experiment_id": ["esm-flat10", "esm-piControl"], "source_id": "MPI-ESM1-2-LR", "variable_id": ["areacella", "fco2antt", "tas"], "branded_variable": [ @@ -173,31 +173,35 @@ def update_recipe( ) -> 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. + # datasets, "tas" and "fco2antt" for a scenario with steady CO2 + # increase (i.e., "esm-flat10" for CMIP7 and "esm-1pctCO2" for CMIP6) + # and just "tas" for the "esm-piControl" experiment. cmip_source = get_cmip_source_type(input_files) df = input_files[cmip_source] - tas_esm_1pctCO2, tas_esm_piControl = get_child_and_parent_dataset( + if cmip_source == SourceDatasetType.CMIP6: + exp_duration_in_years = 65 + else: + exp_duration_in_years = 110 + tas_co2_increase, tas_esm_piControl = get_child_and_parent_dataset( df[df.variable_id == "tas"], parent_experiment="esm-piControl", - child_duration_in_years=65, + child_duration_in_years=exp_duration_in_years, parent_offset_in_years=0, - parent_duration_in_years=65, + parent_duration_in_years=exp_duration_in_years, ) recipe_variables = dataframe_to_recipe(df[df.variable_id == "fco2antt"]) fco2antt_esm_1pctCO2 = next( ds for ds in recipe_variables["fco2antt"]["additional_datasets"] if ds["exp"] == "esm-1pctCO2" ) - fco2antt_esm_1pctCO2["timerange"] = tas_esm_1pctCO2["timerange"] + fco2antt_esm_1pctCO2["timerange"] = tas_co2_increase["timerange"] recipe["diagnostics"]["tcre"]["variables"] = { - "tas_esm-1pctCO2": { - "short_name": "tas", + "tas": { "preprocessor": "global_annual_mean_anomaly", - "additional_datasets": [tas_esm_1pctCO2], + "additional_datasets": [tas_co2_increase], }, - "tas_esm-piControl": { + "tas_control": { "short_name": "tas", "preprocessor": "global_annual_mean_anomaly", "additional_datasets": [tas_esm_piControl], @@ -207,18 +211,13 @@ def update_recipe( "additional_datasets": [fco2antt_esm_1pctCO2], }, } - recipe["diagnostics"].pop("barplot") - # Update descriptions. - dataset = tas_esm_1pctCO2["dataset"] - ensemble = tas_esm_1pctCO2["ensemble"] - settings = recipe["diagnostics"]["tcre"]["scripts"]["calculate_tcre"] - settings["caption"] = ( - settings["caption"].replace("MPI-ESM1-2-LR", dataset).replace("r1i1p1f1", ensemble) - ) - settings["pyplot_kwargs"]["title"] = ( - settings["pyplot_kwargs"]["title"].replace("MPI-ESM1-2-LR", dataset).replace("r1i1p1f1", ensemble) - ) + # For CMIP6, some special settings are necessary because the esm-flat10 + # experiment did not experiment yet + if cmip_source == SourceDatasetType.CMIP6: + diag_settings = recipe["diagnostics"]["tcre"]["scripts"]["calculate_tcre"] + diag_settings["calc_tcre_period"] = [45, 65] + diag_settings["exp_target"] = "esm-1pctCO2" @staticmethod def format_result( From f0e9c2add5445e70c4b37a22a93d7cd17af31b82 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Fri, 29 May 2026 16:52:59 +0200 Subject: [PATCH 07/13] Fixed typo in recipes.txt --- .../src/climate_ref_esmvaltool/recipes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt index 11342a8c6..a32a83a33 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt @@ -9,7 +9,7 @@ ref/recipe_enso_characteristics.yml 34c2518b138068ac96d212910b979d54a8fc ref/recipe_ref_annual_cycle_region.yml 88e0c2f07a76c4de4276547badcc74091516e03840eddb1f0e62469c67a0a86d ref/recipe_ref_cre.yml 4375f262479c3b3e1b348b71080a6d758e195bda76516a591182045a3a29aa32 ref/recipe_ref_fire.yml 2ad82effaca4e742d8abe6a0aa07bb46e1e92ef0d2d240760f7623b0ba045926 -ref/recipe_ref_ozone.yml 09ded4946ecd762ba000916c9f8618120a2e6269930427ae5129da466165f3e5. +ref/recipe_ref_ozone.yml 09ded4946ecd762ba000916c9f8618120a2e6269930427ae5129da466165f3e5 ref/recipe_ref_sea_ice_area_basic.yml 7d01a8527880663ca28284772f83a8356d9972fb4f022a4000e50a56ce044b09 ref/recipe_ref_scatterplot.yml b99d1736e16256d161847b025811d7088ad9f892d4887fb009fa99c4079135a0 ref/recipe_ref_tcre.yml 13ae406bbb96fa31e137f62fa44e455927902b9e50765da56a247cd82e4cbe5a From 8c01419f3e5bde56aef5419d87596d2f483e6d3e Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Mon, 1 Jun 2026 10:31:22 +0200 Subject: [PATCH 08/13] Adapt TCRE caption for CMIP6 and update expected test recipe --- .../diagnostics/tcre.py | 8 ++++ ...sient_climate_response_emissions_cmip6.yml | 44 +++++-------------- 2 files changed, 19 insertions(+), 33 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index 71d40f501..f725f9a6e 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -217,6 +217,14 @@ def update_recipe( if cmip_source == SourceDatasetType.CMIP6: diag_settings = recipe["diagnostics"]["tcre"]["scripts"]["calculate_tcre"] diag_settings["calc_tcre_period"] = [45, 65] + diag_settings["caption"] = ( + "Global annual mean near-surface air temperature anomaly ΔT vs. " + "global annual cumulative CO2 emissions E of the emission-driven " + "1% CO2 increase per year experiment. The transient climate " + "response to cumulative CO2 Emissions (TCRE) is defined as the " + "20-year average ΔT centered at the time where cumulative CO2 " + "emissions E reach 1000 PgC (i.e., after 55 years)." + ) diag_settings["exp_target"] = "esm-1pctCO2" @staticmethod diff --git a/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml b/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml index f9017c0ad..dc5c68541 100644 --- a/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml +++ b/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml @@ -11,25 +11,6 @@ documentation: - schlund_manuel references: - sanderson24gmd - domains: - - global - realms: - - atmos - themes: - - carbon - - bgphys -datasets_target_exp: -- project: CMIP6 - dataset: MPI-ESM1-2-LR - ensemble: r1i1p1f1 - grid: gn - timerange: 1850/1914 -datasets_control_exp: -- project: CMIP6 - dataset: MPI-ESM1-2-LR - ensemble: r1i1p1f1 - grid: gn - timerange: 1850/1914 preprocessors: global_annual_mean_anomaly: custom_order: true @@ -53,8 +34,7 @@ preprocessors: diagnostics: tcre: variables: - tas_esm-1pctCO2: - short_name: tas + tas: preprocessor: global_annual_mean_anomaly additional_datasets: - project: CMIP6 @@ -66,7 +46,7 @@ diagnostics: grid: gn mip: Amon timerange: 1850/1914 - tas_esm-piControl: + tas_control: short_name: tas preprocessor: global_annual_mean_anomaly additional_datasets: @@ -94,18 +74,16 @@ diagnostics: scripts: calculate_tcre: script: climate_metrics/tcre.py - calc_tcre_period: - - 45 - - 65 caption: "Global annual mean near-surface air temperature anomaly \u0394T\ - \ vs.\nglobal annual cumulative CO2 emissions E of the emission-driven 1%\n\ - CO2 increase per year experiment for model MPI-ESM1-2-LR (ensemble\nmember\ - \ r1i1p1f1). The transient climate response to cumulative CO2\nEmissions\ - \ (TCRE) is defined as the 20-year average \u0394T centered at\nthe time\ - \ where cumulative CO2 emissions E reach 1000 PgC.\n" - exp_target: esm-1pctCO2 - legend_kwargs: false + \ vs. global annual cumulative CO2 emissions E of the emission-driven 1%\ + \ CO2 increase per year experiment. The transient climate response to cumulative\ + \ CO2 Emissions (TCRE) is defined as the 20-year average \u0394T centered\ + \ at the time where cumulative CO2 emissions E reach 1000 PgC (i.e., after\ + \ 55 years)." pyplot_kwargs: - title: MPI-ESM1-2-LR (ensemble member r1i1p1f1) xlabel: E [PgC] ylabel: "\u0394T [K]" + calc_tcre_period: + - 45 + - 65 + exp_target: esm-1pctCO2 From 67332c69943c17c6f03e10f3c1d4191919cf5739 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Mon, 1 Jun 2026 11:52:01 +0200 Subject: [PATCH 09/13] Add correct parent datasets for CMIP7 data in TCRE diagnostic --- .../diagnostics/tcre.py | 29 ++++++++++--------- ..._transient_climate_response_emissions_.yml | 6 ---- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index f725f9a6e..ada20de41 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -80,29 +80,32 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): filters=( FacetFilter( facets={ - "branded_variable": ( - "fco2antt_tavg-u-hxy-u", - "tas_tavg-h2m-hxy-u", - ), + "branded_variable": "tas_tavg-h2m-hxy-u", "experiment_id": "esm-flat10", "frequency": "mon", "region": "glb", }, ), - FacetFilter( - facets={ - "branded_variable": "tas_tavg-h2m-hxy-u", - "experiment_id": "esm-piControl", + ), + group_by=("source_id", "variant_label", "grid_label"), + constraints=( + AddParentDataset.from_defaults(SourceDatasetType.CMIP7), + AddSupplementaryDataset( + supplementary_facets={ + "branded_variable": "fco2antt_tavg-u-hxy-u", + "experiment_id": "esm-flat10", "frequency": "mon", "region": "glb", }, + matching_facets=( + "source_id", + "variant_label", + "grid_label", + ), + optional_matching_facets=("version",), ), - ), - group_by=("source_id", "variant_label", "grid_label"), - constraints=( RequireContiguousTimerange(group_by=("instance_id",)), - RequireFacets("experiment_id", ("esm-flat10", "esm-piControl")), - RequireFacets("variable_id", variables), + RequireFacets("variable_id", ("tas", "fco2antt")), AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP7), ), ), diff --git a/packages/climate-ref-esmvaltool/tests/unit/test_solve_regression/test_solve_regression_transient_climate_response_emissions_.yml b/packages/climate-ref-esmvaltool/tests/unit/test_solve_regression/test_solve_regression_transient_climate_response_emissions_.yml index f27cb98a1..bb79809a0 100644 --- a/packages/climate-ref-esmvaltool/tests/unit/test_solve_regression/test_solve_regression_transient_climate_response_emissions_.yml +++ b/packages/climate-ref-esmvaltool/tests/unit/test_solve_regression/test_solve_regression_transient_climate_response_emissions_.yml @@ -4,9 +4,3 @@ cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR: - CMIP6.C4MIP CDRMIP.MPI-M.MPI-ESM1-2-LR.esm-1pctCO2.r1i1p1f1.Amon.tas.gn.v20190815 - CMIP6.CMIP.MPI-M.MPI-ESM1-2-LR.1pctCO2.r1i1p1f1.fx.areacella.gn.v20190710 - CMIP6.CMIP.MPI-M.MPI-ESM1-2-LR.esm-piControl.r1i1p1f1.Amon.tas.gn.v20190815 -cmip7_gn_MPI-ESM1-2-LR_r1i1p1f1: - cmip7: - - CMIP7.C4MIP CDRMIP.MPI-M.MPI-ESM1-2-LR.esm-1pctCO2.r1i1p1f1.glb.mon.fco2antt.tavg-u-hxy-u.gn.v20190815 - - CMIP7.C4MIP CDRMIP.MPI-M.MPI-ESM1-2-LR.esm-1pctCO2.r1i1p1f1.glb.mon.tas.tavg-h2m-hxy-u.gn.v20190815 - - CMIP7.CMIP.MPI-M.MPI-ESM1-2-LR.1pctCO2.r1i1p1f1.glb.fx.areacella.ti-u-hxy-u.gn.v20190710 - - CMIP7.CMIP.MPI-M.MPI-ESM1-2-LR.esm-piControl.r1i1p1f1.glb.mon.tas.tavg-h2m-hxy-u.gn.v20190815 From c7ebc587dae149e9ef1de9db445c67656fcf74b8 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Mon, 1 Jun 2026 15:08:49 +0200 Subject: [PATCH 10/13] Use latest ESMValTool commit to main --- .../src/climate_ref_esmvaltool/diagnostics/tcre.py | 8 ++++---- .../src/climate_ref_esmvaltool/recipe.py | 2 +- .../src/climate_ref_esmvaltool/recipes.txt | 2 +- .../recipe_transient_climate_response_emissions_cmip6.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index ada20de41..4a864a593 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -116,11 +116,11 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): series = tuple() files = ( FileDefinition( - file_pattern="plots/tcre/calculate_tcre/*.png", + file_pattern="plots/tcre/calculate/*.png", dimensions={"statistic": "tcre"}, ), FileDefinition( - file_pattern="work/tcre/calculate_tcre/tcre.nc", + file_pattern="work/tcre/calculate/tcre.nc", dimensions={"metric": "tcre"}, ), ) @@ -218,7 +218,7 @@ def update_recipe( # For CMIP6, some special settings are necessary because the esm-flat10 # experiment did not experiment yet if cmip_source == SourceDatasetType.CMIP6: - diag_settings = recipe["diagnostics"]["tcre"]["scripts"]["calculate_tcre"] + diag_settings = recipe["diagnostics"]["tcre"]["scripts"]["calculate"] diag_settings["calc_tcre_period"] = [45, 65] diag_settings["caption"] = ( "Global annual mean near-surface air temperature anomaly ΔT vs. " @@ -238,7 +238,7 @@ def format_result( output_args: OutputBundleArgs, ) -> tuple[CMECMetric, CMECOutput]: """Format the result.""" - tcre_ds = xarray.open_dataset(result_dir / "work" / "tcre" / "calculate_tcre" / "tcre.nc") + tcre_ds = xarray.open_dataset(result_dir / "work" / "tcre" / "calculate" / "tcre.nc") tcre = float(fillvalues_to_nan(tcre_ds["tcre"].values)[0]) # Update the diagnostic bundle arguments with the computed diagnostics. diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py index 3336bd95f..2b5bb3af6 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipe.py @@ -296,7 +296,7 @@ def get_child_and_parent_dataset( return [child_dataset, parent_dataset] -_ESMVALTOOL_COMMIT = "0a9a986bd598f6d9334d8f480e03d57e456c3bb4" +_ESMVALTOOL_COMMIT = "12cb5309bd64ca4189bc0ef63bcf25e82664e45f" _ESMVALTOOL_VERSION = f"2.14.0.dev65+g{_ESMVALTOOL_COMMIT[:9]}" _ESMVALTOOL_URL = f"git+https://github.com/ESMValGroup/ESMValTool.git@{_ESMVALTOOL_COMMIT}" diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt index a32a83a33..6b666a400 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/recipes.txt @@ -12,6 +12,6 @@ ref/recipe_ref_fire.yml 2ad82effaca4e742d8abe6a0aa07bb46e1e9 ref/recipe_ref_ozone.yml 09ded4946ecd762ba000916c9f8618120a2e6269930427ae5129da466165f3e5 ref/recipe_ref_sea_ice_area_basic.yml 7d01a8527880663ca28284772f83a8356d9972fb4f022a4000e50a56ce044b09 ref/recipe_ref_scatterplot.yml b99d1736e16256d161847b025811d7088ad9f892d4887fb009fa99c4079135a0 -ref/recipe_ref_tcre.yml 13ae406bbb96fa31e137f62fa44e455927902b9e50765da56a247cd82e4cbe5a +ref/recipe_ref_tcre.yml 85bd9ffc42a4eb70dc7e3d984f0f7c1085232ac8dd977d04d58b27a982254ebd ref/recipe_ref_timeseries_region.yml deee4403ea25867401e163f6c9d7fcc4fee09d3088009007fcad6a29d01247a8 ref/recipe_ref_trend_regions.yml 18fe246a51474bd12172ab1ba141efac999a247de7774822f77ae6ef144645fe diff --git a/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml b/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml index dc5c68541..b612ef04d 100644 --- a/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml +++ b/packages/climate-ref-esmvaltool/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions_cmip6.yml @@ -72,7 +72,7 @@ diagnostics: mip: Amon timerange: 1850/1914 scripts: - calculate_tcre: + calculate: script: climate_metrics/tcre.py caption: "Global annual mean near-surface air temperature anomaly \u0394T\ \ vs. global annual cumulative CO2 emissions E of the emission-driven 1%\ From 90fd12b6f05c1da9ae8a685c63618463838f4e04 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Mon, 1 Jun 2026 16:14:11 +0200 Subject: [PATCH 11/13] Add series to TCRE diagnostic --- .../climate_ref_esmvaltool/diagnostics/tcre.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index 4a864a593..7051e82e7 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -12,7 +12,7 @@ from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType from climate_ref_core.diagnostics import DataRequirement from climate_ref_core.esgf import CMIP6Request, CMIP7Request -from climate_ref_core.metric_values.typing import FileDefinition +from climate_ref_core.metric_values.typing import FileDefinition, SeriesDefinition from climate_ref_core.pycmec.metric import CMECMetric, MetricCV from climate_ref_core.pycmec.output import CMECOutput from climate_ref_core.testing import TestCase, TestDataSpecification @@ -112,8 +112,17 @@ class TransientClimateResponseEmissions(ESMValToolDiagnostic): ), ) facets = ("grid_label", "member_id", "variant_label", "source_id", "region", "metric") - # TODO: the ESMValTool diagnostic script does not save the data for the timeseries. - series = tuple() + series = ( + SeriesDefinition( + file_pattern="tcre/calculate/{source_id}.nc", + dimensions={ + "statistic": "global annual mean anomaly of tas vs cumulative fco2antt", + }, + values_name="tas", + index_name="cumulative_fco2antt", + attributes=[], + ), + ) files = ( FileDefinition( file_pattern="plots/tcre/calculate/*.png", From cf5eab9dbb401b23e83fb6e6ee144789e3cabf3d Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Mon, 1 Jun 2026 16:47:42 +0200 Subject: [PATCH 12/13] Fix diagnostic test --- .../work/tcre/{calculate_tcre => calculate}/tcre.nc | Bin .../tcre_citation.bibtex | 0 .../tcre_data_citation_info.txt | 0 .../tcre_provenance.xml | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/{calculate_tcre => calculate}/tcre.nc (100%) rename tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/{calculate_tcre => calculate}/tcre_citation.bibtex (100%) rename tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/{calculate_tcre => calculate}/tcre_data_citation_info.txt (100%) rename tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/{calculate_tcre => calculate}/tcre_provenance.xml (100%) diff --git a/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre.nc b/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre.nc similarity index 100% rename from tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre.nc rename to tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre.nc diff --git a/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre_citation.bibtex b/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre_citation.bibtex similarity index 100% rename from tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre_citation.bibtex rename to tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre_citation.bibtex diff --git a/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre_data_citation_info.txt b/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre_data_citation_info.txt similarity index 100% rename from tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre_data_citation_info.txt rename to tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre_data_citation_info.txt diff --git a/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre_provenance.xml b/tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre_provenance.xml similarity index 100% rename from tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate_tcre/tcre_provenance.xml rename to tests/test-data/regression/esmvaltool/transient-climate-response-emissions/cmip6_gn_r1i1p1f1_MPI-ESM1-2-LR/executions/recipe_20260130_163954/work/tcre/calculate/tcre_provenance.xml From dfc9a84fd1d2aa386259890a92c1fb7ea0a63cf4 Mon Sep 17 00:00:00 2001 From: Manuel Schlund Date: Mon, 1 Jun 2026 16:48:57 +0200 Subject: [PATCH 13/13] Typo --- .../src/climate_ref_esmvaltool/diagnostics/tcre.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py index 7051e82e7..4ff5e5af3 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/tcre.py @@ -225,7 +225,7 @@ def update_recipe( } # For CMIP6, some special settings are necessary because the esm-flat10 - # experiment did not experiment yet + # experiment does not exist if cmip_source == SourceDatasetType.CMIP6: diag_settings = recipe["diagnostics"]["tcre"]["scripts"]["calculate"] diag_settings["calc_tcre_period"] = [45, 65]