From f79b2fe72b6cc8b968e3f058345d046a876243e0 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Wed, 1 Jul 2026 19:00:04 +1000 Subject: [PATCH 1/3] feat(esmvaltool): key reference identity on reference_source_id and emit kind --- changelog/+layer-a-esmvaltool.feature.md | 4 ++ .../diagnostics/base.py | 8 ++- .../cmip6/manifest.json | 4 +- .../cmip6/regression/series.json | 6 ++ .../cmip6/manifest.json | 4 +- .../cmip6/regression/series.json | 12 ++++ .../sea-ice-area-basic/cmip6/manifest.json | 4 +- .../cmip6/regression/series.json | 4 ++ .../sea-ice-area-basic/cmip7/manifest.json | 4 +- .../cmip7/regression/series.json | 4 ++ .../tests/unit/diagnostics/test_base.py | 40 ++++++++++++ .../tests/unit/test_series_contract.py | 63 +++++++++++++++++++ 12 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 changelog/+layer-a-esmvaltool.feature.md create mode 100644 packages/climate-ref-esmvaltool/tests/unit/test_series_contract.py diff --git a/changelog/+layer-a-esmvaltool.feature.md b/changelog/+layer-a-esmvaltool.feature.md new file mode 100644 index 000000000..34b021e2f --- /dev/null +++ b/changelog/+layer-a-esmvaltool.feature.md @@ -0,0 +1,4 @@ +ESMValTool series now emit the first-class `kind` (`model` or `reference`), +so an observation curve can be told apart from a model curve directly +instead of being inferred from the presence of `reference_source_id`. +The presentation attributes carried by each series are also made uniform across diagnostics. diff --git a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/base.py b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/base.py index 79519cc14..34cc29706 100644 --- a/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/base.py +++ b/packages/climate-ref-esmvaltool/src/climate_ref_esmvaltool/diagnostics/base.py @@ -19,7 +19,7 @@ ExecutionDefinition, ExecutionResult, ) -from climate_ref_core.metric_values.typing import SeriesMetricValue +from climate_ref_core.metric_values.typing import MetricValueKind, SeriesMetricValue from climate_ref_core.pycmec.metric import CMECMetric, MetricCV from climate_ref_core.pycmec.output import CMECOutput, OutputCV from climate_ref_esmvaltool.recipe import ( @@ -517,9 +517,15 @@ def _extract_series_from_file( # Convert byte strings from NetCDF to regular strings. index = [v.decode().strip() for v in index] + # A reference (observation) series is signalled by ``reference_source_id`` in the + # definition's dimensions; everything else is a model series. + kind: MetricValueKind = ( + "reference" if "reference_source_id" in series_def.dimensions else "model" + ) series.append( SeriesMetricValue( dimensions={**input_selectors, **series_def.dimensions}, + kind=kind, values=fillvalues_to_nan(dataset[series_def.values_name].values).tolist(), index=index, index_name=series_def.index_name, diff --git a/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/manifest.json b/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/manifest.json index e08cba786..efcd767ea 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/manifest.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/manifest.json @@ -3,7 +3,7 @@ "committed": { "diagnostic.json": "183d82f3963ad19b5a556b8025e6990c444f292adda1d464e12136d05a5ef3b3", "output.json": "4b9ebaf83c65b8e0718a84951502617a545fce6386cabe640de7ec406afe6509", - "series.json": "4ec8ab11924089ef7cba8bd16de237ad8431399caaef74c0a66e81fefee69ef3" + "series.json": "50c0cf4550d4ed6aaa42579957fa3603cfce3d2200bb7880bd7a7e66f09f5376" }, "diagnostic_version": 1, "native": { @@ -81,5 +81,5 @@ } }, "schema": 2, - "test_case_version": 1 + "test_case_version": 2 } diff --git a/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/regression/series.json b/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/regression/series.json index 17a5a9593..9f752115c 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/regression/series.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/cloud-radiative-effects/cmip6/regression/series.json @@ -200,6 +200,7 @@ 89.5 ], "index_name": "lat", + "kind": "reference", "values": [ -1.102461, -0.6439076, @@ -584,6 +585,7 @@ 89.5 ], "index_name": "lat", + "kind": "reference", "values": [ -2.597448, -2.985919, @@ -968,6 +970,7 @@ 89.5 ], "index_name": "lat", + "kind": "reference", "values": [ 6.785992, 7.329451, @@ -1352,6 +1355,7 @@ 89.5 ], "index_name": "lat", + "kind": "reference", "values": [ -9.128001, -8.946151, @@ -1736,6 +1740,7 @@ 89.5 ], "index_name": "lat", + "kind": "reference", "values": [ 5.890097, 5.866584, @@ -2120,6 +2125,7 @@ 89.5 ], "index_name": "lat", + "kind": "reference", "values": [ -0.5029026, -0.4262416, diff --git a/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/manifest.json b/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/manifest.json index eff37af87..90e97911d 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/manifest.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/manifest.json @@ -3,7 +3,7 @@ "committed": { "diagnostic.json": "183d82f3963ad19b5a556b8025e6990c444f292adda1d464e12136d05a5ef3b3", "output.json": "f1a62fdcea7c346688eb476587778df31bec3e0b457b8fb5b4aeb7d57d2bb63e", - "series.json": "2e7f6ee7162116378d21f0f405d639244ea8e53b74c2dfe2260ad0e1665b3ec9" + "series.json": "ad93b4525763b2e0070f0bf92a20d95ea77731b911e21da770d5fba7d13e7782" }, "diagnostic_version": 1, "native": { @@ -149,5 +149,5 @@ } }, "schema": 2, - "test_case_version": 1 + "test_case_version": 2 } diff --git a/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/regression/series.json b/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/regression/series.json index ebed2ace0..b2c10208c 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/regression/series.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/enso-basic-climatology/cmip6/regression/series.json @@ -50,6 +50,7 @@ 14.5 ], "index_name": "lat", + "kind": "reference", "values": [ 0.8117609, 0.9348878, @@ -134,6 +135,7 @@ 14.5 ], "index_name": "lat", + "kind": "reference", "values": [ 0.4165757, 0.3797182, @@ -218,6 +220,7 @@ 14.5 ], "index_name": "lat", + "kind": "reference", "values": [ 1.640816, 1.671181, @@ -392,6 +395,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 1.553391, 1.584454, @@ -656,6 +660,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 0.4707869, 0.448114, @@ -920,6 +925,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 14.90164, 16.3394, @@ -1184,6 +1190,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 8.117987, 8.118301, @@ -1448,6 +1455,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 1.553391, 1.584454, @@ -1712,6 +1720,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 0.4707869, 0.448114, @@ -1976,6 +1985,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 14.90164, 16.3394, @@ -2240,6 +2250,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ 29.65842, 29.57058, @@ -2504,6 +2515,7 @@ 269.5 ], "index_name": "lon", + "kind": "reference", "values": [ -4.569511, -5.326211, diff --git a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/manifest.json b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/manifest.json index 3a964ba37..8dd115889 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/manifest.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/manifest.json @@ -3,7 +3,7 @@ "committed": { "diagnostic.json": "183d82f3963ad19b5a556b8025e6990c444f292adda1d464e12136d05a5ef3b3", "output.json": "ece9f19183b1bede25cda85779d3eb905f51bc24615559dbcc2ac6688835cd92", - "series.json": "8ad040e4747b2fc954d9166da0e6a11749cf5f97efc51ea73e49b220b2062f8b" + "series.json": "7b48e1d8126b3c37a27eb167cdeebc00ca1d5a2c8f955e9362120dbedd84b926" }, "diagnostic_version": 1, "native": { @@ -65,5 +65,5 @@ } }, "schema": 2, - "test_case_version": 1 + "test_case_version": 2 } diff --git a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/regression/series.json b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/regression/series.json index 181e0e461..dd6c15199 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/regression/series.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip6/regression/series.json @@ -32,6 +32,7 @@ 12 ], "index_name": "month_number", + "kind": "reference", "values": [ 12.79599, 13.63637, @@ -113,6 +114,7 @@ "2014-09-16T00:00:00" ], "index_name": "time", + "kind": "reference", "values": [ 6.301603, null, @@ -193,6 +195,7 @@ 12 ], "index_name": "month_number", + "kind": "reference", "values": [ 3.640914, 2.252787, @@ -282,6 +285,7 @@ "2014-02-15T00:00:00" ], "index_name": "time", + "kind": "reference", "values": [ 2.269726, null, diff --git a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json index e5f0e2ea6..04ce01772 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json @@ -3,10 +3,10 @@ "committed": { "diagnostic.json": "183d82f3963ad19b5a556b8025e6990c444f292adda1d464e12136d05a5ef3b3", "output.json": "ece9f19183b1bede25cda85779d3eb905f51bc24615559dbcc2ac6688835cd92", - "series.json": "1535dab04428841a3ac32a30acaa7c78ce57d8035cd3671518c01ab1db9e52eb" + "series.json": "19a25697156765ef8707c5c28123bd22026c723faa38c998a94d8875f1e283c4" }, "diagnostic_version": 1, "native": {}, "schema": 2, - "test_case_version": 1 + "test_case_version": 2 } diff --git a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/regression/series.json b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/regression/series.json index 6e342fecb..b05f81fe8 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/regression/series.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/regression/series.json @@ -32,6 +32,7 @@ 12 ], "index_name": "month_number", + "kind": "reference", "values": [ 12.79599, 13.63637, @@ -113,6 +114,7 @@ "2014-09-16T00:00:00" ], "index_name": "time", + "kind": "reference", "values": [ 6.301603, null, @@ -193,6 +195,7 @@ 12 ], "index_name": "month_number", + "kind": "reference", "values": [ 3.640914, 2.252787, @@ -282,6 +285,7 @@ "2014-02-15T00:00:00" ], "index_name": "time", + "kind": "reference", "values": [ 2.269726, null, diff --git a/packages/climate-ref-esmvaltool/tests/unit/diagnostics/test_base.py b/packages/climate-ref-esmvaltool/tests/unit/diagnostics/test_base.py index c9da4def5..112d0fb3f 100644 --- a/packages/climate-ref-esmvaltool/tests/unit/diagnostics/test_base.py +++ b/packages/climate-ref-esmvaltool/tests/unit/diagnostics/test_base.py @@ -155,6 +155,46 @@ def test_series_extraction(tmp_path, metric_definition, mock_diagnostic, mocker) assert s.attributes["caption"] == "Test caption." +@pytest.mark.parametrize( + "dimensions,expected_kind", + [ + ({"variable_id": "lwcre", "statistic": "zonal mean"}, "model"), + ( + {"variable_id": "lwcre", "statistic": "zonal mean", "reference_source_id": "CERES-EBAF"}, + "reference", + ), + ], +) +def test_series_extraction_kind(tmp_path, metric_definition, mock_diagnostic, dimensions, expected_kind): + """A series_def carrying ``reference_source_id`` yields ``kind="reference"``; otherwise ``"model"``.""" + metric_definition.diagnostic.series = [ + SeriesDefinition( + file_pattern="work/timeseries/script1/file0.nc", + attributes=[], + dimensions=dimensions, + values_name="data", + index_name="time", + ) + ] + + results_dir = metric_definition.to_output_path("executions") / "recipe_test" + nc_path = results_dir / "work" / "timeseries" / "script1" / "file0.nc" + nc_path.parent.mkdir(parents=True, exist_ok=True) + ds = xr.Dataset({"data": ("time", np.array([10.0, 20.0, 30.0]))}, coords={"time": np.array([1, 2, 3])}) + ds.to_netcdf(nc_path) + + metadata_file = results_dir / "run" / "timeseries" / "script1" / "diagnostic_provenance.yml" + metadata_file.parent.mkdir(parents=True, exist_ok=True) + with metadata_file.open("w", encoding="utf-8") as file: + yaml.dump({str(nc_path): {"caption": "Test caption."}}, file) + + result = mock_diagnostic.build_execution_result(definition=metric_definition) + loaded_series = SeriesMetricValueType.load_from_json(result.to_output_path(result.series_filename)) + + assert loaded_series, "Series should not be empty" + assert loaded_series[0].kind == expected_kind + + def test_series_extraction_byte_string_index(tmp_path, metric_definition, mock_diagnostic, mocker): """Test that byte string coordinates in NetCDF files are decoded to regular strings.""" metric_definition.diagnostic.series = [ diff --git a/packages/climate-ref-esmvaltool/tests/unit/test_series_contract.py b/packages/climate-ref-esmvaltool/tests/unit/test_series_contract.py new file mode 100644 index 000000000..05ab7c889 --- /dev/null +++ b/packages/climate-ref-esmvaltool/tests/unit/test_series_contract.py @@ -0,0 +1,63 @@ +""" +Contract tests over the committed ESMValTool ``series.json`` regression baselines. + +These assert two invariants hold across every committed baseline: + +- the role of each series is carried by the ``kind`` flag, derived from the presence of + ``reference_source_id`` in the series dimensions; +- the presentation-attribute key set is uniform across all series, modulo a small set of + legitimately-absent fields (a ``calendar`` only exists for a temporal index, a + ``standard_name`` only when the source variable declares one, and so on). +""" + +from pathlib import Path + +import pytest + +from climate_ref_core.metric_values import SeriesMetricValue + +TEST_DATA = Path(__file__).resolve().parents[1] / "test-data" + +# Always present on every committed series, regardless of the underlying variable or index. +REQUIRED_ATTRS = frozenset({"caption", "index_name", "value_long_name", "value_units", "values_name"}) +# Present only when the underlying data carries them (a temporal index has a calendar; a +# spatial index has units; some variables declare a CF ``standard_name``, others do not). +OPTIONAL_ATTRS = frozenset( + {"calendar", "index_long_name", "index_standard_name", "index_units", "value_standard_name"} +) + +SERIES_FILES = sorted(TEST_DATA.glob("**/regression/series.json")) + + +def _case_id(path: Path) -> str: + return str(path.relative_to(TEST_DATA).parent.parent) + + +@pytest.mark.parametrize("series_file", SERIES_FILES, ids=[_case_id(p) for p in SERIES_FILES]) +def test_committed_series_role_and_attrs(series_file): + """Every committed series carries the correct ``kind`` and a uniform attribute key set.""" + # An empty series.json is legitimate: some cases emit only scalars and plots, no series. + for s in SeriesMetricValue.load_from_json(series_file): + is_reference = "reference_source_id" in s.dimensions + expected_kind = "reference" if is_reference else "model" + assert s.kind == expected_kind, ( + f"{_case_id(series_file)}: series {s.dimensions} has kind={s.kind!r}, expected {expected_kind!r}" + ) + + attr_keys = frozenset(s.attributes or {}) + missing = REQUIRED_ATTRS - attr_keys + assert not missing, f"{_case_id(series_file)}: series {s.dimensions} missing attrs {sorted(missing)}" + unexpected = attr_keys - REQUIRED_ATTRS - OPTIONAL_ATTRS + assert not unexpected, ( + f"{_case_id(series_file)}: series {s.dimensions} has unexpected attrs {sorted(unexpected)}" + ) + + +def test_some_reference_series_exist(): + """Guard the guard: at least one committed baseline exercises the reference branch.""" + seen_reference = any( + s.kind == "reference" + for series_file in SERIES_FILES + for s in SeriesMetricValue.load_from_json(series_file) + ) + assert seen_reference, "no reference series found in any committed baseline; the kind test is vacuous" From 0f3601a7c86e114e858eb31ea84195aee24e0e60 Mon Sep 17 00:00:00 2001 From: Jared Lewis Date: Wed, 1 Jul 2026 19:03:19 +1000 Subject: [PATCH 2/3] docs: add changelog entry for esmvaltool series kind --- changelog/+layer-a-esmvaltool.feature.md | 4 ---- changelog/776.feature.md | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) delete mode 100644 changelog/+layer-a-esmvaltool.feature.md create mode 100644 changelog/776.feature.md diff --git a/changelog/+layer-a-esmvaltool.feature.md b/changelog/+layer-a-esmvaltool.feature.md deleted file mode 100644 index 34b021e2f..000000000 --- a/changelog/+layer-a-esmvaltool.feature.md +++ /dev/null @@ -1,4 +0,0 @@ -ESMValTool series now emit the first-class `kind` (`model` or `reference`), -so an observation curve can be told apart from a model curve directly -instead of being inferred from the presence of `reference_source_id`. -The presentation attributes carried by each series are also made uniform across diagnostics. diff --git a/changelog/776.feature.md b/changelog/776.feature.md new file mode 100644 index 000000000..b41d7e5a2 --- /dev/null +++ b/changelog/776.feature.md @@ -0,0 +1,3 @@ +ESMValTool series now carry an explicit `kind` of either `model` or `reference`, +so an observation curve can be distinguished from a model curve directly +rather than inferred from the presence of a reference source. From a23644d70e7fc1f58a8010c4feed4983945c74bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 09:13:02 +0000 Subject: [PATCH 3/3] chore(regression): mint native baselines for esmvaltool --- .../sea-ice-area-basic/cmip7/manifest.json | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json index 04ce01772..19456e914 100644 --- a/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json +++ b/packages/climate-ref-esmvaltool/tests/test-data/sea-ice-area-basic/cmip7/manifest.json @@ -6,7 +6,64 @@ "series.json": "19a25697156765ef8707c5c28123bd22026c723faa38c998a94d8875f1e283c4" }, "diagnostic_version": 1, - "native": {}, + "native": { + "diagnostic.json": { + "sha256": "e52b1e19e1ed5a2a046bb8aa01c004240305fabfe69c4ffb4e64898b1b6bbb84", + "size": 128 + }, + "executions/recipe/index.html": { + "sha256": "321a97aa277c5da181df94fdc3840adc22ea39b1ce5e43abab25d63f369aca9c", + "size": 22118 + }, + "executions/recipe/plots/siarea_min/allplots/timeseries_sea_ice_area_nh_sep_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.png": { + "sha256": "52481441afa31c1a002ab03eb80900405a67a987cad18f1182aaa095d905df3e", + "size": 169322 + }, + "executions/recipe/plots/siarea_min/allplots/timeseries_sea_ice_area_sh_feb_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.png": { + "sha256": "52dcecbcc3eb1f3c97500c23f69641c6bcac92e572b5d10ddd14f50762bf19bb", + "size": 163218 + }, + "executions/recipe/plots/siarea_seas/allplots/annual_cycle_sea_ice_area_nh_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.png": { + "sha256": "6a2642ed31b15c7e36d98110cc82efc0d45d9196624074ead4524ef6a8fa2017", + "size": 140446 + }, + "executions/recipe/plots/siarea_seas/allplots/annual_cycle_sea_ice_area_sh_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.png": { + "sha256": "67c979fb197a047c47e6913cc718ea50933e035d68dbcf1660d061a4b036f4ea", + "size": 143298 + }, + "executions/recipe/run/siarea_min/allplots/diagnostic_provenance.yml": { + "sha256": "b4b29ffbbcba669c0f5db59f5bfccde0efcbdd4bd3b7e6adea0704fd4d49de28", + "size": 1716 + }, + "executions/recipe/run/siarea_seas/allplots/diagnostic_provenance.yml": { + "sha256": "7a5e82c3c81ca78ac651134ee4b75bb1ea102d4fe7fadcfbe8fd733c349c1120", + "size": 1696 + }, + "executions/recipe/work/siarea_min/allplots/timeseries_sea_ice_area_nh_sep_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.nc": { + "sha256": "92d341d4800ae75ae226a14ccb79731ce870c2387396f96f9e9c72ab280de3cc", + "size": 10269 + }, + "executions/recipe/work/siarea_min/allplots/timeseries_sea_ice_area_sh_feb_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.nc": { + "sha256": "c91af07478699a4a21f83819012f6685b13a01a1bacc70cca7df621da3546065", + "size": 10269 + }, + "executions/recipe/work/siarea_seas/allplots/annual_cycle_sea_ice_area_nh_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.nc": { + "sha256": "3b6590bc8c9f0e4f00cd20b112490ada9eaf0aa80e520f73a8547e2a21d8ebb5", + "size": 10156 + }, + "executions/recipe/work/siarea_seas/allplots/annual_cycle_sea_ice_area_sh_ambiguous_dataset_ambiguous_mip_historical_r1i1p1f1.nc": { + "sha256": "510eb6fd6a0cd2735d7df544f704b3f8fde69e7fb4016421811d4fa9b2b58dbb", + "size": 10156 + }, + "output.json": { + "sha256": "451bcae9a54d7d358a750ef4910d33b1d6b68666596e863ecb897dc15ffd45d8", + "size": 5266 + }, + "series.json": { + "sha256": "8592f2df19bee6692dde1e8ee11d113b040766d2e2691da24bd1ba57e5eb1be7", + "size": 16724 + } + }, "schema": 2, "test_case_version": 2 }