climate-ref-core 0.5.2__tar.gz → 0.5.3__tar.gz
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_core-0.5.2 → climate_ref_core-0.5.3}/PKG-INFO +3 -1
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/pyproject.toml +3 -1
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/dataset_registry.py +1 -1
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/diagnostics.py +39 -22
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/test_cmec_metric.py +9 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_dataset_registry/test_dataset_registry.py +2 -2
- climate_ref_core-0.5.3/tests/unit/test_datasets/dataset_collection_obs4mips_hash.yml +2 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_datasets.py +3 -3
- climate_ref_core-0.5.2/tests/unit/test_datasets/dataset_collection_obs4mips_hash.yml +0 -2
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/.gitignore +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/LICENCE +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/NOTICE +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/README.md +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/__init__.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/constraints.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/datasets.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/env.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/exceptions.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/executor.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/logging.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/metric_values/__init__.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/metric_values/typing.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/providers.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/py.typed +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/README.md +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/__init__.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/controlled_vocabulary.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/cv_cmip7_aft.yaml +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/metric.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/output.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/metric_values/test_typing.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/cmec_testdata/cmec_metric_sample.json +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/cmec_testdata/cmec_output_sample.json +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/cmec_testdata/cv_sample.yaml +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/cmec_testdata/test_metric_json_schema.yml +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/cmec_testdata/test_output_json_schema.yml +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/conftest.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/test_cmec_output.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/test_controlled_vocabulary.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_constraints.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_datasets/dataset_collection_hash.yml +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_datasets/metric_dataset_hash.yml +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_exceptions.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_executor.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_logging.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_metrics.py +0 -0
- {climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_providers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: climate-ref-core
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.3
|
|
4
4
|
Summary: Core library for the CMIP Rapid Evaluation Framework
|
|
5
5
|
Author-email: Jared Lewis <jared.lewis@climate-resource.com>, Mika Pflueger <mika.pflueger@climate-resource.com>, Bouwe Andela <b.andela@esciencecenter.nl>, Jiwoo Lee <lee1043@llnl.gov>, Min Xu <xum1@ornl.gov>, Nathan Collier <collierno@ornl.gov>, Dora Hegedus <dora.hegedus@stfc.ac.uk>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -18,8 +18,10 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Classifier: Topic :: Scientific/Engineering
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
20
|
Requires-Dist: attrs>=23.2.0
|
|
21
|
+
Requires-Dist: loguru>=0.7.0
|
|
21
22
|
Requires-Dist: numpy>=1.25.0
|
|
22
23
|
Requires-Dist: pandas>=2.1.0
|
|
24
|
+
Requires-Dist: pooch<2,>=1.8.0
|
|
23
25
|
Requires-Dist: pydantic>=2.10.6
|
|
24
26
|
Requires-Dist: requests
|
|
25
27
|
Requires-Dist: rich
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "climate-ref-core"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.3"
|
|
4
4
|
description = "Core library for the CMIP Rapid Evaluation Framework"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -31,6 +31,8 @@ dependencies = [
|
|
|
31
31
|
"typing_extensions",
|
|
32
32
|
"requests",
|
|
33
33
|
"rich",
|
|
34
|
+
"loguru>=0.7.0",
|
|
35
|
+
"pooch>=1.8.0,<2",
|
|
34
36
|
|
|
35
37
|
# SPEC 0000 constraints
|
|
36
38
|
# We follow [SPEC-0000](https://scientific-python.org/specs/spec-0000/)
|
|
@@ -148,7 +148,7 @@ class DatasetRegistryManager:
|
|
|
148
148
|
path=pooch.os_cache(cache_name),
|
|
149
149
|
base_url=base_url,
|
|
150
150
|
version=version,
|
|
151
|
-
retry_if_failed=
|
|
151
|
+
retry_if_failed=10,
|
|
152
152
|
env="REF_DATASET_CACHE_DIR",
|
|
153
153
|
)
|
|
154
154
|
registry.load_registry(str(importlib.resources.files(package) / resource))
|
|
@@ -5,7 +5,6 @@ Diagnostic interface
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
7
|
import pathlib
|
|
8
|
-
from abc import abstractmethod
|
|
9
8
|
from collections.abc import Iterable, Sequence
|
|
10
9
|
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
11
10
|
|
|
@@ -438,12 +437,28 @@ class AbstractDiagnostic(Protocol):
|
|
|
438
437
|
The provider that provides the diagnostic.
|
|
439
438
|
"""
|
|
440
439
|
|
|
441
|
-
def
|
|
440
|
+
def execute(self, definition: ExecutionDefinition) -> None:
|
|
442
441
|
"""
|
|
443
|
-
|
|
442
|
+
Execute the diagnostic on the given configuration.
|
|
444
443
|
|
|
445
444
|
The implementation of this method is left to the diagnostic providers.
|
|
445
|
+
The results should be written to the output directory of the execution definition.
|
|
446
|
+
These are later used to build the output bundle and the diagnostic bundle.
|
|
447
|
+
|
|
448
|
+
This may occur in a separate process (or python environment in the case of a `CommandLineDiagnostic`).
|
|
449
|
+
|
|
450
|
+
Parameters
|
|
451
|
+
----------
|
|
452
|
+
definition
|
|
453
|
+
The configuration to run the diagnostic on.
|
|
454
|
+
"""
|
|
455
|
+
...
|
|
456
|
+
|
|
457
|
+
def build_execution_result(self, definition: ExecutionDefinition) -> ExecutionResult:
|
|
458
|
+
"""
|
|
459
|
+
Build the result from running the diagnostic on the given configuration.
|
|
446
460
|
|
|
461
|
+
This can be replayed later to build the result from the output execution.
|
|
447
462
|
|
|
448
463
|
Parameters
|
|
449
464
|
----------
|
|
@@ -455,6 +470,7 @@ class AbstractDiagnostic(Protocol):
|
|
|
455
470
|
:
|
|
456
471
|
The result of running the diagnostic.
|
|
457
472
|
"""
|
|
473
|
+
...
|
|
458
474
|
|
|
459
475
|
|
|
460
476
|
class Diagnostic(AbstractDiagnostic):
|
|
@@ -506,6 +522,24 @@ class Diagnostic(AbstractDiagnostic):
|
|
|
506
522
|
def provider(self, value: DiagnosticProvider) -> None:
|
|
507
523
|
self._provider = value
|
|
508
524
|
|
|
525
|
+
def run(self, definition: ExecutionDefinition) -> ExecutionResult:
|
|
526
|
+
"""
|
|
527
|
+
Run the diagnostic on the given configuration.
|
|
528
|
+
|
|
529
|
+
This executes the diagnostic and builds the result from the output bundle.
|
|
530
|
+
|
|
531
|
+
Parameters
|
|
532
|
+
----------
|
|
533
|
+
definition
|
|
534
|
+
The configuration to run the diagnostic on.
|
|
535
|
+
"""
|
|
536
|
+
# Execute the diagnostic
|
|
537
|
+
# This may be run in a separate process (or python environment)
|
|
538
|
+
self.execute(definition)
|
|
539
|
+
|
|
540
|
+
# Build the result from the output bundle
|
|
541
|
+
return self.build_execution_result(definition)
|
|
542
|
+
|
|
509
543
|
|
|
510
544
|
class CommandLineDiagnostic(Diagnostic):
|
|
511
545
|
"""
|
|
@@ -514,7 +548,6 @@ class CommandLineDiagnostic(Diagnostic):
|
|
|
514
548
|
|
|
515
549
|
provider: CommandLineDiagnosticProvider
|
|
516
550
|
|
|
517
|
-
@abstractmethod
|
|
518
551
|
def build_cmd(self, definition: ExecutionDefinition) -> Iterable[str]:
|
|
519
552
|
"""
|
|
520
553
|
Build the command to run the diagnostic on the given configuration.
|
|
@@ -529,24 +562,9 @@ class CommandLineDiagnostic(Diagnostic):
|
|
|
529
562
|
:
|
|
530
563
|
A command that can be run with :func:`subprocess.run`.
|
|
531
564
|
"""
|
|
565
|
+
return []
|
|
532
566
|
|
|
533
|
-
|
|
534
|
-
def build_execution_result(self, definition: ExecutionDefinition) -> ExecutionResult:
|
|
535
|
-
"""
|
|
536
|
-
Build the result from running the diagnostic on the given configuration.
|
|
537
|
-
|
|
538
|
-
Parameters
|
|
539
|
-
----------
|
|
540
|
-
definition
|
|
541
|
-
The configuration to run the diagnostic on.
|
|
542
|
-
|
|
543
|
-
Returns
|
|
544
|
-
-------
|
|
545
|
-
:
|
|
546
|
-
The result of running the diagnostic.
|
|
547
|
-
"""
|
|
548
|
-
|
|
549
|
-
def run(self, definition: ExecutionDefinition) -> ExecutionResult:
|
|
567
|
+
def execute(self, definition: ExecutionDefinition) -> None:
|
|
550
568
|
"""
|
|
551
569
|
Run the diagnostic on the given configuration.
|
|
552
570
|
|
|
@@ -562,4 +580,3 @@ class CommandLineDiagnostic(Diagnostic):
|
|
|
562
580
|
"""
|
|
563
581
|
cmd = self.build_cmd(definition)
|
|
564
582
|
self.provider.run(cmd)
|
|
565
|
-
return self.build_execution_result(definition)
|
|
@@ -477,6 +477,15 @@ def test_remove():
|
|
|
477
477
|
}
|
|
478
478
|
|
|
479
479
|
|
|
480
|
+
def test_iter_results(cmec_metric):
|
|
481
|
+
assert list(cmec_metric.iter_results())
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def test_iter_results_empty(cmec_right_metric_dict):
|
|
485
|
+
cmec_metric = CMECMetric.model_validate(CMECMetric.create_template())
|
|
486
|
+
assert not list(cmec_metric.iter_results())
|
|
487
|
+
|
|
488
|
+
|
|
480
489
|
@pytest.mark.xfail(reason="No need to currently support removing deeper dimensions")
|
|
481
490
|
def test_remove_not_first(cmec_right_metric_dict):
|
|
482
491
|
remove_dimensions(cmec_right_metric_dict, ["metric"])
|
|
@@ -107,7 +107,7 @@ def test_fetch_all_files(mocker, tmp_path, symlink):
|
|
|
107
107
|
registry.fetch = mocker.MagicMock(return_value=downloaded_file)
|
|
108
108
|
|
|
109
109
|
fetch_all_files(registry, "obs4ref", tmp_path, symlink=symlink)
|
|
110
|
-
assert registry.fetch.call_count ==
|
|
110
|
+
assert registry.fetch.call_count == 36
|
|
111
111
|
|
|
112
112
|
expected_file = (
|
|
113
113
|
tmp_path / "obs4REF/MOHC/HadISST-1-1/mon/ts/gn/v20210727/ts_mon_HadISST-1-1_PCMDI_gn_187001-201907.nc"
|
|
@@ -123,4 +123,4 @@ def test_fetch_all_files_no_output(mocker):
|
|
|
123
123
|
registry.fetch = mocker.MagicMock()
|
|
124
124
|
|
|
125
125
|
fetch_all_files(registry, "obs4ref", None)
|
|
126
|
-
assert registry.fetch.call_count ==
|
|
126
|
+
assert registry.fetch.call_count == 36
|
|
@@ -120,11 +120,11 @@ class TestDatasetCollectionObs4MIPs:
|
|
|
120
120
|
assert dataset_collection_obs4mips.instance_id.equals(expected)
|
|
121
121
|
|
|
122
122
|
def test_hash(self, dataset_collection_obs4mips, obs4mips_data_catalog, data_regression):
|
|
123
|
-
|
|
124
|
-
dataset_hash = hash(DatasetCollection(
|
|
123
|
+
ts_datasets = obs4mips_data_catalog[obs4mips_data_catalog.variable_id == "ts"]
|
|
124
|
+
dataset_hash = hash(DatasetCollection(ts_datasets, "instance_id"))
|
|
125
125
|
assert isinstance(dataset_hash, int)
|
|
126
126
|
|
|
127
|
-
assert dataset_hash != hash(DatasetCollection(
|
|
127
|
+
assert dataset_hash != hash(DatasetCollection(ts_datasets.iloc[[0, 0]], "instance_id"))
|
|
128
128
|
|
|
129
129
|
# This hash will change if the data catalog changes
|
|
130
130
|
# Specifically if more tas datasets are provided
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/metric_values/__init__.py
RENAMED
|
File without changes
|
{climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/metric_values/typing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/src/climate_ref_core/pycmec/cv_cmip7_aft.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/cmec_testdata/cv_sample.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/pycmec/test_controlled_vocabulary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{climate_ref_core-0.5.2 → climate_ref_core-0.5.3}/tests/unit/test_datasets/metric_dataset_hash.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|