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/445.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added dimensions to files produced by ESMValTool diagnostics.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from climate_ref_core.constraints import GroupConstraint
from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType
from climate_ref_core.metric_values import SeriesMetricValue
from climate_ref_core.metric_values.typing import SeriesDefinition
from climate_ref_core.metric_values.typing import FileDefinition, SeriesDefinition
from climate_ref_core.pycmec.metric import CMECMetric
from climate_ref_core.pycmec.output import CMECOutput

Expand Down Expand Up @@ -516,6 +516,7 @@ class Diagnostic(AbstractDiagnostic):
"""

series: Sequence[SeriesDefinition] = tuple()
files: Sequence[FileDefinition] = tuple()

def __init__(self) -> None:
super().__init__()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@
Value = float | int


class SeriesDefinition(BaseModel):
class FileDefinition(BaseModel):
"""
A definition of a 1-d array with an associated index and additional dimensions.
A definition of an output file with associated additional dimensions.
"""

file_pattern: str
"""A glob pattern to match files that contain the series values."""

sel: dict[str, Any] | None = None
"""A dictionary of selection criteria to apply with :meth:`xarray.Dataset.sel` after loading the file."""

dimensions: dict[str, str]
"""Key, value pairs that identify the dimensions of the metric."""


class SeriesDefinition(FileDefinition):
"""
A definition of a 1-d array with an associated index and additional dimensions.
"""

sel: dict[str, Any] | None = None
"""A dictionary of selection criteria to apply with :meth:`xarray.Dataset.sel` after loading the file."""

values_name: str
"""The name of the variable in the file that contains the values of the series."""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,15 @@ def build_execution_result(
for filename in metadata:
caption = metadata[filename].get("caption", "")
relative_path = definition.as_relative_path(filename)
for file_def in (*definition.diagnostic.files, *definition.diagnostic.series):
if fnmatch.fnmatch(
str(relative_path),
f"executions/*/{file_def.file_pattern.format(**input_selectors)}",
):
dimensions = file_def.dimensions
break
else:
dimensions = {}
if relative_path.suffix in plot_suffixes:
key = OutputCV.PLOTS.value
else:
Expand All @@ -226,10 +235,15 @@ def build_execution_result(
OutputCV.FILENAME.value: f"{relative_path}",
OutputCV.LONG_NAME.value: caption,
OutputCV.DESCRIPTION.value: "",
OutputCV.DIMENSIONS.value: dimensions,
}
series.extend(
self._extract_series_from_file(
definition, filename, relative_path, caption=caption, input_selectors=input_selectors
definition,
filename,
relative_path,
caption=caption,
input_selectors=input_selectors,
)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import pandas
from pathlib import Path

import pandas as pd

from climate_ref_core.constraints import (
AddSupplementaryDataset,
PartialDateTime,
RequireFacets,
RequireTimerange,
)
from climate_ref_core.datasets import FacetFilter, SourceDatasetType
from climate_ref_core.datasets import ExecutionDatasetCollection, FacetFilter, SourceDatasetType
from climate_ref_core.diagnostics import DataRequirement
from climate_ref_core.metric_values.typing import FileDefinition
from climate_ref_core.pycmec.metric import CMECMetric, MetricCV
from climate_ref_core.pycmec.output import CMECOutput
from climate_ref_esmvaltool.diagnostics.base import ESMValToolDiagnostic
from climate_ref_esmvaltool.recipe import dataframe_to_recipe
from climate_ref_esmvaltool.types import Recipe
from climate_ref_esmvaltool.types import MetricBundleArgs, OutputBundleArgs, Recipe


class ClimateAtGlobalWarmingLevels(ESMValToolDiagnostic):
Expand Down Expand Up @@ -80,10 +85,30 @@ class ClimateAtGlobalWarmingLevels(ESMValToolDiagnostic):
)
facets = ()

files = tuple(
FileDefinition(
file_pattern=f"plots/gwl_mean_plots_{var_name}/plot_gwl_stats/*.png",
dimensions={
"statistic": "mean",
"variable_id": var_name,
},
)
for var_name in variables
) + tuple(
FileDefinition(
file_pattern=f"work/gwl_mean_plots_{var_name}/plot_gwl_stats/*.nc",
dimensions={
"statistic": "mean",
"variable_id": var_name,
},
)
for var_name in variables
)

@staticmethod
def update_recipe(
recipe: Recipe,
input_files: dict[SourceDatasetType, pandas.DataFrame],
input_files: dict[SourceDatasetType, pd.DataFrame],
) -> None:
"""Update the recipe."""
# Set up the datasets
Expand Down Expand Up @@ -124,3 +149,48 @@ def update_recipe(
"preprocessor": "multi_model_gwl_stats",
"timerange": "2000/2100",
}

@staticmethod
def format_result(
result_dir: Path,
execution_dataset: ExecutionDatasetCollection,
metric_args: MetricBundleArgs,
output_args: OutputBundleArgs,
) -> tuple[CMECMetric, CMECOutput]:
"""Format the result."""
metric_args[MetricCV.DIMENSIONS.value] = {
"json_structure": [
"global warming level",
"exceedance year",
],
"global warming level": {},
"exceedance year": {},
}

df = pd.read_csv(
result_dir
/ "work"
/ "calculate_gwl_exceedance_years"
/ "gwl_exceedance_calculation"
/ "GWL_exceedance_years.csv"
)
for row in df.itertuples(index=False):
gwl = str(row.GWL)
if gwl not in metric_args[MetricCV.DIMENSIONS.value]["global warming level"]:
metric_args[MetricCV.DIMENSIONS.value]["global warming level"][gwl] = {}
exceedance_year = str(row.Exceedance_Year)
metric_args[MetricCV.RESULTS.value][gwl] = exceedance_year

# metric_args[MetricCV.DIMENSIONS.value] = {
# "json_structure": ["region", "metric"],
# "region": {"global": {}},
# "metric": {"zec": {}},
# }

# metric_args[MetricCV.RESULTS.value] = {
# "global": {
# "zec": zec,
# },
# }

return CMECMetric.model_validate(metric_args), CMECOutput.model_validate(output_args)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from climate_ref_core.constraints import AddSupplementaryDataset, RequireContiguousTimerange
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_core.metric_values.typing import FileDefinition, 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
Expand Down Expand Up @@ -33,13 +33,27 @@ class GlobalMeanTimeseries(ESMValToolDiagnostic):
facets = ()
series = (
SeriesDefinition(
file_pattern="timeseries/script1/*.nc",
dimensions={"statistic": "tas annual global mean"},
file_pattern="work/timeseries/script1/*.nc",
dimensions={
"statistic": "annual mean",
"variable_id": "tas",
"region": "global",
},
values_name="tas",
index_name="time",
attributes=[],
),
)
files = (
FileDefinition(
file_pattern="plots/timeseries/script1/png/*.png",
dimensions={
"statistic": "annual mean",
"variable_id": "tas",
"region": "global",
},
),
)

@staticmethod
def update_recipe(
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading