climate-ref-esmvaltool 0.6.6__py3-none-any.whl → 0.8.0__py3-none-any.whl
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/diagnostics/base.py +92 -45
- climate_ref_esmvaltool/diagnostics/climate_at_global_warming_levels.py +37 -14
- climate_ref_esmvaltool/diagnostics/climate_drivers_for_fire.py +37 -15
- climate_ref_esmvaltool/diagnostics/cloud_radiative_effects.py +37 -18
- climate_ref_esmvaltool/diagnostics/cloud_scatterplots.py +19 -7
- climate_ref_esmvaltool/diagnostics/ecs.py +26 -5
- climate_ref_esmvaltool/diagnostics/enso.py +98 -8
- climate_ref_esmvaltool/diagnostics/example.py +11 -10
- climate_ref_esmvaltool/diagnostics/regional_historical_changes.py +139 -24
- climate_ref_esmvaltool/diagnostics/sea_ice_area_basic.py +57 -3
- climate_ref_esmvaltool/diagnostics/sea_ice_sensitivity.py +26 -12
- climate_ref_esmvaltool/diagnostics/tcr.py +16 -3
- climate_ref_esmvaltool/diagnostics/tcre.py +10 -12
- climate_ref_esmvaltool/diagnostics/zec.py +17 -3
- climate_ref_esmvaltool/recipe.py +9 -5
- {climate_ref_esmvaltool-0.6.6.dist-info → climate_ref_esmvaltool-0.8.0.dist-info}/METADATA +2 -1
- climate_ref_esmvaltool-0.8.0.dist-info/RECORD +30 -0
- {climate_ref_esmvaltool-0.6.6.dist-info → climate_ref_esmvaltool-0.8.0.dist-info}/WHEEL +1 -1
- climate_ref_esmvaltool-0.6.6.dist-info/RECORD +0 -30
- {climate_ref_esmvaltool-0.6.6.dist-info → climate_ref_esmvaltool-0.8.0.dist-info}/entry_points.txt +0 -0
- {climate_ref_esmvaltool-0.6.6.dist-info → climate_ref_esmvaltool-0.8.0.dist-info}/licenses/LICENCE +0 -0
- {climate_ref_esmvaltool-0.6.6.dist-info → climate_ref_esmvaltool-0.8.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -11,6 +11,7 @@ from climate_ref_core.constraints import (
|
|
|
11
11
|
)
|
|
12
12
|
from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType
|
|
13
13
|
from climate_ref_core.diagnostics import DataRequirement
|
|
14
|
+
from climate_ref_core.metric_values.typing import SeriesDefinition
|
|
14
15
|
from climate_ref_core.pycmec.metric import CMECMetric, MetricCV
|
|
15
16
|
from climate_ref_core.pycmec.output import CMECOutput
|
|
16
17
|
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
|
|
@@ -27,32 +28,117 @@ class ENSOBasicClimatology(ESMValToolDiagnostic):
|
|
|
27
28
|
slug = "enso-basic-climatology"
|
|
28
29
|
base_recipe = "ref/recipe_enso_basicclimatology.yml"
|
|
29
30
|
|
|
30
|
-
variables = (
|
|
31
|
-
"pr",
|
|
32
|
-
"tos",
|
|
33
|
-
"tauu",
|
|
34
|
-
)
|
|
35
31
|
data_requirements = (
|
|
36
32
|
DataRequirement(
|
|
37
33
|
source_type=SourceDatasetType.CMIP6,
|
|
38
34
|
filters=(
|
|
39
35
|
FacetFilter(
|
|
40
36
|
facets={
|
|
41
|
-
"variable_id":
|
|
37
|
+
"variable_id": ("pr", "tauu"),
|
|
42
38
|
"experiment_id": "historical",
|
|
39
|
+
"table_id": "Amon",
|
|
40
|
+
},
|
|
41
|
+
),
|
|
42
|
+
FacetFilter(
|
|
43
|
+
facets={
|
|
44
|
+
"variable_id": "tos",
|
|
45
|
+
"experiment_id": "historical",
|
|
46
|
+
"table_id": "Omon",
|
|
43
47
|
},
|
|
44
48
|
),
|
|
45
49
|
),
|
|
46
50
|
group_by=("source_id", "member_id", "grid_label"),
|
|
47
51
|
constraints=(
|
|
48
|
-
RequireFacets("variable_id", variables),
|
|
49
52
|
RequireContiguousTimerange(group_by=("instance_id",)),
|
|
50
53
|
RequireOverlappingTimerange(group_by=("instance_id",)),
|
|
54
|
+
RequireFacets(
|
|
55
|
+
"variable_id",
|
|
56
|
+
(
|
|
57
|
+
"pr",
|
|
58
|
+
"tauu",
|
|
59
|
+
"tos",
|
|
60
|
+
),
|
|
61
|
+
),
|
|
51
62
|
),
|
|
52
63
|
),
|
|
53
64
|
)
|
|
54
65
|
facets = ()
|
|
55
66
|
|
|
67
|
+
series = (
|
|
68
|
+
tuple(
|
|
69
|
+
SeriesDefinition(
|
|
70
|
+
file_pattern=f"diagnostic_metrics/plot_script/{source_id}_eq_{var_name}_bias.nc",
|
|
71
|
+
dimensions=(
|
|
72
|
+
{
|
|
73
|
+
"statistic": (
|
|
74
|
+
f"zonal bias in the time-mean {var_name} structure across the equatorial Pacific"
|
|
75
|
+
),
|
|
76
|
+
}
|
|
77
|
+
| ({} if source_id == "{source_id}" else {"reference_source_id": source_id})
|
|
78
|
+
),
|
|
79
|
+
values_name="tos" if var_name == "sst" else var_name,
|
|
80
|
+
index_name="lon",
|
|
81
|
+
attributes=[],
|
|
82
|
+
)
|
|
83
|
+
for var_name in ("pr", "sst", "tauu")
|
|
84
|
+
for source_id in ("{source_id}", "GPCP-V2.3", "TROPFLUX")
|
|
85
|
+
)
|
|
86
|
+
+ tuple(
|
|
87
|
+
SeriesDefinition(
|
|
88
|
+
file_pattern=f"diagnostic_metrics/plot_script/{{source_id}}_eq_{var_name}_seacycle.nc",
|
|
89
|
+
dimensions=(
|
|
90
|
+
{
|
|
91
|
+
"statistic": (
|
|
92
|
+
"zonal bias in the amplitude of the mean seasonal cycle of "
|
|
93
|
+
f"{var_name} in the equatorial Pacific"
|
|
94
|
+
),
|
|
95
|
+
}
|
|
96
|
+
| ({} if source_id == "{source_id}" else {"reference_source_id": source_id})
|
|
97
|
+
),
|
|
98
|
+
values_name="tos" if var_name == "sst" else var_name,
|
|
99
|
+
index_name="lon",
|
|
100
|
+
attributes=[],
|
|
101
|
+
)
|
|
102
|
+
for var_name in ("pr", "sst", "tauu")
|
|
103
|
+
for source_id in ("{source_id}", "GPCP-V2.3", "TROPFLUX")
|
|
104
|
+
)
|
|
105
|
+
+ tuple(
|
|
106
|
+
SeriesDefinition(
|
|
107
|
+
file_pattern="diagnostic_metrics/plot_script/{source_id}_pr_double.nc",
|
|
108
|
+
dimensions=(
|
|
109
|
+
{
|
|
110
|
+
"statistic": (
|
|
111
|
+
"meridional bias in the time-mean pr structure across the eastern Pacific"
|
|
112
|
+
),
|
|
113
|
+
}
|
|
114
|
+
| ({} if source_id == "{source_id}" else {"reference_source_id": source_id})
|
|
115
|
+
),
|
|
116
|
+
values_name="pr",
|
|
117
|
+
index_name="lat",
|
|
118
|
+
attributes=[],
|
|
119
|
+
)
|
|
120
|
+
for source_id in ("{source_id}", "GPCP-V2.3")
|
|
121
|
+
)
|
|
122
|
+
+ tuple(
|
|
123
|
+
SeriesDefinition(
|
|
124
|
+
file_pattern="diagnostic_metrics/plot_script/*_pr_double_seacycle.nc",
|
|
125
|
+
dimensions=(
|
|
126
|
+
{
|
|
127
|
+
"statistic": (
|
|
128
|
+
"meridional bias in the amplitude of the mean seasonal "
|
|
129
|
+
"pr cycle in the eastern Pacific"
|
|
130
|
+
),
|
|
131
|
+
}
|
|
132
|
+
| ({} if source_id == "{source_id}" else {"reference_source_id": source_id})
|
|
133
|
+
),
|
|
134
|
+
values_name="pr",
|
|
135
|
+
index_name="lat",
|
|
136
|
+
attributes=[],
|
|
137
|
+
)
|
|
138
|
+
for source_id in ("{source_id}", "GPCP-V2.3")
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
|
|
56
142
|
@staticmethod
|
|
57
143
|
def update_recipe(
|
|
58
144
|
recipe: Recipe,
|
|
@@ -85,19 +171,23 @@ class ENSOCharacteristics(ESMValToolDiagnostic):
|
|
|
85
171
|
facets={
|
|
86
172
|
"variable_id": "tos",
|
|
87
173
|
"experiment_id": "historical",
|
|
174
|
+
"table_id": "Omon",
|
|
88
175
|
},
|
|
89
176
|
),
|
|
90
177
|
),
|
|
91
178
|
group_by=("source_id", "member_id", "grid_label"),
|
|
92
179
|
constraints=(
|
|
93
|
-
RequireFacets("variable_id", ("tos",)),
|
|
94
180
|
RequireContiguousTimerange(group_by=("instance_id",)),
|
|
95
181
|
RequireOverlappingTimerange(group_by=("instance_id",)),
|
|
96
182
|
AddSupplementaryDataset.from_defaults("areacello", SourceDatasetType.CMIP6),
|
|
183
|
+
RequireFacets("variable_id", ("tos", "areacello")),
|
|
97
184
|
),
|
|
98
185
|
),
|
|
99
186
|
)
|
|
100
187
|
facets = ("grid_label", "member_id", "source_id", "region", "metric")
|
|
188
|
+
# ENSO pattern and lifecycle are series, but the ESMValTool diagnostic
|
|
189
|
+
# script does not save the values used in the figure.
|
|
190
|
+
series = tuple()
|
|
101
191
|
|
|
102
192
|
@staticmethod
|
|
103
193
|
def update_recipe(
|
|
@@ -17,28 +17,29 @@ class GlobalMeanTimeseries(ESMValToolDiagnostic):
|
|
|
17
17
|
name = "Global Mean Timeseries"
|
|
18
18
|
slug = "global-mean-timeseries"
|
|
19
19
|
base_recipe = "examples/recipe_python.yml"
|
|
20
|
-
series = (
|
|
21
|
-
SeriesDefinition(
|
|
22
|
-
file_pattern="timeseries/script1/*.nc",
|
|
23
|
-
dimensions={},
|
|
24
|
-
values_name="tas",
|
|
25
|
-
index_name="time",
|
|
26
|
-
attributes=[],
|
|
27
|
-
),
|
|
28
|
-
)
|
|
29
20
|
|
|
30
21
|
data_requirements = (
|
|
31
22
|
DataRequirement(
|
|
32
23
|
source_type=SourceDatasetType.CMIP6,
|
|
33
24
|
filters=(FacetFilter(facets={"variable_id": ("tas",)}),),
|
|
34
|
-
group_by=("
|
|
25
|
+
group_by=("source_id", "experiment_id", "member_id", "table_id", "variable_id", "grid_label"),
|
|
35
26
|
constraints=(
|
|
36
27
|
RequireContiguousTimerange(group_by=("instance_id",)),
|
|
37
28
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
38
29
|
),
|
|
39
30
|
),
|
|
40
31
|
)
|
|
32
|
+
|
|
41
33
|
facets = ()
|
|
34
|
+
series = (
|
|
35
|
+
SeriesDefinition(
|
|
36
|
+
file_pattern="timeseries/script1/*.nc",
|
|
37
|
+
dimensions={"statistic": "tas annual global mean"},
|
|
38
|
+
values_name="tas",
|
|
39
|
+
index_name="time",
|
|
40
|
+
attributes=[],
|
|
41
|
+
),
|
|
42
|
+
)
|
|
42
43
|
|
|
43
44
|
@staticmethod
|
|
44
45
|
def update_recipe(
|
|
@@ -7,15 +7,16 @@ import xarray
|
|
|
7
7
|
|
|
8
8
|
from climate_ref_core.constraints import (
|
|
9
9
|
AddSupplementaryDataset,
|
|
10
|
-
|
|
10
|
+
PartialDateTime,
|
|
11
11
|
RequireFacets,
|
|
12
|
+
RequireTimerange,
|
|
12
13
|
)
|
|
13
14
|
from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType
|
|
14
15
|
from climate_ref_core.diagnostics import DataRequirement
|
|
15
16
|
from climate_ref_core.metric_values.typing import SeriesDefinition
|
|
16
17
|
from climate_ref_core.pycmec.metric import CMECMetric, MetricCV
|
|
17
18
|
from climate_ref_core.pycmec.output import CMECOutput
|
|
18
|
-
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
|
|
19
|
+
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic, fillvalues_to_nan
|
|
19
20
|
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
|
|
20
21
|
from climate_ref_esmvaltool.types import MetricBundleArgs, OutputBundleArgs, Recipe
|
|
21
22
|
|
|
@@ -86,6 +87,15 @@ def normalize_region(region: str) -> str:
|
|
|
86
87
|
return region.replace("&", "-and-").replace("/", "-and-")
|
|
87
88
|
|
|
88
89
|
|
|
90
|
+
REFERENCE_DATASETS = {
|
|
91
|
+
"hus": "ERA-5",
|
|
92
|
+
"pr": "GPCP-V2.3",
|
|
93
|
+
"psl": "ERA-5",
|
|
94
|
+
"tas": "HadCRUT5-5.0.1.0-analysis",
|
|
95
|
+
"ua": "ERA-5",
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
89
99
|
class RegionalHistoricalAnnualCycle(ESMValToolDiagnostic):
|
|
90
100
|
"""
|
|
91
101
|
Plot regional historical annual cycle of climate variables.
|
|
@@ -102,18 +112,6 @@ class RegionalHistoricalAnnualCycle(ESMValToolDiagnostic):
|
|
|
102
112
|
"tas",
|
|
103
113
|
"ua",
|
|
104
114
|
)
|
|
105
|
-
series = tuple(
|
|
106
|
-
SeriesDefinition(
|
|
107
|
-
file_pattern=f"anncyc-{region}/allplots/*_{var_name}_*.nc",
|
|
108
|
-
sel={"dim0": 0}, # Select the model and not the observation.
|
|
109
|
-
dimensions={"region": region},
|
|
110
|
-
values_name=var_name,
|
|
111
|
-
index_name="month_number",
|
|
112
|
-
attributes=[],
|
|
113
|
-
)
|
|
114
|
-
for var_name in variables
|
|
115
|
-
for region in REGIONS
|
|
116
|
-
)
|
|
117
115
|
|
|
118
116
|
data_requirements = (
|
|
119
117
|
DataRequirement(
|
|
@@ -123,14 +121,18 @@ class RegionalHistoricalAnnualCycle(ESMValToolDiagnostic):
|
|
|
123
121
|
facets={
|
|
124
122
|
"variable_id": variables,
|
|
125
123
|
"experiment_id": "historical",
|
|
126
|
-
"
|
|
124
|
+
"table_id": "Amon",
|
|
127
125
|
},
|
|
128
126
|
),
|
|
129
127
|
),
|
|
130
128
|
group_by=("source_id", "member_id", "grid_label"),
|
|
131
129
|
constraints=(
|
|
130
|
+
RequireTimerange(
|
|
131
|
+
group_by=("instance_id",),
|
|
132
|
+
start=PartialDateTime(1980, 1),
|
|
133
|
+
end=PartialDateTime(2009, 12),
|
|
134
|
+
),
|
|
132
135
|
RequireFacets("variable_id", variables),
|
|
133
|
-
RequireContiguousTimerange(group_by=("instance_id",)),
|
|
134
136
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
135
137
|
),
|
|
136
138
|
),
|
|
@@ -149,7 +151,14 @@ class RegionalHistoricalAnnualCycle(ESMValToolDiagnostic):
|
|
|
149
151
|
),
|
|
150
152
|
),
|
|
151
153
|
group_by=("source_id",),
|
|
152
|
-
constraints=(
|
|
154
|
+
constraints=(
|
|
155
|
+
RequireTimerange(
|
|
156
|
+
group_by=("instance_id",),
|
|
157
|
+
start=PartialDateTime(1980, 1),
|
|
158
|
+
end=PartialDateTime(2009, 12),
|
|
159
|
+
),
|
|
160
|
+
RequireFacets("variable_id", ("psl", "ua")),
|
|
161
|
+
),
|
|
153
162
|
# TODO: Add obs4MIPs datasets once available and working:
|
|
154
163
|
#
|
|
155
164
|
# obs4MIPs dataset that cannot be ingested (https://github.com/Climate-REF/climate-ref/issues/260):
|
|
@@ -160,7 +169,28 @@ class RegionalHistoricalAnnualCycle(ESMValToolDiagnostic):
|
|
|
160
169
|
# - HadCRUT5_ground_5.0.1.0-analysis: tas
|
|
161
170
|
),
|
|
162
171
|
)
|
|
172
|
+
|
|
163
173
|
facets = ()
|
|
174
|
+
series = tuple(
|
|
175
|
+
SeriesDefinition(
|
|
176
|
+
file_pattern=f"anncyc-{region}/allplots/*_{var_name}_*.nc",
|
|
177
|
+
sel={"dim0": 0}, # Select the model and not the observation.
|
|
178
|
+
dimensions=(
|
|
179
|
+
{
|
|
180
|
+
"region": region,
|
|
181
|
+
"variable_id": var_name,
|
|
182
|
+
"statistic": "mean",
|
|
183
|
+
}
|
|
184
|
+
| ({} if i == 0 else {"reference_source_id": REFERENCE_DATASETS[var_name]})
|
|
185
|
+
),
|
|
186
|
+
values_name=var_name,
|
|
187
|
+
index_name="month_number",
|
|
188
|
+
attributes=[],
|
|
189
|
+
)
|
|
190
|
+
for var_name in variables
|
|
191
|
+
for region in REGIONS
|
|
192
|
+
for i in range(2)
|
|
193
|
+
)
|
|
164
194
|
|
|
165
195
|
@staticmethod
|
|
166
196
|
def update_recipe(
|
|
@@ -211,18 +241,91 @@ class RegionalHistoricalTimeSeries(RegionalHistoricalAnnualCycle):
|
|
|
211
241
|
name = "Regional historical mean and anomaly of climate variables"
|
|
212
242
|
slug = "regional-historical-timeseries"
|
|
213
243
|
base_recipe = "ref/recipe_ref_timeseries_region.yml"
|
|
244
|
+
|
|
245
|
+
variables = (
|
|
246
|
+
"hus",
|
|
247
|
+
"pr",
|
|
248
|
+
"psl",
|
|
249
|
+
"tas",
|
|
250
|
+
"ua",
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
data_requirements = (
|
|
254
|
+
DataRequirement(
|
|
255
|
+
source_type=SourceDatasetType.CMIP6,
|
|
256
|
+
filters=(
|
|
257
|
+
FacetFilter(
|
|
258
|
+
facets={
|
|
259
|
+
"variable_id": variables,
|
|
260
|
+
"experiment_id": "historical",
|
|
261
|
+
"table_id": "Amon",
|
|
262
|
+
},
|
|
263
|
+
),
|
|
264
|
+
),
|
|
265
|
+
group_by=("source_id", "member_id", "grid_label"),
|
|
266
|
+
constraints=(
|
|
267
|
+
RequireTimerange(
|
|
268
|
+
group_by=("instance_id",),
|
|
269
|
+
start=PartialDateTime(1980, 1),
|
|
270
|
+
end=PartialDateTime(2014, 12),
|
|
271
|
+
),
|
|
272
|
+
RequireFacets("variable_id", variables),
|
|
273
|
+
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
274
|
+
),
|
|
275
|
+
),
|
|
276
|
+
DataRequirement(
|
|
277
|
+
source_type=SourceDatasetType.obs4MIPs,
|
|
278
|
+
filters=(
|
|
279
|
+
FacetFilter(
|
|
280
|
+
facets={
|
|
281
|
+
"variable_id": (
|
|
282
|
+
"psl",
|
|
283
|
+
"ua",
|
|
284
|
+
),
|
|
285
|
+
"source_id": "ERA-5",
|
|
286
|
+
"frequency": "mon",
|
|
287
|
+
},
|
|
288
|
+
),
|
|
289
|
+
),
|
|
290
|
+
group_by=("source_id",),
|
|
291
|
+
constraints=(
|
|
292
|
+
RequireTimerange(
|
|
293
|
+
group_by=("instance_id",),
|
|
294
|
+
start=PartialDateTime(1980, 1),
|
|
295
|
+
end=PartialDateTime(2014, 12),
|
|
296
|
+
),
|
|
297
|
+
),
|
|
298
|
+
# TODO: Add obs4MIPs datasets once available and working:
|
|
299
|
+
#
|
|
300
|
+
# obs4MIPs dataset that cannot be ingested (https://github.com/Climate-REF/climate-ref/issues/260):
|
|
301
|
+
# - GPCP-V2.3: pr
|
|
302
|
+
#
|
|
303
|
+
# Not yet available on obs4MIPs:
|
|
304
|
+
# - ERA5: hus
|
|
305
|
+
# - HadCRUT5_ground_5.0.1.0-analysis: tas
|
|
306
|
+
),
|
|
307
|
+
)
|
|
308
|
+
|
|
214
309
|
series = tuple(
|
|
215
310
|
SeriesDefinition(
|
|
216
311
|
file_pattern=f"{diagnostic}-{region}/allplots/*_{var_name}_*.nc",
|
|
217
|
-
sel={"dim0":
|
|
218
|
-
dimensions=
|
|
312
|
+
sel={"dim0": i},
|
|
313
|
+
dimensions=(
|
|
314
|
+
{
|
|
315
|
+
"region": region,
|
|
316
|
+
"variable_id": var_name,
|
|
317
|
+
"statistic": ("mean" if diagnostic == "timeseries_abs" else "mean anomaly"),
|
|
318
|
+
}
|
|
319
|
+
| ({} if i == 0 else {"reference_source_id": REFERENCE_DATASETS[var_name]})
|
|
320
|
+
),
|
|
219
321
|
values_name=var_name,
|
|
220
322
|
index_name="time",
|
|
221
323
|
attributes=[],
|
|
222
324
|
)
|
|
223
|
-
for var_name in
|
|
325
|
+
for var_name in variables
|
|
224
326
|
for region in REGIONS
|
|
225
327
|
for diagnostic in ["timeseries_abs", "timeseries"]
|
|
328
|
+
for i in range(2)
|
|
226
329
|
)
|
|
227
330
|
|
|
228
331
|
|
|
@@ -249,13 +352,17 @@ class RegionalHistoricalTrend(ESMValToolDiagnostic):
|
|
|
249
352
|
"ua",
|
|
250
353
|
),
|
|
251
354
|
"experiment_id": "historical",
|
|
252
|
-
"
|
|
355
|
+
"table_id": "Amon",
|
|
253
356
|
},
|
|
254
357
|
),
|
|
255
358
|
),
|
|
256
359
|
group_by=("source_id", "member_id", "grid_label"),
|
|
257
360
|
constraints=(
|
|
258
|
-
|
|
361
|
+
RequireTimerange(
|
|
362
|
+
group_by=("instance_id",),
|
|
363
|
+
start=PartialDateTime(1980, 1),
|
|
364
|
+
end=PartialDateTime(2009, 12),
|
|
365
|
+
),
|
|
259
366
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
260
367
|
),
|
|
261
368
|
),
|
|
@@ -275,7 +382,13 @@ class RegionalHistoricalTrend(ESMValToolDiagnostic):
|
|
|
275
382
|
),
|
|
276
383
|
),
|
|
277
384
|
group_by=("source_id",),
|
|
278
|
-
constraints=(
|
|
385
|
+
constraints=(
|
|
386
|
+
RequireTimerange(
|
|
387
|
+
group_by=("instance_id",),
|
|
388
|
+
start=PartialDateTime(1980, 1),
|
|
389
|
+
end=PartialDateTime(2009, 12),
|
|
390
|
+
),
|
|
391
|
+
),
|
|
279
392
|
# TODO: Add obs4MIPs datasets once available and working:
|
|
280
393
|
#
|
|
281
394
|
# obs4MIPs dataset that cannot be ingested (https://github.com/Climate-REF/climate-ref/issues/260):
|
|
@@ -330,7 +443,9 @@ class RegionalHistoricalTrend(ESMValToolDiagnostic):
|
|
|
330
443
|
variable_id = next(iter(ds.data_vars.keys()))
|
|
331
444
|
metric_args[MetricCV.DIMENSIONS.value]["variable_id"][variable_id] = {}
|
|
332
445
|
metric_args[MetricCV.RESULTS.value][variable_id] = {}
|
|
333
|
-
for region_value, trend_value in zip(
|
|
446
|
+
for region_value, trend_value in zip(
|
|
447
|
+
ds.shape_id.astype(str).values, fillvalues_to_nan(ds[variable_id].values)
|
|
448
|
+
):
|
|
334
449
|
region = region_value.strip()
|
|
335
450
|
trend = float(trend_value)
|
|
336
451
|
if region not in metric_args[MetricCV.DIMENSIONS.value]["region"]:
|
|
@@ -2,14 +2,27 @@ import pandas
|
|
|
2
2
|
|
|
3
3
|
from climate_ref_core.constraints import (
|
|
4
4
|
AddSupplementaryDataset,
|
|
5
|
-
|
|
5
|
+
PartialDateTime,
|
|
6
|
+
RequireFacets,
|
|
7
|
+
RequireTimerange,
|
|
6
8
|
)
|
|
7
9
|
from climate_ref_core.datasets import FacetFilter, SourceDatasetType
|
|
8
10
|
from climate_ref_core.diagnostics import DataRequirement
|
|
11
|
+
from climate_ref_core.metric_values.typing import SeriesDefinition
|
|
9
12
|
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
|
|
10
13
|
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
|
|
11
14
|
from climate_ref_esmvaltool.types import Recipe
|
|
12
15
|
|
|
16
|
+
REGIONS = {
|
|
17
|
+
"nh": "Northern Hemisphere",
|
|
18
|
+
"sh": "Southern Hemisphere",
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
MONTHS = {
|
|
22
|
+
"nh": "September",
|
|
23
|
+
"sh": "February",
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
|
|
14
27
|
class SeaIceAreaBasic(ESMValToolDiagnostic):
|
|
15
28
|
"""
|
|
@@ -28,18 +41,59 @@ class SeaIceAreaBasic(ESMValToolDiagnostic):
|
|
|
28
41
|
facets={
|
|
29
42
|
"variable_id": "siconc",
|
|
30
43
|
"experiment_id": "historical",
|
|
44
|
+
"table_id": "SImon",
|
|
31
45
|
},
|
|
32
46
|
),
|
|
33
47
|
),
|
|
34
|
-
group_by=("
|
|
48
|
+
group_by=("source_id", "member_id", "grid_label"),
|
|
35
49
|
constraints=(
|
|
36
|
-
|
|
50
|
+
RequireTimerange(
|
|
51
|
+
group_by=("instance_id",),
|
|
52
|
+
start=PartialDateTime(1979, 1),
|
|
53
|
+
end=PartialDateTime(2014, 12),
|
|
54
|
+
),
|
|
37
55
|
AddSupplementaryDataset.from_defaults("areacello", SourceDatasetType.CMIP6),
|
|
56
|
+
RequireFacets("variable_id", ("siconc", "areacello")),
|
|
38
57
|
),
|
|
39
58
|
),
|
|
40
59
|
# TODO: Use OSI-450-nh and OSI-450-sh from obs4MIPs once available.
|
|
41
60
|
)
|
|
42
61
|
facets = ()
|
|
62
|
+
series = tuple(
|
|
63
|
+
SeriesDefinition(
|
|
64
|
+
file_pattern=f"siarea_min/allplots/timeseries_sea_ice_area_{region}_*.nc",
|
|
65
|
+
sel={"dim0": i},
|
|
66
|
+
dimensions=(
|
|
67
|
+
{
|
|
68
|
+
"region": REGIONS[region],
|
|
69
|
+
"statistic": f"{MONTHS[region]} sea ice area",
|
|
70
|
+
}
|
|
71
|
+
| ({} if i == 0 else {"reference_source_id": f"OSI-450-{region}"})
|
|
72
|
+
),
|
|
73
|
+
values_name="siconc",
|
|
74
|
+
index_name="time",
|
|
75
|
+
attributes=[],
|
|
76
|
+
)
|
|
77
|
+
for region in REGIONS
|
|
78
|
+
for i in range(2)
|
|
79
|
+
) + tuple(
|
|
80
|
+
SeriesDefinition(
|
|
81
|
+
file_pattern=f"siarea_seas/allplots/annual_cycle_sea_ice_area_{region}_*.nc",
|
|
82
|
+
sel={"dim0": i},
|
|
83
|
+
dimensions=(
|
|
84
|
+
{
|
|
85
|
+
"region": REGIONS[region],
|
|
86
|
+
"statistic": "20-year average seasonal cycle of the sea ice area",
|
|
87
|
+
}
|
|
88
|
+
| ({} if i == 0 else {"reference_source_id": f"OSI-450-{region}"})
|
|
89
|
+
),
|
|
90
|
+
values_name="siconc",
|
|
91
|
+
index_name="month_number",
|
|
92
|
+
attributes=[],
|
|
93
|
+
)
|
|
94
|
+
for region in REGIONS
|
|
95
|
+
for i in range(2)
|
|
96
|
+
)
|
|
43
97
|
|
|
44
98
|
@staticmethod
|
|
45
99
|
def update_recipe(
|
|
@@ -5,8 +5,9 @@ import pandas as pd
|
|
|
5
5
|
|
|
6
6
|
from climate_ref_core.constraints import (
|
|
7
7
|
AddSupplementaryDataset,
|
|
8
|
-
|
|
8
|
+
PartialDateTime,
|
|
9
9
|
RequireFacets,
|
|
10
|
+
RequireTimerange,
|
|
10
11
|
)
|
|
11
12
|
from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType
|
|
12
13
|
from climate_ref_core.diagnostics import DataRequirement
|
|
@@ -26,31 +27,44 @@ class SeaIceSensitivity(ESMValToolDiagnostic):
|
|
|
26
27
|
slug = "sea-ice-sensitivity"
|
|
27
28
|
base_recipe = "recipe_seaice_sensitivity.yml"
|
|
28
29
|
|
|
29
|
-
variables = (
|
|
30
|
-
"siconc",
|
|
31
|
-
"tas",
|
|
32
|
-
)
|
|
33
|
-
|
|
34
30
|
data_requirements = (
|
|
35
31
|
DataRequirement(
|
|
36
32
|
source_type=SourceDatasetType.CMIP6,
|
|
37
33
|
filters=(
|
|
38
34
|
FacetFilter(
|
|
39
35
|
facets={
|
|
40
|
-
"variable_id":
|
|
36
|
+
"variable_id": "siconc",
|
|
37
|
+
"experiment_id": "historical",
|
|
38
|
+
"table_id": "SImon",
|
|
39
|
+
},
|
|
40
|
+
),
|
|
41
|
+
FacetFilter(
|
|
42
|
+
facets={
|
|
43
|
+
"variable_id": "tas",
|
|
41
44
|
"experiment_id": "historical",
|
|
45
|
+
"table_id": "Amon",
|
|
42
46
|
},
|
|
43
47
|
),
|
|
44
48
|
),
|
|
45
49
|
group_by=("experiment_id",), # this does nothing, but group_by cannot be empty
|
|
46
50
|
constraints=(
|
|
51
|
+
RequireTimerange(
|
|
52
|
+
group_by=("instance_id",),
|
|
53
|
+
start=PartialDateTime(1979, 1),
|
|
54
|
+
end=PartialDateTime(2014, 12),
|
|
55
|
+
),
|
|
56
|
+
RequireFacets(
|
|
57
|
+
"variable_id",
|
|
58
|
+
required_facets=("siconc", "tas"),
|
|
59
|
+
group_by=("source_id", "member_id", "grid_label"),
|
|
60
|
+
),
|
|
47
61
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
48
62
|
AddSupplementaryDataset.from_defaults("areacello", SourceDatasetType.CMIP6),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
RequireFacets(
|
|
64
|
+
"variable_id",
|
|
65
|
+
required_facets=("areacello",),
|
|
66
|
+
group_by=("source_id", "grid_label"),
|
|
67
|
+
),
|
|
54
68
|
),
|
|
55
69
|
),
|
|
56
70
|
)
|
|
@@ -11,9 +11,10 @@ from climate_ref_core.constraints import (
|
|
|
11
11
|
)
|
|
12
12
|
from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType
|
|
13
13
|
from climate_ref_core.diagnostics import DataRequirement
|
|
14
|
+
from climate_ref_core.metric_values.typing import SeriesDefinition
|
|
14
15
|
from climate_ref_core.pycmec.metric import CMECMetric, MetricCV
|
|
15
16
|
from climate_ref_core.pycmec.output import CMECOutput
|
|
16
|
-
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
|
|
17
|
+
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic, fillvalues_to_nan
|
|
17
18
|
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
|
|
18
19
|
from climate_ref_esmvaltool.types import MetricBundleArgs, OutputBundleArgs, Recipe
|
|
19
20
|
|
|
@@ -39,19 +40,31 @@ class TransientClimateResponse(ESMValToolDiagnostic):
|
|
|
39
40
|
facets={
|
|
40
41
|
"variable_id": ("tas",),
|
|
41
42
|
"experiment_id": experiments,
|
|
43
|
+
"table_id": "Amon",
|
|
42
44
|
},
|
|
43
45
|
),
|
|
44
46
|
),
|
|
45
47
|
group_by=("source_id", "member_id", "grid_label"),
|
|
46
48
|
constraints=(
|
|
47
|
-
RequireFacets("experiment_id", experiments),
|
|
48
49
|
RequireContiguousTimerange(group_by=("instance_id",)),
|
|
49
50
|
RequireOverlappingTimerange(group_by=("instance_id",)),
|
|
51
|
+
RequireFacets("experiment_id", experiments),
|
|
50
52
|
AddSupplementaryDataset.from_defaults("areacella", SourceDatasetType.CMIP6),
|
|
51
53
|
),
|
|
52
54
|
),
|
|
53
55
|
)
|
|
54
56
|
facets = ("grid_label", "member_id", "source_id", "region", "metric")
|
|
57
|
+
series = (
|
|
58
|
+
SeriesDefinition(
|
|
59
|
+
file_pattern="tcr/calculate/{source_id}*.nc",
|
|
60
|
+
dimensions={
|
|
61
|
+
"statistic": "global annual mean tas anomaly relative to linear fit of piControl run",
|
|
62
|
+
},
|
|
63
|
+
values_name="tas_anomaly",
|
|
64
|
+
index_name="time",
|
|
65
|
+
attributes=[],
|
|
66
|
+
),
|
|
67
|
+
)
|
|
55
68
|
|
|
56
69
|
@staticmethod
|
|
57
70
|
def update_recipe(
|
|
@@ -104,7 +117,7 @@ class TransientClimateResponse(ESMValToolDiagnostic):
|
|
|
104
117
|
) -> tuple[CMECMetric, CMECOutput]:
|
|
105
118
|
"""Format the result."""
|
|
106
119
|
tcr_ds = xarray.open_dataset(result_dir / "work" / "tcr" / "calculate" / "tcr.nc")
|
|
107
|
-
tcr = float(tcr_ds["tcr"].values[0])
|
|
120
|
+
tcr = float(fillvalues_to_nan(tcr_ds["tcr"].values)[0])
|
|
108
121
|
|
|
109
122
|
# Update the diagnostic bundle arguments with the computed diagnostics.
|
|
110
123
|
metric_args[MetricCV.DIMENSIONS.value] = {
|