Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/473.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added ESMValTool ozone diagnostics.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rlu
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rlutcs_198201-201612.nc 21f096ecafff659e5c7e3338060425f7194e5d1b39c9510865496e04ecac3d75
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rsut_198201-201612.nc f2c3f3afcdc2e730df7985c210a3de89b0d4f83b150e0c3846f7ac3c5fa9c54a
ESMValTool/OBS/Tier2/ESACCI-CLOUD/OBS_ESACCI-CLOUD_sat_AVHRR-AMPM-fv3.0_Amon_rsutcs_198201-201612.nc d180d3140d4c1f6b9bb1960e07b45f192643f047e7c272c8c8c7070296ca3ab7
ESMValTool/OBS/Tier2/ESACCI-OZONE/OBS6_ESACCI-OZONE_sat_L3_AERmon_o3_198410-202212.nc 7ed9446b66e3b8382df4b6ce3074499a9ad00b7173a784c95df289fc9971ce69
ESMValTool/OBS/Tier2/HadCRUT5/OBS_HadCRUT5_ground_5.0.1.0-analysis_Amon_tas_185001-202112.nc edc3ee50b942dfbeccfd58b574df3393555379c2de3418c9717ac11dbafc12fc
ESMValTool/OBS/Tier2/ISCCP-FH/OBS_ISCCP-FH_sat_v0_Amon_rlut_198401-201612.nc 650b347df432f6e5f3f693310aad695a7502f2905ac545753c7d4ccb0592adbe
ESMValTool/OBS/Tier2/ISCCP-FH/OBS_ISCCP-FH_sat_v0_Amon_rlutcs_198401-201612.nc a90d9e035447f8778a2f64362411c079536d9dea559f6d53d032710b2c9b00e3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
from climate_ref_esmvaltool.diagnostics.ecs import EquilibriumClimateSensitivity
from climate_ref_esmvaltool.diagnostics.enso import ENSOBasicClimatology, ENSOCharacteristics
from climate_ref_esmvaltool.diagnostics.example import GlobalMeanTimeseries
from climate_ref_esmvaltool.diagnostics.ozone import (
O3LatMonthMapplot,
O3LatTimeMapplot,
O3PolarCapTimeseriesNH,
O3PolarCapTimeseriesSH,
O3ZonalMeanProfiles,
)
from climate_ref_esmvaltool.diagnostics.regional_historical_changes import (
RegionalHistoricalAnnualCycle,
RegionalHistoricalTimeSeries,
Expand All @@ -37,6 +44,11 @@
"ENSOCharacteristics",
"EquilibriumClimateSensitivity",
"GlobalMeanTimeseries",
"O3LatMonthMapplot",
"O3LatTimeMapplot",
"O3PolarCapTimeseriesNH",
"O3PolarCapTimeseriesSH",
"O3ZonalMeanProfiles",
"RegionalHistoricalAnnualCycle",
"RegionalHistoricalTimeSeries",
"RegionalHistoricalTrend",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
import pandas

from climate_ref_core.constraints import (
PartialDateTime,
RequireContiguousTimerange,
RequireTimerange,
)
from climate_ref_core.datasets import FacetFilter, SourceDatasetType
from climate_ref_core.diagnostics import DataRequirement

# from climate_ref_core.metric_values.typing import SeriesDefinition
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
from climate_ref_esmvaltool.types import Recipe


class O3LatTimeMapplot(ESMValToolDiagnostic):
"""
Calculate the ozone diagnostics - zonal mean total column ozone vs. time.
"""

name = "Ozone Diagnostics"
slug = "ozone-lat-time"
base_recipe = "ref/recipe_ref_ozone.yml"

data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"experiment_id": "historical",
"table_id": "AERmon",
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(1996, 1),
end=PartialDateTime(2014, 12),
),
RequireContiguousTimerange(group_by=("instance_id",)),
),
),
DataRequirement(
source_type=SourceDatasetType.obs4MIPs,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"source_id": "C3S-GTO-ECV-9-0",
"frequency": "mon",
},
),
),
group_by=("source_id",),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(1996, 1),
end=PartialDateTime(2014, 12),
),
),
),
)
facets = ()

@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
) -> None:
"""Update the recipe."""
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
dataset = recipe_variables["toz"]["additional_datasets"][0]
# set time range of model (CMIP6) dataset (should match observational period)
dataset["timerange"] = "1996/2014"
recipe["datasets"] = [dataset]
diagnostic = "lat_time_mapplot"
recipe["diagnostics"] = {diagnostic: recipe["diagnostics"][diagnostic]}
recipe["diagnostics"][diagnostic]["variables"]["toz"]["timerange"] = "1996/2014"


class O3PolarCapTimeseriesSH(ESMValToolDiagnostic):
"""
Calculate the ozone diagnostics - October SH polar mean (60S-85S) time series.
"""

name = "Ozone Diagnostics"
slug = "ozone-sh-oct"
base_recipe = "ref/recipe_ref_ozone.yml"

data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"experiment_id": "historical",
"table_id": "AERmon",
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(1950, 1),
end=PartialDateTime(2014, 12),
),
RequireContiguousTimerange(group_by=("instance_id",)),
),
),
DataRequirement(
source_type=SourceDatasetType.obs4MIPs,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"source_id": "C3S-GTO-ECV-9-0",
"frequency": "mon",
},
),
),
group_by=("source_id",),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(1996, 1),
end=PartialDateTime(2021, 12),
),
),
),
)
facets = ()

@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
) -> None:
"""Update the recipe."""
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
dataset = recipe_variables["toz"]["additional_datasets"][0]
# set model (CMIP6) time range to 1950...2014
dataset["timerange"] = "1950/2014"
recipe["datasets"] = [dataset]
diagnostic = "polar_cap_time_series_SH"
recipe["diagnostics"] = {diagnostic: recipe["diagnostics"][diagnostic]}


class O3PolarCapTimeseriesNH(ESMValToolDiagnostic):
"""
Calculate the ozone diagnostics - March NH polar mean (60N-80N) time series.
"""

name = "Ozone Diagnostics"
slug = "ozone-nh-mar"
base_recipe = "ref/recipe_ref_ozone.yml"

data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"experiment_id": "historical",
"table_id": "AERmon",
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(1950, 1),
end=PartialDateTime(2014, 12),
),
RequireContiguousTimerange(group_by=("instance_id",)),
),
),
DataRequirement(
source_type=SourceDatasetType.obs4MIPs,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"source_id": "C3S-GTO-ECV-9-0",
"frequency": "mon",
},
),
),
group_by=("source_id",),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(1996, 1),
end=PartialDateTime(2021, 12),
),
),
),
)
facets = ()

@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
) -> None:
"""Update the recipe."""
# Make sure only grid cells south of 80N are considered as there are no
# measurements north of 80N in March. Specifying 85N as northern boundary
# in the orignal 'recipe_ref_ozone.yml' is a bug!
recipe["preprocessors"]["create_time_series_NH"]["extract_region"]["end_latitude"] = 80
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
dataset = recipe_variables["toz"]["additional_datasets"][0]
# set model (CMIP6) time range to 1950...2014
dataset["timerange"] = "1950/2014"
recipe["datasets"] = [dataset]
diagnostic = "polar_cap_time_series_NH"
# adjust plot title to reflect bug fix regarding northern boundary (see above)
recipe["diagnostics"][diagnostic]["scripts"]["plot"]["plots"]["timeseries"]["pyplot_kwargs"][
"title"
] = "Total Column Ozone, 60-80N, March"
recipe["diagnostics"] = {diagnostic: recipe["diagnostics"][diagnostic]}


class O3ZonalMeanProfiles(ESMValToolDiagnostic):
"""
Calculate the ozone diagnostics - stratospheric zonal mean profiles.
"""

name = "Ozone Diagnostics"
slug = "ozone-zonal"
base_recipe = "ref/recipe_ref_ozone.yml"

data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": "o3",
"experiment_id": "historical",
"table_id": "Amon",
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(2005, 1),
end=PartialDateTime(2014, 12),
),
RequireContiguousTimerange(group_by=("instance_id",)),
),
),
# TODO: Use ESACCI-OZONE (SAGE-OMPS, variable o3) from obs4MIPs once available.
)
facets = ()

@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
) -> None:
"""Update the recipe."""
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
dataset = recipe_variables["o3"]["additional_datasets"][0]
# set model (CMIP6) time range to 2005...2014
dataset["timerange"] = "2005/2014"
recipe["datasets"] = [dataset]
diagnostic = "zonal_mean_profiles"
# adjust plot title to actual time range
recipe["diagnostics"][diagnostic]["scripts"]["plot"]["plots"]["zonal_mean_profile"]["pyplot_kwargs"][
"suptitle"
] = "{long_name} (2005-2014 mean)"
recipe["diagnostics"] = {diagnostic: recipe["diagnostics"][diagnostic]}
recipe["diagnostics"][diagnostic]["variables"]["o3"]["timerange"] = "2005/2014"


class O3LatMonthMapplot(ESMValToolDiagnostic):
"""
Calculate the ozone diagnostics - zonal mean total column ozone vs. annual cycle plot.
"""

name = "Ozone Diagnostics"
slug = "ozone-annual-cycle"
base_recipe = "ref/recipe_ref_ozone.yml"

data_requirements = (
DataRequirement(
source_type=SourceDatasetType.CMIP6,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"experiment_id": "historical",
"table_id": "AERmon",
},
),
),
group_by=("source_id", "member_id", "grid_label"),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(2005, 1),
end=PartialDateTime(2014, 12),
),
RequireContiguousTimerange(group_by=("instance_id",)),
),
),
DataRequirement(
source_type=SourceDatasetType.obs4MIPs,
filters=(
FacetFilter(
facets={
"variable_id": "toz",
"source_id": "C3S-GTO-ECV-9-0",
"frequency": "mon",
},
),
),
group_by=("source_id",),
constraints=(
RequireTimerange(
group_by=("instance_id",),
start=PartialDateTime(2005, 1),
end=PartialDateTime(2014, 12),
),
),
),
)
facets = ()

@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
) -> None:
"""Update the recipe."""
recipe_variables = dataframe_to_recipe(input_files[SourceDatasetType.CMIP6])
dataset = recipe_variables["toz"]["additional_datasets"][0]
# set model (CMIP6) time range to 2005...2014
dataset["timerange"] = "2005/2014"
recipe["datasets"] = [dataset]
diagnostic = "lat_month_mapplot"
recipe["diagnostics"] = {diagnostic: recipe["diagnostics"][diagnostic]}
recipe["diagnostics"][diagnostic]["variables"]["toz"]["timerange"] = "2005/2014"
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ref/recipe_enso_characteristics.yml 34c2518b138068ac96d212910b979d54a8fc
ref/recipe_ref_annual_cycle_region.yml 64ebc687789dad6c45a2361b45218cb5a0ad0e38c516840c65fc7e8bf7b5ace7
ref/recipe_ref_cre.yml 4375f262479c3b3e1b348b71080a6d758e195bda76516a591182045a3a29aa32
ref/recipe_ref_fire.yml 2ad82effaca4e742d8abe6a0aa07bb46e1e92ef0d2d240760f7623b0ba045926
ref/recipe_ref_ozone.yml 388aaf01721c0856ab7143b47b9d2f1efeaaae4ef57e11572c1e133b49aad0a6
ref/recipe_ref_sea_ice_area_basic.yml 7d01a8527880663ca28284772f83a8356d9972fb4f022a4000e50a56ce044b09
ref/recipe_ref_scatterplot.yml b99d1736e16256d161847b025811d7088ad9f892d4887fb009fa99c4079135a0
ref/recipe_ref_timeseries_region.yml 86f36e442021caba201601d8cf4624f8ce6715ce421670a467c792db2910db22
Expand Down
Loading