anemoi-datasets 0.5.15__py3-none-any.whl → 0.5.17__py3-none-any.whl
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.
- anemoi/datasets/__init__.py +4 -1
- anemoi/datasets/__main__.py +12 -2
- anemoi/datasets/_version.py +9 -4
- anemoi/datasets/commands/cleanup.py +17 -2
- anemoi/datasets/commands/compare.py +18 -2
- anemoi/datasets/commands/copy.py +196 -14
- anemoi/datasets/commands/create.py +50 -7
- anemoi/datasets/commands/finalise-additions.py +17 -2
- anemoi/datasets/commands/finalise.py +17 -2
- anemoi/datasets/commands/init-additions.py +17 -2
- anemoi/datasets/commands/init.py +16 -2
- anemoi/datasets/commands/inspect.py +283 -62
- anemoi/datasets/commands/load-additions.py +16 -2
- anemoi/datasets/commands/load.py +16 -2
- anemoi/datasets/commands/patch.py +17 -2
- anemoi/datasets/commands/publish.py +17 -2
- anemoi/datasets/commands/scan.py +31 -3
- anemoi/datasets/compute/recentre.py +47 -11
- anemoi/datasets/create/__init__.py +612 -85
- anemoi/datasets/create/check.py +142 -20
- anemoi/datasets/create/chunks.py +64 -4
- anemoi/datasets/create/config.py +185 -21
- anemoi/datasets/create/filter.py +50 -0
- anemoi/datasets/create/filters/__init__.py +33 -0
- anemoi/datasets/create/filters/empty.py +37 -0
- anemoi/datasets/create/filters/legacy.py +93 -0
- anemoi/datasets/create/filters/noop.py +37 -0
- anemoi/datasets/create/filters/orog_to_z.py +58 -0
- anemoi/datasets/create/{functions/filters → filters}/pressure_level_relative_humidity_to_specific_humidity.py +33 -10
- anemoi/datasets/create/{functions/filters → filters}/pressure_level_specific_humidity_to_relative_humidity.py +32 -8
- anemoi/datasets/create/filters/rename.py +205 -0
- anemoi/datasets/create/{functions/filters → filters}/rotate_winds.py +43 -28
- anemoi/datasets/create/{functions/filters → filters}/single_level_dewpoint_to_relative_humidity.py +32 -9
- anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_dewpoint.py +33 -9
- anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_specific_humidity.py +55 -7
- anemoi/datasets/create/{functions/filters → filters}/single_level_specific_humidity_to_relative_humidity.py +98 -37
- anemoi/datasets/create/filters/speeddir_to_uv.py +95 -0
- anemoi/datasets/create/{functions/filters → filters}/sum.py +24 -27
- anemoi/datasets/create/filters/transform.py +53 -0
- anemoi/datasets/create/{functions/filters → filters}/unrotate_winds.py +27 -18
- anemoi/datasets/create/filters/uv_to_speeddir.py +94 -0
- anemoi/datasets/create/{functions/filters → filters}/wz_to_w.py +51 -33
- anemoi/datasets/create/input/__init__.py +76 -5
- anemoi/datasets/create/input/action.py +149 -13
- anemoi/datasets/create/input/concat.py +81 -10
- anemoi/datasets/create/input/context.py +39 -4
- anemoi/datasets/create/input/data_sources.py +72 -6
- anemoi/datasets/create/input/empty.py +21 -3
- anemoi/datasets/create/input/filter.py +60 -12
- anemoi/datasets/create/input/function.py +154 -37
- anemoi/datasets/create/input/join.py +86 -14
- anemoi/datasets/create/input/misc.py +67 -17
- anemoi/datasets/create/input/pipe.py +33 -6
- anemoi/datasets/create/input/repeated_dates.py +189 -41
- anemoi/datasets/create/input/result.py +202 -87
- anemoi/datasets/create/input/step.py +119 -22
- anemoi/datasets/create/input/template.py +100 -13
- anemoi/datasets/create/input/trace.py +62 -7
- anemoi/datasets/create/patch.py +52 -4
- anemoi/datasets/create/persistent.py +134 -17
- anemoi/datasets/create/size.py +15 -1
- anemoi/datasets/create/source.py +51 -0
- anemoi/datasets/create/sources/__init__.py +36 -0
- anemoi/datasets/create/{functions/sources → sources}/accumulations.py +296 -30
- anemoi/datasets/create/{functions/sources → sources}/constants.py +27 -2
- anemoi/datasets/create/{functions/sources → sources}/eccc_fstd.py +7 -3
- anemoi/datasets/create/sources/empty.py +37 -0
- anemoi/datasets/create/{functions/sources → sources}/forcings.py +25 -1
- anemoi/datasets/create/sources/grib.py +297 -0
- anemoi/datasets/create/{functions/sources → sources}/hindcasts.py +38 -4
- anemoi/datasets/create/sources/legacy.py +93 -0
- anemoi/datasets/create/{functions/sources → sources}/mars.py +168 -20
- anemoi/datasets/create/sources/netcdf.py +42 -0
- anemoi/datasets/create/sources/opendap.py +43 -0
- anemoi/datasets/create/{functions/sources/__init__.py → sources/patterns.py} +35 -4
- anemoi/datasets/create/sources/recentre.py +150 -0
- anemoi/datasets/create/{functions/sources → sources}/source.py +27 -5
- anemoi/datasets/create/{functions/sources → sources}/tendencies.py +64 -7
- anemoi/datasets/create/sources/xarray.py +92 -0
- anemoi/datasets/create/sources/xarray_kerchunk.py +36 -0
- anemoi/datasets/create/sources/xarray_support/README.md +1 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/__init__.py +109 -8
- anemoi/datasets/create/sources/xarray_support/coordinates.py +442 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/field.py +94 -16
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/fieldlist.py +90 -25
- anemoi/datasets/create/sources/xarray_support/flavour.py +1036 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/grid.py +92 -31
- anemoi/datasets/create/sources/xarray_support/metadata.py +395 -0
- anemoi/datasets/create/sources/xarray_support/patch.py +91 -0
- anemoi/datasets/create/sources/xarray_support/time.py +391 -0
- anemoi/datasets/create/sources/xarray_support/variable.py +331 -0
- anemoi/datasets/create/sources/xarray_zarr.py +41 -0
- anemoi/datasets/create/{functions/sources → sources}/zenodo.py +34 -5
- anemoi/datasets/create/statistics/__init__.py +233 -44
- anemoi/datasets/create/statistics/summary.py +52 -6
- anemoi/datasets/create/testing.py +76 -0
- anemoi/datasets/create/{functions/filters/noop.py → typing.py} +6 -3
- anemoi/datasets/create/utils.py +97 -6
- anemoi/datasets/create/writer.py +26 -4
- anemoi/datasets/create/zarr.py +170 -23
- anemoi/datasets/data/__init__.py +51 -4
- anemoi/datasets/data/complement.py +191 -40
- anemoi/datasets/data/concat.py +141 -16
- anemoi/datasets/data/dataset.py +552 -61
- anemoi/datasets/data/debug.py +197 -26
- anemoi/datasets/data/ensemble.py +93 -8
- anemoi/datasets/data/fill_missing.py +165 -18
- anemoi/datasets/data/forwards.py +428 -56
- anemoi/datasets/data/grids.py +323 -97
- anemoi/datasets/data/indexing.py +112 -19
- anemoi/datasets/data/interpolate.py +92 -12
- anemoi/datasets/data/join.py +158 -19
- anemoi/datasets/data/masked.py +129 -15
- anemoi/datasets/data/merge.py +137 -23
- anemoi/datasets/data/misc.py +172 -16
- anemoi/datasets/data/missing.py +233 -29
- anemoi/datasets/data/rescale.py +111 -10
- anemoi/datasets/data/select.py +168 -26
- anemoi/datasets/data/statistics.py +67 -6
- anemoi/datasets/data/stores.py +149 -64
- anemoi/datasets/data/subset.py +159 -25
- anemoi/datasets/data/unchecked.py +168 -57
- anemoi/datasets/data/xy.py +168 -25
- anemoi/datasets/dates/__init__.py +191 -16
- anemoi/datasets/dates/groups.py +189 -47
- anemoi/datasets/grids.py +270 -31
- anemoi/datasets/testing.py +28 -1
- {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/METADATA +10 -7
- anemoi_datasets-0.5.17.dist-info/RECORD +137 -0
- {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/WHEEL +1 -1
- {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info/licenses}/LICENSE +1 -1
- anemoi/datasets/create/functions/__init__.py +0 -66
- anemoi/datasets/create/functions/filters/__init__.py +0 -9
- anemoi/datasets/create/functions/filters/empty.py +0 -17
- anemoi/datasets/create/functions/filters/orog_to_z.py +0 -58
- anemoi/datasets/create/functions/filters/rename.py +0 -79
- anemoi/datasets/create/functions/filters/speeddir_to_uv.py +0 -78
- anemoi/datasets/create/functions/filters/uv_to_speeddir.py +0 -56
- anemoi/datasets/create/functions/sources/empty.py +0 -15
- anemoi/datasets/create/functions/sources/grib.py +0 -150
- anemoi/datasets/create/functions/sources/netcdf.py +0 -15
- anemoi/datasets/create/functions/sources/opendap.py +0 -15
- anemoi/datasets/create/functions/sources/recentre.py +0 -60
- anemoi/datasets/create/functions/sources/xarray/coordinates.py +0 -255
- anemoi/datasets/create/functions/sources/xarray/flavour.py +0 -472
- anemoi/datasets/create/functions/sources/xarray/metadata.py +0 -148
- anemoi/datasets/create/functions/sources/xarray/patch.py +0 -44
- anemoi/datasets/create/functions/sources/xarray/time.py +0 -177
- anemoi/datasets/create/functions/sources/xarray/variable.py +0 -188
- anemoi/datasets/create/functions/sources/xarray_kerchunk.py +0 -42
- anemoi/datasets/create/functions/sources/xarray_zarr.py +0 -15
- anemoi/datasets/utils/fields.py +0 -47
- anemoi_datasets-0.5.15.dist-info/RECORD +0 -129
- {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/entry_points.txt +0 -0
- {anemoi_datasets-0.5.15.dist-info → anemoi_datasets-0.5.17.dist-info}/top_level.txt +0 -0
|
@@ -11,9 +11,14 @@
|
|
|
11
11
|
import datetime
|
|
12
12
|
import logging
|
|
13
13
|
from functools import cached_property
|
|
14
|
+
from typing import Any
|
|
15
|
+
from typing import Dict
|
|
16
|
+
from typing import Optional
|
|
17
|
+
from typing import Tuple
|
|
14
18
|
|
|
15
|
-
from earthkit.data
|
|
19
|
+
from earthkit.data import Field
|
|
16
20
|
from earthkit.data.core.fieldlist import math
|
|
21
|
+
from numpy.typing import NDArray
|
|
17
22
|
|
|
18
23
|
from .coordinates import extract_single_value
|
|
19
24
|
from .coordinates import is_scalar
|
|
@@ -23,19 +28,41 @@ LOG = logging.getLogger(__name__)
|
|
|
23
28
|
|
|
24
29
|
|
|
25
30
|
class EmptyFieldList:
|
|
26
|
-
|
|
31
|
+
"""A class to represent an empty list of fields."""
|
|
32
|
+
|
|
33
|
+
def __len__(self) -> int:
|
|
34
|
+
"""Return the length of the field list."""
|
|
27
35
|
return 0
|
|
28
36
|
|
|
29
|
-
def __getitem__(self, i):
|
|
37
|
+
def __getitem__(self, i: int) -> Any:
|
|
38
|
+
"""Raise an IndexError when trying to access an item.
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
Any
|
|
43
|
+
This method does not return anything as it raises an IndexError.
|
|
44
|
+
|
|
45
|
+
Raises
|
|
46
|
+
------
|
|
47
|
+
IndexError
|
|
48
|
+
Always raised to indicate that the list is empty.
|
|
49
|
+
|
|
50
|
+
Args
|
|
51
|
+
----
|
|
52
|
+
i : int
|
|
53
|
+
Index of the item to access.
|
|
54
|
+
"""
|
|
30
55
|
raise IndexError(i)
|
|
31
56
|
|
|
32
57
|
def __repr__(self) -> str:
|
|
58
|
+
"""Return a string representation of the EmptyFieldList."""
|
|
33
59
|
return "EmptyFieldList()"
|
|
34
60
|
|
|
35
61
|
|
|
36
62
|
class XArrayField(Field):
|
|
63
|
+
"""A class to represent a field in an XArray dataset."""
|
|
37
64
|
|
|
38
|
-
def __init__(self, owner, selection):
|
|
65
|
+
def __init__(self, owner: Any, selection: Any) -> None:
|
|
39
66
|
"""Create a new XArrayField object.
|
|
40
67
|
|
|
41
68
|
Parameters
|
|
@@ -69,10 +96,29 @@ class XArrayField(Field):
|
|
|
69
96
|
raise ValueError("Invalid shape for selection")
|
|
70
97
|
|
|
71
98
|
@property
|
|
72
|
-
def shape(self):
|
|
99
|
+
def shape(self) -> Tuple[int, int]:
|
|
100
|
+
"""Return the shape of the field."""
|
|
73
101
|
return self._shape
|
|
74
102
|
|
|
75
|
-
def to_numpy(
|
|
103
|
+
def to_numpy(
|
|
104
|
+
self, flatten: bool = False, dtype: Optional[type] = None, index: Optional[int] = None
|
|
105
|
+
) -> NDArray[Any]:
|
|
106
|
+
"""Convert the selection to a numpy array.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
NDArray[Any]
|
|
111
|
+
The selection converted to a numpy array.
|
|
112
|
+
|
|
113
|
+
Args
|
|
114
|
+
----
|
|
115
|
+
flatten : bool, optional
|
|
116
|
+
Whether to flatten the array, by default False.
|
|
117
|
+
dtype : Optional[type], optional
|
|
118
|
+
Data type of the array, by default None.
|
|
119
|
+
index : Optional[int], optional
|
|
120
|
+
Index to select a specific element, by default None.
|
|
121
|
+
"""
|
|
76
122
|
if index is not None:
|
|
77
123
|
values = self.selection[index]
|
|
78
124
|
else:
|
|
@@ -86,34 +132,53 @@ class XArrayField(Field):
|
|
|
86
132
|
return values # .reshape(self.shape)
|
|
87
133
|
|
|
88
134
|
@cached_property
|
|
89
|
-
def _metadata(self):
|
|
135
|
+
def _metadata(self) -> XArrayMetadata:
|
|
136
|
+
"""Return the metadata of the field."""
|
|
90
137
|
return XArrayMetadata(self)
|
|
91
138
|
|
|
92
|
-
def grid_points(self):
|
|
139
|
+
def grid_points(self) -> Any:
|
|
140
|
+
"""Return the grid points of the field."""
|
|
93
141
|
return self.owner.grid_points()
|
|
94
142
|
|
|
95
|
-
def to_latlon(self, flatten=True):
|
|
143
|
+
def to_latlon(self, flatten: bool = True) -> Dict[str, Any]:
|
|
144
|
+
"""Convert the selection to latitude and longitude coordinates.
|
|
145
|
+
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
Dict[str, Any]
|
|
149
|
+
The latitude and longitude coordinates.
|
|
150
|
+
|
|
151
|
+
Args
|
|
152
|
+
----
|
|
153
|
+
flatten : bool, optional
|
|
154
|
+
Whether to flatten the coordinates, by default True.
|
|
155
|
+
"""
|
|
96
156
|
assert flatten
|
|
97
157
|
return dict(lat=self.latitudes, lon=self.longitudes)
|
|
98
158
|
|
|
99
159
|
@property
|
|
100
|
-
def resolution(self):
|
|
160
|
+
def resolution(self) -> Optional[Any]:
|
|
161
|
+
"""Return the resolution of the field."""
|
|
101
162
|
return None
|
|
102
163
|
|
|
103
164
|
@property
|
|
104
|
-
def grid_mapping(self):
|
|
165
|
+
def grid_mapping(self) -> Any:
|
|
166
|
+
"""Return the grid mapping of the field."""
|
|
105
167
|
return self.owner.grid_mapping
|
|
106
168
|
|
|
107
169
|
@property
|
|
108
|
-
def latitudes(self):
|
|
170
|
+
def latitudes(self) -> Any:
|
|
171
|
+
"""Return the latitudes of the field."""
|
|
109
172
|
return self.owner.latitudes
|
|
110
173
|
|
|
111
174
|
@property
|
|
112
|
-
def longitudes(self):
|
|
175
|
+
def longitudes(self) -> Any:
|
|
176
|
+
"""Return the longitudes of the field."""
|
|
113
177
|
return self.owner.longitudes
|
|
114
178
|
|
|
115
179
|
@property
|
|
116
|
-
def forecast_reference_time(self):
|
|
180
|
+
def forecast_reference_time(self) -> datetime.datetime:
|
|
181
|
+
"""Return the forecast reference time of the field."""
|
|
117
182
|
date, time = self.metadata("date", "time")
|
|
118
183
|
assert len(time) == 4, time
|
|
119
184
|
assert len(date) == 8, date
|
|
@@ -121,9 +186,22 @@ class XArrayField(Field):
|
|
|
121
186
|
time = int(time) // 100
|
|
122
187
|
return datetime.datetime(yyyymmdd // 10000, yyyymmdd // 100 % 100, yyyymmdd % 100, time)
|
|
123
188
|
|
|
124
|
-
def __repr__(self):
|
|
189
|
+
def __repr__(self) -> str:
|
|
190
|
+
"""Return a string representation of the field."""
|
|
125
191
|
return repr(self._metadata)
|
|
126
192
|
|
|
127
|
-
def _values(self, dtype=None):
|
|
193
|
+
def _values(self, dtype: Optional[type] = None) -> Any:
|
|
194
|
+
"""Return the values of the selection.
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
Any
|
|
199
|
+
The values of the selection.
|
|
200
|
+
|
|
201
|
+
Args
|
|
202
|
+
----
|
|
203
|
+
dtype : Optional[type], optional
|
|
204
|
+
Data type of the values, by default None.
|
|
205
|
+
"""
|
|
128
206
|
# we don't use .values as this will download the data
|
|
129
207
|
return self.selection
|
|
@@ -10,9 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
12
|
import logging
|
|
13
|
+
from typing import Any
|
|
14
|
+
from typing import Dict
|
|
15
|
+
from typing import List
|
|
16
|
+
from typing import Optional
|
|
17
|
+
from typing import Union
|
|
13
18
|
|
|
19
|
+
import xarray as xr
|
|
14
20
|
import yaml
|
|
15
|
-
from earthkit.data
|
|
21
|
+
from earthkit.data import FieldList
|
|
16
22
|
|
|
17
23
|
from .field import EmptyFieldList
|
|
18
24
|
from .flavour import CoordinateGuesser
|
|
@@ -25,19 +31,49 @@ LOG = logging.getLogger(__name__)
|
|
|
25
31
|
|
|
26
32
|
|
|
27
33
|
class XarrayFieldList(FieldList):
|
|
28
|
-
|
|
29
|
-
self.ds = ds
|
|
30
|
-
self.variables = variables.copy()
|
|
31
|
-
self.total_length = sum(v.length for v in variables)
|
|
34
|
+
"""A class to represent a list of fields from an xarray Dataset."""
|
|
32
35
|
|
|
33
|
-
def
|
|
36
|
+
def __init__(self, ds: xr.Dataset, variables: List[Variable]) -> None:
|
|
37
|
+
"""Initialize the XarrayFieldList.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
ds : xr.Dataset
|
|
42
|
+
The xarray Dataset.
|
|
43
|
+
variables : List[Variable]
|
|
44
|
+
The list of variables.
|
|
45
|
+
"""
|
|
46
|
+
self.ds: xr.Dataset = ds
|
|
47
|
+
self.variables: List[Variable] = variables.copy()
|
|
48
|
+
self.total_length: int = sum(v.length for v in variables)
|
|
49
|
+
|
|
50
|
+
def __repr__(self) -> str:
|
|
51
|
+
"""Return a string representation of the XarrayFieldList."""
|
|
34
52
|
return f"XarrayFieldList({self.total_length})"
|
|
35
53
|
|
|
36
|
-
def __len__(self):
|
|
54
|
+
def __len__(self) -> int:
|
|
55
|
+
"""Return the length of the XarrayFieldList."""
|
|
37
56
|
return self.total_length
|
|
38
57
|
|
|
39
|
-
def __getitem__(self, i):
|
|
40
|
-
|
|
58
|
+
def __getitem__(self, i: int) -> Any:
|
|
59
|
+
"""Get an item from the XarrayFieldList by index.
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
i : int
|
|
64
|
+
The index of the item to get.
|
|
65
|
+
|
|
66
|
+
Returns
|
|
67
|
+
-------
|
|
68
|
+
Any
|
|
69
|
+
The item at the specified index.
|
|
70
|
+
|
|
71
|
+
Raises
|
|
72
|
+
------
|
|
73
|
+
IndexError
|
|
74
|
+
If the index is out of range.
|
|
75
|
+
"""
|
|
76
|
+
k: int = i
|
|
41
77
|
|
|
42
78
|
if i < 0:
|
|
43
79
|
i = self.total_length + i
|
|
@@ -50,12 +86,33 @@ class XarrayFieldList(FieldList):
|
|
|
50
86
|
raise IndexError(k)
|
|
51
87
|
|
|
52
88
|
@classmethod
|
|
53
|
-
def from_xarray(
|
|
89
|
+
def from_xarray(
|
|
90
|
+
cls,
|
|
91
|
+
ds: xr.Dataset,
|
|
92
|
+
*,
|
|
93
|
+
flavour: Optional[Union[str, Dict[str, Any]]] = None,
|
|
94
|
+
patch: Optional[Dict[str, Any]] = None,
|
|
95
|
+
) -> "XarrayFieldList":
|
|
96
|
+
"""Create an XarrayFieldList from an xarray Dataset.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
ds : xr.Dataset
|
|
101
|
+
The xarray Dataset to create the field list from.
|
|
102
|
+
flavour : Optional[Union[str, Dict[str, Any]]], optional
|
|
103
|
+
The flavour to use for guessing coordinates.
|
|
104
|
+
patch : Optional[Dict[str, Any]], optional
|
|
105
|
+
The patch to apply to the dataset.
|
|
54
106
|
|
|
107
|
+
Returns
|
|
108
|
+
-------
|
|
109
|
+
XarrayFieldList
|
|
110
|
+
The created XarrayFieldList.
|
|
111
|
+
"""
|
|
55
112
|
if patch is not None:
|
|
56
113
|
ds = patch_dataset(ds, patch)
|
|
57
114
|
|
|
58
|
-
variables = []
|
|
115
|
+
variables: List[Variable] = []
|
|
59
116
|
|
|
60
117
|
if isinstance(flavour, str):
|
|
61
118
|
with open(flavour) as f:
|
|
@@ -64,9 +121,9 @@ class XarrayFieldList(FieldList):
|
|
|
64
121
|
else:
|
|
65
122
|
flavour = json.load(f)
|
|
66
123
|
|
|
67
|
-
if isinstance(flavour,
|
|
68
|
-
flavour_coords = [coords["name"] for coords in flavour["rules"].values()]
|
|
69
|
-
ds_dims = [dim for dim in ds._dims]
|
|
124
|
+
if isinstance(flavour, Dict):
|
|
125
|
+
flavour_coords: List[str] = [coords["name"] for coords in flavour["rules"].values()]
|
|
126
|
+
ds_dims: List[str] = [dim for dim in ds._dims]
|
|
70
127
|
for dim in ds_dims:
|
|
71
128
|
if dim in flavour_coords and dim not in ds._coord_names:
|
|
72
129
|
ds = ds.assign_coords({dim: ds[dim]})
|
|
@@ -75,10 +132,10 @@ class XarrayFieldList(FieldList):
|
|
|
75
132
|
|
|
76
133
|
guess = CoordinateGuesser.from_flavour(ds, flavour)
|
|
77
134
|
|
|
78
|
-
skip = set()
|
|
135
|
+
skip: set = set()
|
|
79
136
|
|
|
80
|
-
def _skip_attr(v, attr_name):
|
|
81
|
-
attr_val = getattr(v, attr_name, "")
|
|
137
|
+
def _skip_attr(v: Any, attr_name: str) -> None:
|
|
138
|
+
attr_val: str = getattr(v, attr_name, "")
|
|
82
139
|
if isinstance(attr_val, str):
|
|
83
140
|
skip.update(attr_val.split(" "))
|
|
84
141
|
|
|
@@ -97,7 +154,7 @@ class XarrayFieldList(FieldList):
|
|
|
97
154
|
continue
|
|
98
155
|
|
|
99
156
|
variable = ds[name]
|
|
100
|
-
coordinates = []
|
|
157
|
+
coordinates: List[Any] = []
|
|
101
158
|
|
|
102
159
|
for coord in variable.coords:
|
|
103
160
|
|
|
@@ -108,7 +165,7 @@ class XarrayFieldList(FieldList):
|
|
|
108
165
|
c.is_dim = False
|
|
109
166
|
coordinates.append(c)
|
|
110
167
|
|
|
111
|
-
grid_coords = sum(1 for c in coordinates if c.is_grid and c.is_dim)
|
|
168
|
+
grid_coords: int = sum(1 for c in coordinates if c.is_grid and c.is_dim)
|
|
112
169
|
assert grid_coords <= 2
|
|
113
170
|
|
|
114
171
|
if grid_coords < 2:
|
|
@@ -128,14 +185,21 @@ class XarrayFieldList(FieldList):
|
|
|
128
185
|
|
|
129
186
|
return cls(ds, variables)
|
|
130
187
|
|
|
131
|
-
def sel(self, **kwargs):
|
|
132
|
-
"""
|
|
188
|
+
def sel(self, **kwargs: Any) -> FieldList:
|
|
189
|
+
"""Select fields from the XarrayFieldList based on criteria.
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
kwargs : dict
|
|
194
|
+
The selection criteria.
|
|
133
195
|
|
|
134
196
|
Returns
|
|
135
197
|
-------
|
|
136
198
|
FieldList
|
|
137
|
-
The new FieldList
|
|
199
|
+
The new FieldList with selected fields.
|
|
200
|
+
"""
|
|
138
201
|
|
|
202
|
+
"""
|
|
139
203
|
The algorithm is as follows:
|
|
140
204
|
1 - Use the kwargs to select the variables that match the selection (`param` or `variable`)
|
|
141
205
|
2 - For each variable, use the remaining kwargs to select the coordinates (`level`, `number`, ...)
|
|
@@ -146,19 +210,20 @@ class XarrayFieldList(FieldList):
|
|
|
146
210
|
So we get an extra chance to filter the fields by the metadata.
|
|
147
211
|
"""
|
|
148
212
|
|
|
149
|
-
variables = []
|
|
150
|
-
count = 0
|
|
213
|
+
variables: List[Variable] = []
|
|
214
|
+
count: int = 0
|
|
151
215
|
|
|
152
216
|
for v in self.variables:
|
|
153
217
|
|
|
154
218
|
# First, select matching variables
|
|
219
|
+
|
|
155
220
|
# This will consume 'param' or 'variable' from kwargs
|
|
156
221
|
# and return the rest
|
|
157
222
|
match, rest = v.match(**kwargs)
|
|
158
223
|
|
|
159
224
|
if match:
|
|
160
225
|
count += 1
|
|
161
|
-
missing = {}
|
|
226
|
+
missing: Dict[str, Any] = {}
|
|
162
227
|
|
|
163
228
|
# Select from the variable's coordinates (time, level, number, ....)
|
|
164
229
|
# This may return a new variable with a isel() slice of the selection
|