Skip to content

Commit 1c91f9e

Browse files
committed
Add sea ice area seasonal cycle and timeseries diagnostic
1 parent 7344f41 commit 1c91f9e

6 files changed

Lines changed: 242 additions & 0 deletions

File tree

changelog/239.feature.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added seasonal cycle and time series of sea ice area metrics.

packages/ref-metrics-esmvaltool/src/cmip_ref_metrics_esmvaltool/metrics/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
from cmip_ref_metrics_esmvaltool.metrics.ecs import EquilibriumClimateSensitivity
44
from cmip_ref_metrics_esmvaltool.metrics.example import GlobalMeanTimeseries
5+
from cmip_ref_metrics_esmvaltool.metrics.sea_ice_area_seasonal_cycle import SeaIceAreaSeasonalCycle
56
from cmip_ref_metrics_esmvaltool.metrics.tcr import TransientClimateResponse
67
from cmip_ref_metrics_esmvaltool.metrics.tcre import TransientClimateResponseEmissions
78
from cmip_ref_metrics_esmvaltool.metrics.zec import ZeroEmissionCommitment
89

910
__all__ = [
1011
"EquilibriumClimateSensitivity",
1112
"GlobalMeanTimeseries",
13+
"SeaIceAreaSeasonalCycle",
1214
"TransientClimateResponse",
1315
"TransientClimateResponseEmissions",
1416
"ZeroEmissionCommitment",
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import pandas
2+
3+
from cmip_ref_core.constraints import (
4+
AddSupplementaryDataset,
5+
RequireContiguousTimerange,
6+
)
7+
from cmip_ref_core.datasets import FacetFilter, SourceDatasetType
8+
from cmip_ref_core.metrics import DataRequirement
9+
from cmip_ref_metrics_esmvaltool.metrics.base import ESMValToolMetric
10+
from cmip_ref_metrics_esmvaltool.recipe import dataframe_to_recipe
11+
from cmip_ref_metrics_esmvaltool.types import Recipe
12+
13+
14+
class SeaIceAreaSeasonalCycle(ESMValToolMetric):
15+
"""
16+
Calculate seasonal cycle and time series of NH and SH sea ice area.
17+
"""
18+
19+
name = "Sea ice area seasonal cycle"
20+
slug = "esmvaltool-sea-ice-area-seasonal-cycle"
21+
base_recipe = "ref/recipe_ref_sea_ice_area_basic.yml"
22+
23+
data_requirements = (
24+
DataRequirement(
25+
source_type=SourceDatasetType.CMIP6,
26+
filters=(
27+
FacetFilter(
28+
facets={
29+
"variable_id": "siconc",
30+
"experiment_id": "historical",
31+
},
32+
),
33+
),
34+
group_by=("instance_id",),
35+
constraints=(
36+
RequireContiguousTimerange(group_by=("instance_id",)),
37+
AddSupplementaryDataset.from_defaults("areacello", SourceDatasetType.CMIP6),
38+
),
39+
),
40+
)
41+
42+
@staticmethod
43+
def update_recipe(recipe: Recipe, input_files: pandas.DataFrame) -> None:
44+
"""Update the recipe."""
45+
# Overlap between observations and historical experiment.
46+
timerange = "1995/2014"
47+
48+
# Update datasets
49+
recipe_variables = dataframe_to_recipe(input_files)
50+
recipe["datasets"] = recipe_variables["siconc"]["additional_datasets"]
51+
for dataset in recipe["datasets"]:
52+
dataset["timerange"] = timerange
53+
54+
# Update observational datasets
55+
nh_obs = {
56+
"dataset": "OSI-450-nh",
57+
"mip": "OImon",
58+
"project": "OBS",
59+
"supplementary_variables": [
60+
{
61+
"short_name": "areacello",
62+
"mip": "fx",
63+
},
64+
],
65+
"tier": 2,
66+
"timerange": timerange,
67+
"type": "reanaly",
68+
"version": "v3",
69+
}
70+
sh_obs = nh_obs.copy()
71+
sh_obs["dataset"] = "OSI-450-sh"
72+
diagnostics = recipe["diagnostics"]
73+
diagnostics["siarea_min"]["variables"]["sea_ice_area_nh_sep"]["additional_datasets"] = [nh_obs]
74+
diagnostics["siarea_min"]["variables"]["sea_ice_area_sh_feb"]["additional_datasets"] = [sh_obs]
75+
diagnostics["siarea_seas"]["variables"]["sea_ice_area_nh"]["additional_datasets"] = [nh_obs]
76+
diagnostics["siarea_seas"]["variables"]["sea_ice_area_sh"]["additional_datasets"] = [sh_obs]

packages/ref-metrics-esmvaltool/src/cmip_ref_metrics_esmvaltool/recipes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ recipe_ecs.yml 0cc57034fcb64e32015b4ff949ece5df8cdb8c6f493618b50cede
33
recipe_tcr.yml 35f9ef035a4e71aff5cac5dd26c49da2162fc00291bf3b0bd16b661b7b2f606b
44
recipe_tcre.yml 4668e357e00c515a8264ac75cb319ce558289689e10189e6f9e982886c414c94
55
recipe_zec.yml b0af7f789b7610ab3f29a6617124aa40c40866ead958204fc199eaf82863de51
6+
ref/recipe_ref_sea_ice_area_basic.yml 552e282a16ec355778b06f33897e1b8ba8388e5f8a5f814c4c42d91f63007457
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
{
2+
"start_time":{
3+
"33":"1850-01-16T12:00:00.000",
4+
"31":null
5+
},
6+
"end_time":{
7+
"33":"2014-12-16T12:00:00.000",
8+
"31":null
9+
},
10+
"path":{
11+
"33":"\/home\/bandela\/climate_data\/CMIP6\/CMIP\/CSIRO\/ACCESS-ESM1-5\/historical\/r1i1p1f1\/SImon\/siconc\/gn\/v20200817\/siconc_SImon_ACCESS-ESM1-5_historical_r1i1p1f1_gn_185001-201412.nc",
12+
"31":"\/home\/bandela\/climate_data\/CMIP6\/CMIP\/CSIRO\/ACCESS-ESM1-5\/historical\/r1i1p1f1\/Ofx\/areacello\/gn\/v20191115\/areacello_Ofx_ACCESS-ESM1-5_historical_r1i1p1f1_gn.nc"
13+
},
14+
"activity_id":{
15+
"33":"CMIP",
16+
"31":"CMIP"
17+
},
18+
"branch_method":{
19+
"33":"standard",
20+
"31":"standard"
21+
},
22+
"branch_time_in_child":{
23+
"33":0.0,
24+
"31":0.0
25+
},
26+
"branch_time_in_parent":{
27+
"33":21915.0,
28+
"31":21915.0
29+
},
30+
"experiment":{
31+
"33":"all-forcing simulation of the recent past",
32+
"31":"all-forcing simulation of the recent past"
33+
},
34+
"experiment_id":{
35+
"33":"historical",
36+
"31":"historical"
37+
},
38+
"frequency":{
39+
"33":"mon",
40+
"31":"fx"
41+
},
42+
"grid":{
43+
"33":"native atmosphere N96 grid (145x192 latxlon)",
44+
"31":"native atmosphere N96 grid (145x192 latxlon)"
45+
},
46+
"grid_label":{
47+
"33":"gn",
48+
"31":"gn"
49+
},
50+
"institution_id":{
51+
"33":"CSIRO",
52+
"31":"CSIRO"
53+
},
54+
"nominal_resolution":{
55+
"33":"250 km",
56+
"31":"250 km"
57+
},
58+
"parent_activity_id":{
59+
"33":"CMIP",
60+
"31":"CMIP"
61+
},
62+
"parent_experiment_id":{
63+
"33":"piControl",
64+
"31":"piControl"
65+
},
66+
"parent_source_id":{
67+
"33":"ACCESS-ESM1-5",
68+
"31":"ACCESS-ESM1-5"
69+
},
70+
"parent_time_units":{
71+
"33":"days since 0101-1-1",
72+
"31":"days since 0101-1-1"
73+
},
74+
"parent_variant_label":{
75+
"33":"r1i1p1f1",
76+
"31":"r1i1p1f1"
77+
},
78+
"product":{
79+
"33":"model-output",
80+
"31":"model-output"
81+
},
82+
"realm":{
83+
"33":"seaIce",
84+
"31":"ocean"
85+
},
86+
"source_id":{
87+
"33":"ACCESS-ESM1-5",
88+
"31":"ACCESS-ESM1-5"
89+
},
90+
"source_type":{
91+
"33":"AOGCM",
92+
"31":"AOGCM"
93+
},
94+
"sub_experiment":{
95+
"33":"none",
96+
"31":"none"
97+
},
98+
"sub_experiment_id":{
99+
"33":"none",
100+
"31":"none"
101+
},
102+
"table_id":{
103+
"33":"SImon",
104+
"31":"Ofx"
105+
},
106+
"variable_id":{
107+
"33":"siconc",
108+
"31":"areacello"
109+
},
110+
"variant_label":{
111+
"33":"r1i1p1f1",
112+
"31":"r1i1p1f1"
113+
},
114+
"member_id":{
115+
"33":"r1i1p1f1",
116+
"31":"r1i1p1f1"
117+
},
118+
"standard_name":{
119+
"33":"sea_ice_area_fraction",
120+
"31":"cell_area"
121+
},
122+
"long_name":{
123+
"33":"Sea-Ice Area Percentage (Ocean Grid)",
124+
"31":"Grid-Cell Area for Ocean Variables"
125+
},
126+
"units":{
127+
"33":"%",
128+
"31":"m2"
129+
},
130+
"vertical_levels":{
131+
"33":1,
132+
"31":1
133+
},
134+
"init_year":{
135+
"33":null,
136+
"31":null
137+
},
138+
"version":{
139+
"33":"v20200817",
140+
"31":"v20191115"
141+
},
142+
"instance_id":{
143+
"33":"CMIP6.CMIP.CSIRO.ACCESS-ESM1-5.historical.r1i1p1f1.SImon.siconc.gn.v20200817",
144+
"31":"CMIP6.CMIP.CSIRO.ACCESS-ESM1-5.historical.r1i1p1f1.Ofx.areacello.gn.v20191115"
145+
}
146+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from pathlib import Path
2+
3+
import pandas
4+
from cmip_ref_metrics_esmvaltool.metrics import SeaIceAreaSeasonalCycle
5+
from cmip_ref_metrics_esmvaltool.recipe import load_recipe
6+
7+
8+
def test_update_recipe():
9+
input_files = pandas.read_json(Path(__file__).parent / "input_files_sea_ice_area.json")
10+
recipe = load_recipe("ref/recipe_ref_sea_ice_area_basic.yml")
11+
SeaIceAreaSeasonalCycle().update_recipe(recipe, input_files)
12+
assert len(recipe["datasets"]) == 1
13+
dataset = recipe["datasets"][0]
14+
assert dataset["dataset"] == input_files.iloc[0].source_id
15+
assert dataset["timerange"] == "1995/2014"
16+
assert len(recipe["diagnostics"]) == 2

0 commit comments

Comments
 (0)