Skip to content

Commit f77bad1

Browse files
WIP
1 parent 0e82529 commit f77bad1

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

ci/environment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dependencies:
66
- cftime
77
- codecov
88
- dask >=2024.12
9+
- esmvalcore >=2.0.0
910
- fastprogress >=1.0.0
1011
- flaky >=3.8.0
1112
- fsspec >=2024.12

intake_esm/core.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
import warnings
66
from copy import deepcopy
77

8+
import esmvalcore.dataset
9+
10+
if typing.TYPE_CHECKING:
11+
import esmvalcore
12+
from esmvalcore.dataset import Dataset
13+
from esmvalcore.typing import FacetValue
14+
815
import dask
916
import packaging.version
1017
import xarray as xr
@@ -22,6 +29,7 @@
2229
from fastprogress.fastprogress import progress_bar
2330
from intake.catalog import Catalog
2431

32+
from ._imports import _ESMVALCORE_AVAILABLE
2533
from .cat import ESMCatalogModel
2634
from .derived import DerivedVariableRegistry, default_registry
2735
from .source import ESMDataSource
@@ -839,6 +847,53 @@ def to_dask(self, **kwargs) -> xr.Dataset:
839847
_, ds = res.popitem()
840848
return ds
841849

850+
def to_iris(
851+
self,
852+
facets: dict[FacetValue, str],
853+
cmorizer: typing.Any | None = None,
854+
**kwargs,
855+
) -> esmvalcore.dataset.Dataset:
856+
"""
857+
Convert result to an ESMValCore Dataset.
858+
859+
This is only possible if the search returned exactly one result.
860+
861+
Parameters
862+
----------
863+
facets: dict[FacetValue, str]
864+
Mapping of ESMValCore Dataset facets to their corresponding esm_datastore
865+
attributes. For example, the mapping for a dataset containing keys
866+
'activity_id', 'source_id', 'member_id', 'experiment_id' would look like:
867+
```python
868+
facets = {
869+
"activity": "activity_id",
870+
"dataset": "source_id",
871+
"ensemble": "member_id",
872+
"exp": "experiment_id",
873+
"grid": "grid_label",
874+
},
875+
```
876+
cmorize: Any, optional
877+
CMORizer to use in order to CMORize the datastore search results for
878+
the ESMValCore Dataset. Presumably this will be a callable? If not set,
879+
no CMORization will be done.
880+
kwargs: dict
881+
TBC.
882+
"""
883+
if not _ESMVALCORE_AVAILABLE:
884+
raise ImportError(
885+
'`to_iris()` requires the esmvalcore package to be installed. '
886+
'To proceed please install esmvalcore using: '
887+
' `python -m pip install esmvalcore` or `conda install -c conda-forge esmvalcore`.'
888+
)
889+
890+
if len(self) != 1: # quick check to fail more quickly if there are many results
891+
raise ValueError(
892+
f'Expected exactly one dataset. Received {len(self)} datasets. Please refine your search.'
893+
)
894+
895+
ds = Dataset(**facets)
896+
842897
def _create_derived_variables(self, datasets, skip_on_error):
843898
if len(self.derivedcat) > 0:
844899
datasets = self.derivedcat.update_datasets(

tests/test_core.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,3 +631,25 @@ def test__get_threaded(mock_get_env, threaded, ITK_ESM_THREADING, expected):
631631
intake_esm.core._get_threaded(threaded)
632632
else:
633633
assert intake_esm.core._get_threaded(threaded) == expected
634+
635+
636+
@mock.patch('intake_esm.core._ESMVALCORE_AVAILABLE', False)
637+
def test_to_iris_unavailable():
638+
cat = intake.open_esm_datastore(zarr_cat_pangeo_cmip6)
639+
cat_sub = cat.search(
640+
**dict(
641+
variable_id=['pr'],
642+
experiment_id='ssp370',
643+
activity_id='AerChemMIP',
644+
source_id='BCC-ESM1',
645+
table_id='Amon',
646+
grid_label='gn',
647+
)
648+
)
649+
with pytest.raises(ImportError, match=r'`to_iris\(\)` requires the esmvalcore package'):
650+
_ = cat_sub.to_iris(
651+
xarray_open_kwargs={
652+
'consolidated': True,
653+
'backend_kwargs': {'storage_options': {'token': 'anon'}},
654+
}
655+
)

0 commit comments

Comments
 (0)