climate-ref-esmvaltool 0.6.5__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/PKG-INFO +1 -1
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/pyproject.toml +2 -2
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/dataset_registry/data.txt +4 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/__init__.py +22 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/base.py +112 -14
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/climate_at_global_warming_levels.py +41 -15
- climate_ref_esmvaltool-0.7.0/src/climate_ref_esmvaltool/diagnostics/climate_drivers_for_fire.py +90 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/cloud_radiative_effects.py +26 -20
- climate_ref_esmvaltool-0.7.0/src/climate_ref_esmvaltool/diagnostics/cloud_scatterplots.py +200 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/ecs.py +32 -20
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/enso.py +88 -12
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/example.py +17 -3
- climate_ref_esmvaltool-0.7.0/src/climate_ref_esmvaltool/diagnostics/regional_historical_changes.py +435 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/sea_ice_area_basic.py +63 -5
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/sea_ice_sensitivity.py +31 -14
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/tcr.py +23 -19
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/tcre.py +13 -12
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/diagnostics/zec.py +20 -3
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/recipe.py +55 -10
- climate_ref_esmvaltool-0.7.0/src/climate_ref_esmvaltool/recipes.txt +16 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/requirements/conda-lock.yml +4081 -3770
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/requirements/environment.yml +1 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/tests/integration/test_diagnostics.py +16 -1
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_climate_at_global_warming_levels.yml +181 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_climate_drivers_for_fire.yml +76 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_cloud_radiative_effects.yml +126 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_cloud_scatterplots_cli_ta.yml +149 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_cloud_scatterplots_clivi_lwcre.yml +151 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_cloud_scatterplots_clt_swcre.yml +151 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_cloud_scatterplots_clwvi_pr.yml +149 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_cloud_scatterplots_reference.yml +309 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_enso_basic_climatology.yml +308 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_enso_characteristics.yml +196 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_equilibrium_climate_sensitivity.yml +52 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_global_mean_timeseries.yml +65 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_regional_historical_annual_cycle.yml +8127 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_regional_historical_timeseries.yml +16813 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_regional_historical_trend.yml +537 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_sea_ice_area_basic.yml +200 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_sea_ice_sensitivity.yml +214 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_transient_climate_response.yml +48 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_transient_climate_response_emissions.yml +109 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/recipes/recipe_zero_emission_commitment.yml +62 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/test_base.py +173 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/diagnostics/test_recipes.py +39 -0
- climate_ref_esmvaltool-0.6.5/tests/unit/test_metrics.py → climate_ref_esmvaltool-0.7.0/tests/unit/test_diagnostic.py +1 -1
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/tests/unit/test_provider.py +2 -0
- climate_ref_esmvaltool-0.7.0/tests/unit/test_recipe.py +64 -0
- climate_ref_esmvaltool-0.6.5/src/climate_ref_esmvaltool/recipes.txt +0 -11
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_climate_at_global_warming_levels.json +0 -1371
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_cloud_radiative_effects.json +0 -218
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_ecs.json +0 -362
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_enso_characteristics.json +0 -142
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_enso_climatology.json +0 -177
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_sea_ice_area.json +0 -146
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_sea_ice_sensitivity.json +0 -506
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_tcr.json +0 -146
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_tcre.json +0 -496
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/input_files_zec.json +0 -218
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_base.py +0 -80
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_climate_at_global_warming_levels.py +0 -41
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_cloud_radiative_effects.py +0 -27
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_ecs.py +0 -73
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_enso.py +0 -47
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_sea_ice_area.py +0 -16
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_sea_ice_sensitivity.py +0 -46
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_tcr.py +0 -63
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_tcre.py +0 -108
- climate_ref_esmvaltool-0.6.5/tests/unit/diagnostics/test_zec.py +0 -92
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/.gitignore +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/LICENCE +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/NOTICE +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/README.md +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/__init__.py +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/_version.py +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/py.typed +0 -0
- {climate_ref_esmvaltool-0.6.5 → climate_ref_esmvaltool-0.7.0}/src/climate_ref_esmvaltool/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: climate-ref-esmvaltool
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: ESMValTool diagnostic provider for the Rapid Evaluation Framework
|
|
5
5
|
Author-email: ESMValTool development team <esmvaltool-dev@listserv.dfn.de>, Jared Lewis <jared.lewis@climate-resource.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "climate-ref-esmvaltool"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "ESMValTool diagnostic provider for the Rapid Evaluation Framework"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -23,8 +23,8 @@ classifiers = [
|
|
|
23
23
|
"License :: OSI Approved :: Apache Software License",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
"pooch >= 1.8",
|
|
27
26
|
"climate-ref-core",
|
|
27
|
+
"pooch >= 1.8",
|
|
28
28
|
"pyyaml",
|
|
29
29
|
"xarray >= 2023.3.0",
|
|
30
30
|
]
|
|
@@ -73,6 +73,9 @@ ESMValTool/OBS/Tier2/CERES-EBAF/OBS_CERES-EBAF_sat_Ed4.2_Amon_rlut_200003-202311
|
|
|
73
73
|
ESMValTool/OBS/Tier2/CERES-EBAF/OBS_CERES-EBAF_sat_Ed4.2_Amon_rlutcs_200003-202311.nc e70e3273092edf01527970693271641fc6474d1974887d7d272e7d656bab83c2
|
|
74
74
|
ESMValTool/OBS/Tier2/CERES-EBAF/OBS_CERES-EBAF_sat_Ed4.2_Amon_rsut_200003-202311.nc e31e648886c4fa9c09686672a06ab18fbba687ff0d6de2891616d4c8b74e215d
|
|
75
75
|
ESMValTool/OBS/Tier2/CERES-EBAF/OBS_CERES-EBAF_sat_Ed4.2_Amon_rsutcs_200003-202311.nc eb96edd9274670aa705eab2a6d1ee0cca11e01ac17096706463e032b58e6be47
|
|
76
|
+
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_clivi_198201-201612.nc 13bc6e3a46397386a14a36776fdd6bdbf5c45147c8dc695d4a7387883d449775
|
|
77
|
+
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_clt_198201-201612.nc 4a430d77dbe9164dba2d1fdef4bb89ea9358b6d10023f3fbee50917422446ed0
|
|
78
|
+
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_clwvi_198201-201612.nc e0ffa31369d9552be16b920110b24013d31e116b180ee3f70b3d0aaa5281eff0
|
|
76
79
|
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rlut_198201-201612.nc 075144d673a9f2ff49fbe59e701535bf80c04908797a9dca83781000a9b1b7f2
|
|
77
80
|
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rlutcs_198201-201612.nc 21f096ecafff659e5c7e3338060425f7194e5d1b39c9510865496e04ecac3d75
|
|
78
81
|
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rsut_198201-201612.nc f2c3f3afcdc2e730df7985c210a3de89b0d4f83b150e0c3846f7ac3c5fa9c54a
|
|
@@ -156,5 +159,6 @@ ESMValTool/OBS/Tier2/OSI-450-sh/OBS_OSI-450-sh_reanaly_v3_OImon_sic_201101-20111
|
|
|
156
159
|
ESMValTool/OBS/Tier2/OSI-450-sh/OBS_OSI-450-sh_reanaly_v3_OImon_sic_201201-201212.nc 86187c3d1174053f2cba6dad010af49ceab77d368aa9314bf53c330b5f2217b9
|
|
157
160
|
ESMValTool/OBS/Tier2/OSI-450-sh/OBS_OSI-450-sh_reanaly_v3_OImon_sic_201301-201312.nc 8820353570884b2ef182caaffb5986ed6268bbe199fd867f61b56e798ca01f1a
|
|
158
161
|
ESMValTool/OBS/Tier2/OSI-450-sh/OBS_OSI-450-sh_reanaly_v3_OImon_sic_201401-201412.nc 7102d0db3dc02c5b0eb0cfe3535ee50171007ef5b43eb9aae1220ac21b0b98e9
|
|
162
|
+
ESMValTool/OBS/Tier3/CALIPSO-ICECLOUD/OBS_CALIPSO-ICECLOUD_sat_1-00_Amon_cli_200701-201512.nc 977824810e8f9dbe7df278c59397ffc3f78491a9eb5a0b70e6b28ac66db8e12d
|
|
159
163
|
ESMValTool/OBS/Tier2/TROPFLUX/OBS6_TROPFLUX_reanaly_v1_Amon_tauu_197901-201812.nc bf313e661b42341d5090038b501ed1ff09e58201009c3fccfe45b78e116fdd78
|
|
160
164
|
ESMValTool/OBS/Tier2/TROPFLUX/OBS6_TROPFLUX_reanaly_v1_Omon_tos_197901-201812.nc 5f10a5a2aa47f5d21378ad3178bf8e4b577b0ed72ef8402dc04f5ff6fc99ec07
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
"""ESMValTool diagnostics."""
|
|
2
2
|
|
|
3
3
|
from climate_ref_esmvaltool.diagnostics.climate_at_global_warming_levels import ClimateAtGlobalWarmingLevels
|
|
4
|
+
from climate_ref_esmvaltool.diagnostics.climate_drivers_for_fire import ClimateDriversForFire
|
|
4
5
|
from climate_ref_esmvaltool.diagnostics.cloud_radiative_effects import CloudRadiativeEffects
|
|
6
|
+
from climate_ref_esmvaltool.diagnostics.cloud_scatterplots import (
|
|
7
|
+
CloudScatterplotCliTa,
|
|
8
|
+
CloudScatterplotCliviLwcre,
|
|
9
|
+
CloudScatterplotCltSwcre,
|
|
10
|
+
CloudScatterplotClwviPr,
|
|
11
|
+
CloudScatterplotsReference,
|
|
12
|
+
)
|
|
5
13
|
from climate_ref_esmvaltool.diagnostics.ecs import EquilibriumClimateSensitivity
|
|
6
14
|
from climate_ref_esmvaltool.diagnostics.enso import ENSOBasicClimatology, ENSOCharacteristics
|
|
7
15
|
from climate_ref_esmvaltool.diagnostics.example import GlobalMeanTimeseries
|
|
16
|
+
from climate_ref_esmvaltool.diagnostics.regional_historical_changes import (
|
|
17
|
+
RegionalHistoricalAnnualCycle,
|
|
18
|
+
RegionalHistoricalTimeSeries,
|
|
19
|
+
RegionalHistoricalTrend,
|
|
20
|
+
)
|
|
8
21
|
from climate_ref_esmvaltool.diagnostics.sea_ice_area_basic import SeaIceAreaBasic
|
|
9
22
|
from climate_ref_esmvaltool.diagnostics.sea_ice_sensitivity import SeaIceSensitivity
|
|
10
23
|
from climate_ref_esmvaltool.diagnostics.tcr import TransientClimateResponse
|
|
@@ -13,11 +26,20 @@ from climate_ref_esmvaltool.diagnostics.zec import ZeroEmissionCommitment
|
|
|
13
26
|
|
|
14
27
|
__all__ = [
|
|
15
28
|
"ClimateAtGlobalWarmingLevels",
|
|
29
|
+
"ClimateDriversForFire",
|
|
16
30
|
"CloudRadiativeEffects",
|
|
31
|
+
"CloudScatterplotCliTa",
|
|
32
|
+
"CloudScatterplotCliviLwcre",
|
|
33
|
+
"CloudScatterplotCltSwcre",
|
|
34
|
+
"CloudScatterplotClwviPr",
|
|
35
|
+
"CloudScatterplotsReference",
|
|
17
36
|
"ENSOBasicClimatology",
|
|
18
37
|
"ENSOCharacteristics",
|
|
19
38
|
"EquilibriumClimateSensitivity",
|
|
20
39
|
"GlobalMeanTimeseries",
|
|
40
|
+
"RegionalHistoricalAnnualCycle",
|
|
41
|
+
"RegionalHistoricalTimeSeries",
|
|
42
|
+
"RegionalHistoricalTrend",
|
|
21
43
|
"SeaIceAreaBasic",
|
|
22
44
|
"SeaIceSensitivity",
|
|
23
45
|
"TransientClimateResponse",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import fnmatch
|
|
1
2
|
from abc import abstractmethod
|
|
2
3
|
from collections.abc import Iterable
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import ClassVar
|
|
5
6
|
|
|
6
7
|
import pandas
|
|
8
|
+
import xarray as xr
|
|
7
9
|
import yaml
|
|
8
10
|
from loguru import logger
|
|
9
11
|
|
|
@@ -14,6 +16,7 @@ from climate_ref_core.diagnostics import (
|
|
|
14
16
|
ExecutionDefinition,
|
|
15
17
|
ExecutionResult,
|
|
16
18
|
)
|
|
19
|
+
from climate_ref_core.metric_values.typing import SeriesMetricValue
|
|
17
20
|
from climate_ref_core.pycmec.metric import CMECMetric, MetricCV
|
|
18
21
|
from climate_ref_core.pycmec.output import CMECOutput, OutputCV
|
|
19
22
|
from climate_ref_esmvaltool.recipe import load_recipe, prepare_climate_data
|
|
@@ -27,7 +30,10 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
27
30
|
|
|
28
31
|
@staticmethod
|
|
29
32
|
@abstractmethod
|
|
30
|
-
def update_recipe(
|
|
33
|
+
def update_recipe(
|
|
34
|
+
recipe: Recipe,
|
|
35
|
+
input_files: dict[SourceDatasetType, pandas.DataFrame],
|
|
36
|
+
) -> None:
|
|
31
37
|
"""
|
|
32
38
|
Update the base recipe for the run.
|
|
33
39
|
|
|
@@ -67,9 +73,9 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
67
73
|
"""
|
|
68
74
|
return CMECMetric.model_validate(metric_args), CMECOutput.model_validate(output_args)
|
|
69
75
|
|
|
70
|
-
def
|
|
76
|
+
def write_recipe(self, definition: ExecutionDefinition) -> Path:
|
|
71
77
|
"""
|
|
72
|
-
|
|
78
|
+
Update the ESMValTool recipe for the diagnostic and write it to file.
|
|
73
79
|
|
|
74
80
|
Parameters
|
|
75
81
|
----------
|
|
@@ -79,22 +85,43 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
79
85
|
Returns
|
|
80
86
|
-------
|
|
81
87
|
:
|
|
82
|
-
The
|
|
88
|
+
The path to the written recipe.
|
|
83
89
|
"""
|
|
84
|
-
input_files =
|
|
90
|
+
input_files = {
|
|
91
|
+
project: dataset_collection.datasets
|
|
92
|
+
for project, dataset_collection in definition.datasets.items()
|
|
93
|
+
}
|
|
85
94
|
recipe = load_recipe(self.base_recipe)
|
|
86
95
|
self.update_recipe(recipe, input_files)
|
|
87
|
-
|
|
96
|
+
recipe_txt = yaml.safe_dump(recipe, sort_keys=False)
|
|
97
|
+
logger.info(f"Using ESMValTool recipe:\n{recipe_txt}")
|
|
88
98
|
recipe_path = definition.to_output_path("recipe.yml")
|
|
89
99
|
with recipe_path.open("w", encoding="utf-8") as file:
|
|
90
|
-
|
|
100
|
+
file.write(recipe_txt)
|
|
101
|
+
return recipe_path
|
|
102
|
+
|
|
103
|
+
def build_cmd(self, definition: ExecutionDefinition) -> Iterable[str]:
|
|
104
|
+
"""
|
|
105
|
+
Build the command to run an ESMValTool recipe.
|
|
91
106
|
|
|
107
|
+
Parameters
|
|
108
|
+
----------
|
|
109
|
+
definition
|
|
110
|
+
A description of the information needed for this execution of the diagnostic
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
:
|
|
115
|
+
The result of running the diagnostic.
|
|
116
|
+
"""
|
|
117
|
+
recipe_path = self.write_recipe(definition)
|
|
92
118
|
climate_data = definition.to_output_path("climate_data")
|
|
93
119
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
120
|
+
for metric_dataset in definition.datasets.values():
|
|
121
|
+
prepare_climate_data(
|
|
122
|
+
metric_dataset.datasets,
|
|
123
|
+
climate_data_dir=climate_data,
|
|
124
|
+
)
|
|
98
125
|
|
|
99
126
|
config = {
|
|
100
127
|
"drs": {
|
|
@@ -130,7 +157,7 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
130
157
|
{
|
|
131
158
|
"OBS": str(data_dir / "OBS"),
|
|
132
159
|
"OBS6": str(data_dir / "OBS"),
|
|
133
|
-
"native6": str(data_dir / "
|
|
160
|
+
"native6": str(data_dir / "native6"),
|
|
134
161
|
}
|
|
135
162
|
)
|
|
136
163
|
config["rootpath"]["obs4MIPs"] = [ # type: ignore[index]
|
|
@@ -140,8 +167,10 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
140
167
|
|
|
141
168
|
config_dir = definition.to_output_path("config")
|
|
142
169
|
config_dir.mkdir()
|
|
170
|
+
config_txt = yaml.safe_dump(config)
|
|
171
|
+
logger.info(f"Using ESMValTool configuration:\n{config_txt}")
|
|
143
172
|
with (config_dir / "config.yml").open("w", encoding="utf-8") as file:
|
|
144
|
-
|
|
173
|
+
file.write(config_txt)
|
|
145
174
|
|
|
146
175
|
return [
|
|
147
176
|
"esmvaltool",
|
|
@@ -172,7 +201,17 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
172
201
|
metric_args = CMECMetric.create_template()
|
|
173
202
|
output_args = CMECOutput.create_template()
|
|
174
203
|
|
|
204
|
+
# Input selectors for the datasets used in the diagnostic.
|
|
205
|
+
# TODO: Better handling of multiple source types
|
|
206
|
+
if SourceDatasetType.CMIP6 in definition.datasets:
|
|
207
|
+
input_selectors = definition.datasets[SourceDatasetType.CMIP6].selector_dict()
|
|
208
|
+
elif SourceDatasetType.obs4MIPs in definition.datasets:
|
|
209
|
+
input_selectors = definition.datasets[SourceDatasetType.obs4MIPs].selector_dict()
|
|
210
|
+
else:
|
|
211
|
+
input_selectors = {}
|
|
212
|
+
|
|
175
213
|
# Add the plots and data files
|
|
214
|
+
series = []
|
|
176
215
|
plot_suffixes = {".png", ".jpg", ".pdf", ".ps"}
|
|
177
216
|
for metadata_file in result_dir.glob("run/*/*/diagnostic_provenance.yml"):
|
|
178
217
|
metadata = yaml.safe_load(metadata_file.read_text(encoding="utf-8"))
|
|
@@ -188,6 +227,11 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
188
227
|
OutputCV.LONG_NAME.value: caption,
|
|
189
228
|
OutputCV.DESCRIPTION.value: "",
|
|
190
229
|
}
|
|
230
|
+
series.extend(
|
|
231
|
+
self._extract_series_from_file(
|
|
232
|
+
definition, filename, relative_path, caption=caption, input_selectors=input_selectors
|
|
233
|
+
)
|
|
234
|
+
)
|
|
191
235
|
|
|
192
236
|
# Add the index.html file
|
|
193
237
|
index_html = f"{result_dir}/index.html"
|
|
@@ -211,11 +255,65 @@ class ESMValToolDiagnostic(CommandLineDiagnostic):
|
|
|
211
255
|
|
|
212
256
|
# Add the extra information from the groupby operations
|
|
213
257
|
if len(metric_bundle.DIMENSIONS[MetricCV.JSON_STRUCTURE.value]):
|
|
214
|
-
input_selectors = definition.datasets[SourceDatasetType.CMIP6].selector_dict()
|
|
215
258
|
metric_bundle = metric_bundle.prepend_dimensions(input_selectors)
|
|
216
259
|
|
|
217
260
|
return ExecutionResult.build_from_output_bundle(
|
|
218
261
|
definition,
|
|
219
262
|
cmec_output_bundle=output_bundle,
|
|
220
263
|
cmec_metric_bundle=metric_bundle,
|
|
264
|
+
series=series,
|
|
221
265
|
)
|
|
266
|
+
|
|
267
|
+
def _extract_series_from_file(
|
|
268
|
+
self,
|
|
269
|
+
definition: ExecutionDefinition,
|
|
270
|
+
filename: Path,
|
|
271
|
+
relative_path: Path,
|
|
272
|
+
caption: str,
|
|
273
|
+
input_selectors: dict[str, str],
|
|
274
|
+
) -> list[SeriesMetricValue]:
|
|
275
|
+
"""
|
|
276
|
+
Extract series data from a file if it matches any of the series definitions.
|
|
277
|
+
"""
|
|
278
|
+
variable_attributes = (
|
|
279
|
+
"long_name",
|
|
280
|
+
"standard_name",
|
|
281
|
+
"units",
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
series = []
|
|
285
|
+
for series_def in definition.diagnostic.series:
|
|
286
|
+
if fnmatch.fnmatch(
|
|
287
|
+
str(relative_path),
|
|
288
|
+
f"executions/*/{series_def.file_pattern.format(**input_selectors)}",
|
|
289
|
+
):
|
|
290
|
+
dataset = xr.open_dataset(filename, decode_times=xr.coders.CFDatetimeCoder(use_cftime=True))
|
|
291
|
+
dataset = dataset.sel(series_def.sel)
|
|
292
|
+
attributes = {
|
|
293
|
+
attr: dataset.attrs[attr] for attr in series_def.attributes if attr in dataset.attrs
|
|
294
|
+
}
|
|
295
|
+
attributes["caption"] = caption
|
|
296
|
+
attributes["values_name"] = series_def.values_name
|
|
297
|
+
attributes["index_name"] = series_def.index_name
|
|
298
|
+
for attr in variable_attributes:
|
|
299
|
+
if attr in dataset[series_def.values_name].attrs:
|
|
300
|
+
attributes[f"value_{attr}"] = dataset[series_def.values_name].attrs[attr]
|
|
301
|
+
if attr in dataset[series_def.index_name].attrs:
|
|
302
|
+
attributes[f"index_{attr}"] = dataset[series_def.index_name].attrs[attr]
|
|
303
|
+
index = dataset[series_def.index_name].values.tolist()
|
|
304
|
+
if hasattr(index[0], "calendar"):
|
|
305
|
+
attributes["calendar"] = index[0].calendar
|
|
306
|
+
if hasattr(index[0], "isoformat"):
|
|
307
|
+
# Convert time objects to strings.
|
|
308
|
+
index = [v.isoformat() for v in index]
|
|
309
|
+
|
|
310
|
+
series.append(
|
|
311
|
+
SeriesMetricValue(
|
|
312
|
+
dimensions={**input_selectors, **series_def.dimensions},
|
|
313
|
+
values=dataset[series_def.values_name].values.tolist(),
|
|
314
|
+
index=index,
|
|
315
|
+
index_name=series_def.index_name,
|
|
316
|
+
attributes=attributes,
|
|
317
|
+
)
|
|
318
|
+
)
|
|
319
|
+
return series
|
|
@@ -2,8 +2,9 @@ import pandas
|
|
|
2
2
|
|
|
3
3
|
from climate_ref_core.constraints import (
|
|
4
4
|
AddSupplementaryDataset,
|
|
5
|
-
|
|
5
|
+
PartialDateTime,
|
|
6
6
|
RequireFacets,
|
|
7
|
+
RequireTimerange,
|
|
7
8
|
)
|
|
8
9
|
from climate_ref_core.datasets import FacetFilter, SourceDatasetType
|
|
9
10
|
from climate_ref_core.diagnostics import DataRequirement
|
|
@@ -26,6 +27,14 @@ class ClimateAtGlobalWarmingLevels(ESMValToolDiagnostic):
|
|
|
26
27
|
"tas",
|
|
27
28
|
)
|
|
28
29
|
|
|
30
|
+
matching_facets = (
|
|
31
|
+
"source_id",
|
|
32
|
+
"member_id",
|
|
33
|
+
"grid_label",
|
|
34
|
+
"table_id",
|
|
35
|
+
"variable_id",
|
|
36
|
+
)
|
|
37
|
+
|
|
29
38
|
data_requirements = (
|
|
30
39
|
DataRequirement(
|
|
31
40
|
source_type=SourceDatasetType.CMIP6,
|
|
@@ -39,25 +48,32 @@ class ClimateAtGlobalWarmingLevels(ESMValToolDiagnostic):
|
|
|
39
48
|
"ssp370",
|
|
40
49
|
"ssp585",
|
|
41
50
|
),
|
|
51
|
+
"table_id": "Amon",
|
|
42
52
|
},
|
|
43
53
|
),
|
|
44
54
|
),
|
|
45
55
|
group_by=("experiment_id",),
|
|
46
56
|
constraints=(
|
|
47
|
-
RequireFacets("variable_id", variables),
|
|
48
57
|
AddSupplementaryDataset(
|
|
49
58
|
supplementary_facets={"experiment_id": "historical"},
|
|
50
|
-
matching_facets=
|
|
51
|
-
"source_id",
|
|
52
|
-
"member_id",
|
|
53
|
-
"grid_label",
|
|
54
|
-
"table_id",
|
|
55
|
-
"variable_id",
|
|
56
|
-
),
|
|
59
|
+
matching_facets=matching_facets,
|
|
57
60
|
optional_matching_facets=tuple(),
|
|
58
61
|
),
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
RequireTimerange(
|
|
63
|
+
group_by=matching_facets,
|
|
64
|
+
start=PartialDateTime(year=1850, month=1),
|
|
65
|
+
end=PartialDateTime(year=2100, month=12),
|
|
66
|
+
),
|
|
67
|
+
RequireFacets(
|
|
68
|
+
"experiment_id",
|
|
69
|
+
required_facets=("historical",),
|
|
70
|
+
group_by=matching_facets,
|
|
71
|
+
),
|
|
72
|
+
RequireFacets(
|
|
73
|
+
"variable_id",
|
|
74
|
+
required_facets=variables,
|
|
75
|
+
group_by=("experiment_id", "source_id", "member_id", "grid_label", "table_id"),
|
|
76
|
+
),
|
|
61
77
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
62
78
|
),
|
|
63
79
|
),
|
|
@@ -65,19 +81,29 @@ class ClimateAtGlobalWarmingLevels(ESMValToolDiagnostic):
|
|
|
65
81
|
facets = ()
|
|
66
82
|
|
|
67
83
|
@staticmethod
|
|
68
|
-
def update_recipe(
|
|
84
|
+
def update_recipe(
|
|
85
|
+
recipe: Recipe,
|
|
86
|
+
input_files: dict[SourceDatasetType, pandas.DataFrame],
|
|
87
|
+
) -> None:
|
|
69
88
|
"""Update the recipe."""
|
|
70
89
|
# Set up the datasets
|
|
71
90
|
diagnostics = recipe["diagnostics"]
|
|
72
91
|
for diagnostic in diagnostics.values():
|
|
73
92
|
diagnostic.pop("additional_datasets")
|
|
74
|
-
recipe_variables = dataframe_to_recipe(
|
|
93
|
+
recipe_variables = dataframe_to_recipe(
|
|
94
|
+
input_files[SourceDatasetType.CMIP6],
|
|
95
|
+
group_by=(
|
|
96
|
+
"source_id",
|
|
97
|
+
"member_id",
|
|
98
|
+
"grid_label",
|
|
99
|
+
"table_id",
|
|
100
|
+
"variable_id",
|
|
101
|
+
),
|
|
102
|
+
)
|
|
75
103
|
datasets = recipe_variables["tas"]["additional_datasets"]
|
|
76
104
|
datasets = [ds for ds in datasets if ds["exp"] != "historical"]
|
|
77
105
|
for dataset in datasets:
|
|
78
106
|
dataset.pop("timerange")
|
|
79
|
-
dataset["activity"] = ["CMIP", dataset["activity"]]
|
|
80
|
-
dataset["exp"] = ["historical", dataset["exp"]]
|
|
81
107
|
recipe["datasets"] = datasets
|
|
82
108
|
|
|
83
109
|
# Specify the timeranges
|
climate_ref_esmvaltool-0.7.0/src/climate_ref_esmvaltool/diagnostics/climate_drivers_for_fire.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import pandas
|
|
2
|
+
|
|
3
|
+
from climate_ref_core.constraints import (
|
|
4
|
+
AddSupplementaryDataset,
|
|
5
|
+
PartialDateTime,
|
|
6
|
+
RequireFacets,
|
|
7
|
+
RequireTimerange,
|
|
8
|
+
)
|
|
9
|
+
from climate_ref_core.datasets import FacetFilter, SourceDatasetType
|
|
10
|
+
from climate_ref_core.diagnostics import DataRequirement
|
|
11
|
+
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
|
|
12
|
+
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
|
|
13
|
+
from climate_ref_esmvaltool.types import Recipe
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ClimateDriversForFire(ESMValToolDiagnostic):
|
|
17
|
+
"""
|
|
18
|
+
Calculate diagnostics regarding climate drivers for fire.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
name = "Climate drivers for fire"
|
|
22
|
+
slug = "climate-drivers-for-fire"
|
|
23
|
+
base_recipe = "ref/recipe_ref_fire.yml"
|
|
24
|
+
|
|
25
|
+
data_requirements = (
|
|
26
|
+
DataRequirement(
|
|
27
|
+
source_type=SourceDatasetType.CMIP6,
|
|
28
|
+
filters=(
|
|
29
|
+
FacetFilter(
|
|
30
|
+
{
|
|
31
|
+
"variable_id": ("hurs", "pr", "tas", "tasmax"),
|
|
32
|
+
"experiment_id": "historical",
|
|
33
|
+
"table_id": "Amon",
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
FacetFilter(
|
|
37
|
+
{
|
|
38
|
+
"variable_id": ("cVeg", "treeFrac"),
|
|
39
|
+
"experiment_id": "historical",
|
|
40
|
+
"table_id": "Lmon",
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
FacetFilter(
|
|
44
|
+
{
|
|
45
|
+
"variable_id": "vegFrac",
|
|
46
|
+
"experiment_id": "historical",
|
|
47
|
+
"table_id": "Emon",
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
),
|
|
51
|
+
group_by=("source_id", "member_id", "grid_label"),
|
|
52
|
+
constraints=(
|
|
53
|
+
RequireTimerange(
|
|
54
|
+
group_by=("instance_id",),
|
|
55
|
+
start=PartialDateTime(2013, 1),
|
|
56
|
+
end=PartialDateTime(2014, 12),
|
|
57
|
+
),
|
|
58
|
+
AddSupplementaryDataset.from_defaults("sftlf", SourceDatasetType.CMIP6),
|
|
59
|
+
RequireFacets(
|
|
60
|
+
"variable_id",
|
|
61
|
+
(
|
|
62
|
+
"cVeg",
|
|
63
|
+
"hurs",
|
|
64
|
+
"pr",
|
|
65
|
+
"tas",
|
|
66
|
+
"tasmax",
|
|
67
|
+
"sftlf",
|
|
68
|
+
"treeFrac",
|
|
69
|
+
"vegFrac",
|
|
70
|
+
),
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
facets = ()
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def update_recipe(
|
|
79
|
+
recipe: Recipe,
|
|
80
|
+
input_files: dict[SourceDatasetType, pandas.DataFrame],
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Update the recipe."""
|
|
83
|
+
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
|
|
84
|
+
dataset = recipe_variables["cVeg"]["additional_datasets"][0]
|
|
85
|
+
dataset.pop("mip")
|
|
86
|
+
dataset.pop("timerange")
|
|
87
|
+
dataset["start_year"] = 2013
|
|
88
|
+
dataset["end_year"] = 2014
|
|
89
|
+
recipe["datasets"] = [dataset]
|
|
90
|
+
recipe["diagnostics"]["fire_evaluation"]["scripts"]["fire_evaluation"]["remove_confire_files"] = True
|
|
@@ -2,12 +2,14 @@ import pandas
|
|
|
2
2
|
|
|
3
3
|
from climate_ref_core.constraints import (
|
|
4
4
|
AddSupplementaryDataset,
|
|
5
|
-
|
|
5
|
+
PartialDateTime,
|
|
6
6
|
RequireFacets,
|
|
7
7
|
RequireOverlappingTimerange,
|
|
8
|
+
RequireTimerange,
|
|
8
9
|
)
|
|
9
10
|
from climate_ref_core.datasets import FacetFilter, SourceDatasetType
|
|
10
11
|
from climate_ref_core.diagnostics import DataRequirement
|
|
12
|
+
from climate_ref_core.metric_values.typing import SeriesDefinition
|
|
11
13
|
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
|
|
12
14
|
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
|
|
13
15
|
from climate_ref_esmvaltool.types import Recipe
|
|
@@ -22,8 +24,6 @@ class CloudRadiativeEffects(ESMValToolDiagnostic):
|
|
|
22
24
|
slug = "cloud-radiative-effects"
|
|
23
25
|
base_recipe = "ref/recipe_ref_cre.yml"
|
|
24
26
|
|
|
25
|
-
facets = ()
|
|
26
|
-
|
|
27
27
|
variables = (
|
|
28
28
|
"rlut",
|
|
29
29
|
"rlutcs",
|
|
@@ -37,40 +37,46 @@ class CloudRadiativeEffects(ESMValToolDiagnostic):
|
|
|
37
37
|
FacetFilter(
|
|
38
38
|
facets={
|
|
39
39
|
"variable_id": variables,
|
|
40
|
-
"experiment_id":
|
|
40
|
+
"experiment_id": "historical",
|
|
41
|
+
"table_id": "Amon",
|
|
41
42
|
}
|
|
42
43
|
),
|
|
43
44
|
),
|
|
44
45
|
group_by=("source_id", "member_id", "grid_label"),
|
|
45
46
|
constraints=(
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
RequireTimerange(
|
|
48
|
+
group_by=("instance_id",),
|
|
49
|
+
start=PartialDateTime(1996, 1),
|
|
50
|
+
end=PartialDateTime(2014, 12),
|
|
51
|
+
),
|
|
48
52
|
RequireOverlappingTimerange(group_by=("instance_id",)),
|
|
53
|
+
RequireFacets("variable_id", variables),
|
|
49
54
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
50
55
|
),
|
|
51
56
|
),
|
|
52
57
|
# TODO: Use CERES-EBAF, ESACCI-CLOUD, and ISCCP-FH from obs4MIPs once available.
|
|
53
58
|
)
|
|
54
59
|
|
|
60
|
+
facets = ()
|
|
61
|
+
series = tuple(
|
|
62
|
+
SeriesDefinition(
|
|
63
|
+
file_pattern=f"plot_profiles/plot/variable_vs_lat_{var_name}_*.nc",
|
|
64
|
+
sel={"dim0": 0}, # Select the model and not the observations.
|
|
65
|
+
dimensions={"statistic": f"{var_name} zonal mean"},
|
|
66
|
+
values_name=var_name,
|
|
67
|
+
index_name="lat",
|
|
68
|
+
attributes=[],
|
|
69
|
+
)
|
|
70
|
+
for var_name in ["lwcre", "swcre"]
|
|
71
|
+
)
|
|
72
|
+
|
|
55
73
|
@staticmethod
|
|
56
|
-
def update_recipe(recipe: Recipe, input_files: pandas.DataFrame) -> None:
|
|
74
|
+
def update_recipe(recipe: Recipe, input_files: dict[SourceDatasetType, pandas.DataFrame]) -> None:
|
|
57
75
|
"""Update the recipe."""
|
|
58
|
-
recipe_variables = dataframe_to_recipe(input_files)
|
|
76
|
+
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
|
|
59
77
|
recipe_variables = {k: v for k, v in recipe_variables.items() if k != "areacella"}
|
|
60
78
|
|
|
61
|
-
# Select a timerange covered by all datasets.
|
|
62
|
-
start_times, end_times = [], []
|
|
63
|
-
for variable in recipe_variables.values():
|
|
64
|
-
for dataset in variable["additional_datasets"]:
|
|
65
|
-
start, end = dataset["timerange"].split("/")
|
|
66
|
-
start_times.append(start)
|
|
67
|
-
end_times.append(end)
|
|
68
|
-
start_time = max(start_times)
|
|
69
|
-
start_time = max(start_time, "20010101T000000") # Earliest observational dataset availability
|
|
70
|
-
timerange = f"{start_time}/{min(end_times)}"
|
|
71
|
-
|
|
72
79
|
datasets = recipe_variables["rsut"]["additional_datasets"]
|
|
73
80
|
for dataset in datasets:
|
|
74
81
|
dataset.pop("timerange")
|
|
75
82
|
recipe["datasets"] = datasets
|
|
76
|
-
recipe["timerange_for_models"] = timerange
|