anemoi-datasets 0.5.16__py3-none-any.whl → 0.5.18__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.
Files changed (155) hide show
  1. anemoi/datasets/__init__.py +4 -1
  2. anemoi/datasets/__main__.py +12 -2
  3. anemoi/datasets/_version.py +9 -4
  4. anemoi/datasets/commands/cleanup.py +17 -2
  5. anemoi/datasets/commands/compare.py +18 -2
  6. anemoi/datasets/commands/copy.py +196 -14
  7. anemoi/datasets/commands/create.py +50 -7
  8. anemoi/datasets/commands/finalise-additions.py +17 -2
  9. anemoi/datasets/commands/finalise.py +17 -2
  10. anemoi/datasets/commands/init-additions.py +17 -2
  11. anemoi/datasets/commands/init.py +16 -2
  12. anemoi/datasets/commands/inspect.py +283 -62
  13. anemoi/datasets/commands/load-additions.py +16 -2
  14. anemoi/datasets/commands/load.py +16 -2
  15. anemoi/datasets/commands/patch.py +17 -2
  16. anemoi/datasets/commands/publish.py +17 -2
  17. anemoi/datasets/commands/scan.py +31 -3
  18. anemoi/datasets/compute/recentre.py +47 -11
  19. anemoi/datasets/create/__init__.py +612 -85
  20. anemoi/datasets/create/check.py +142 -20
  21. anemoi/datasets/create/chunks.py +64 -4
  22. anemoi/datasets/create/config.py +185 -21
  23. anemoi/datasets/create/filter.py +50 -0
  24. anemoi/datasets/create/filters/__init__.py +33 -0
  25. anemoi/datasets/create/filters/empty.py +37 -0
  26. anemoi/datasets/create/filters/legacy.py +93 -0
  27. anemoi/datasets/create/filters/noop.py +37 -0
  28. anemoi/datasets/create/filters/orog_to_z.py +58 -0
  29. anemoi/datasets/create/{functions/filters → filters}/pressure_level_relative_humidity_to_specific_humidity.py +33 -10
  30. anemoi/datasets/create/{functions/filters → filters}/pressure_level_specific_humidity_to_relative_humidity.py +32 -8
  31. anemoi/datasets/create/filters/rename.py +205 -0
  32. anemoi/datasets/create/{functions/filters → filters}/rotate_winds.py +43 -28
  33. anemoi/datasets/create/{functions/filters → filters}/single_level_dewpoint_to_relative_humidity.py +32 -9
  34. anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_dewpoint.py +33 -9
  35. anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_specific_humidity.py +55 -7
  36. anemoi/datasets/create/{functions/filters → filters}/single_level_specific_humidity_to_relative_humidity.py +98 -37
  37. anemoi/datasets/create/filters/speeddir_to_uv.py +95 -0
  38. anemoi/datasets/create/{functions/filters → filters}/sum.py +24 -27
  39. anemoi/datasets/create/filters/transform.py +53 -0
  40. anemoi/datasets/create/{functions/filters → filters}/unrotate_winds.py +27 -18
  41. anemoi/datasets/create/filters/uv_to_speeddir.py +94 -0
  42. anemoi/datasets/create/{functions/filters → filters}/wz_to_w.py +51 -33
  43. anemoi/datasets/create/input/__init__.py +76 -5
  44. anemoi/datasets/create/input/action.py +149 -13
  45. anemoi/datasets/create/input/concat.py +81 -10
  46. anemoi/datasets/create/input/context.py +39 -4
  47. anemoi/datasets/create/input/data_sources.py +72 -6
  48. anemoi/datasets/create/input/empty.py +21 -3
  49. anemoi/datasets/create/input/filter.py +60 -12
  50. anemoi/datasets/create/input/function.py +154 -37
  51. anemoi/datasets/create/input/join.py +86 -14
  52. anemoi/datasets/create/input/misc.py +67 -17
  53. anemoi/datasets/create/input/pipe.py +33 -6
  54. anemoi/datasets/create/input/repeated_dates.py +189 -41
  55. anemoi/datasets/create/input/result.py +202 -87
  56. anemoi/datasets/create/input/step.py +119 -22
  57. anemoi/datasets/create/input/template.py +100 -13
  58. anemoi/datasets/create/input/trace.py +62 -7
  59. anemoi/datasets/create/patch.py +52 -4
  60. anemoi/datasets/create/persistent.py +134 -17
  61. anemoi/datasets/create/size.py +15 -1
  62. anemoi/datasets/create/source.py +51 -0
  63. anemoi/datasets/create/sources/__init__.py +36 -0
  64. anemoi/datasets/create/{functions/sources → sources}/accumulations.py +296 -30
  65. anemoi/datasets/create/{functions/sources → sources}/constants.py +27 -2
  66. anemoi/datasets/create/{functions/sources → sources}/eccc_fstd.py +7 -3
  67. anemoi/datasets/create/sources/empty.py +37 -0
  68. anemoi/datasets/create/{functions/sources → sources}/forcings.py +25 -1
  69. anemoi/datasets/create/sources/grib.py +297 -0
  70. anemoi/datasets/create/{functions/sources → sources}/hindcasts.py +38 -4
  71. anemoi/datasets/create/sources/legacy.py +93 -0
  72. anemoi/datasets/create/{functions/sources → sources}/mars.py +168 -20
  73. anemoi/datasets/create/sources/netcdf.py +42 -0
  74. anemoi/datasets/create/sources/opendap.py +43 -0
  75. anemoi/datasets/create/{functions/sources/__init__.py → sources/patterns.py} +35 -4
  76. anemoi/datasets/create/sources/recentre.py +150 -0
  77. anemoi/datasets/create/{functions/sources → sources}/source.py +27 -5
  78. anemoi/datasets/create/{functions/sources → sources}/tendencies.py +64 -7
  79. anemoi/datasets/create/sources/xarray.py +92 -0
  80. anemoi/datasets/create/sources/xarray_kerchunk.py +36 -0
  81. anemoi/datasets/create/sources/xarray_support/README.md +1 -0
  82. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/__init__.py +109 -8
  83. anemoi/datasets/create/sources/xarray_support/coordinates.py +442 -0
  84. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/field.py +94 -16
  85. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/fieldlist.py +90 -25
  86. anemoi/datasets/create/sources/xarray_support/flavour.py +1036 -0
  87. anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/grid.py +92 -31
  88. anemoi/datasets/create/sources/xarray_support/metadata.py +395 -0
  89. anemoi/datasets/create/sources/xarray_support/patch.py +91 -0
  90. anemoi/datasets/create/sources/xarray_support/time.py +391 -0
  91. anemoi/datasets/create/sources/xarray_support/variable.py +331 -0
  92. anemoi/datasets/create/sources/xarray_zarr.py +41 -0
  93. anemoi/datasets/create/{functions/sources → sources}/zenodo.py +34 -5
  94. anemoi/datasets/create/statistics/__init__.py +233 -44
  95. anemoi/datasets/create/statistics/summary.py +52 -6
  96. anemoi/datasets/create/testing.py +76 -0
  97. anemoi/datasets/create/{functions/filters/noop.py → typing.py} +6 -3
  98. anemoi/datasets/create/utils.py +97 -6
  99. anemoi/datasets/create/writer.py +26 -4
  100. anemoi/datasets/create/zarr.py +170 -23
  101. anemoi/datasets/data/__init__.py +51 -4
  102. anemoi/datasets/data/complement.py +191 -40
  103. anemoi/datasets/data/concat.py +141 -16
  104. anemoi/datasets/data/dataset.py +558 -62
  105. anemoi/datasets/data/debug.py +197 -26
  106. anemoi/datasets/data/ensemble.py +93 -8
  107. anemoi/datasets/data/fill_missing.py +165 -18
  108. anemoi/datasets/data/forwards.py +428 -56
  109. anemoi/datasets/data/grids.py +323 -97
  110. anemoi/datasets/data/indexing.py +112 -19
  111. anemoi/datasets/data/interpolate.py +92 -12
  112. anemoi/datasets/data/join.py +158 -19
  113. anemoi/datasets/data/masked.py +129 -15
  114. anemoi/datasets/data/merge.py +137 -23
  115. anemoi/datasets/data/misc.py +172 -16
  116. anemoi/datasets/data/missing.py +233 -29
  117. anemoi/datasets/data/rescale.py +111 -10
  118. anemoi/datasets/data/select.py +168 -26
  119. anemoi/datasets/data/statistics.py +67 -6
  120. anemoi/datasets/data/stores.py +149 -64
  121. anemoi/datasets/data/subset.py +159 -25
  122. anemoi/datasets/data/unchecked.py +168 -57
  123. anemoi/datasets/data/xy.py +168 -25
  124. anemoi/datasets/dates/__init__.py +191 -16
  125. anemoi/datasets/dates/groups.py +189 -47
  126. anemoi/datasets/grids.py +270 -31
  127. anemoi/datasets/testing.py +28 -1
  128. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/METADATA +9 -6
  129. anemoi_datasets-0.5.18.dist-info/RECORD +137 -0
  130. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/WHEEL +1 -1
  131. anemoi/datasets/create/functions/__init__.py +0 -66
  132. anemoi/datasets/create/functions/filters/__init__.py +0 -9
  133. anemoi/datasets/create/functions/filters/empty.py +0 -17
  134. anemoi/datasets/create/functions/filters/orog_to_z.py +0 -58
  135. anemoi/datasets/create/functions/filters/rename.py +0 -79
  136. anemoi/datasets/create/functions/filters/speeddir_to_uv.py +0 -78
  137. anemoi/datasets/create/functions/filters/uv_to_speeddir.py +0 -56
  138. anemoi/datasets/create/functions/sources/empty.py +0 -15
  139. anemoi/datasets/create/functions/sources/grib.py +0 -150
  140. anemoi/datasets/create/functions/sources/netcdf.py +0 -15
  141. anemoi/datasets/create/functions/sources/opendap.py +0 -15
  142. anemoi/datasets/create/functions/sources/recentre.py +0 -60
  143. anemoi/datasets/create/functions/sources/xarray/coordinates.py +0 -255
  144. anemoi/datasets/create/functions/sources/xarray/flavour.py +0 -472
  145. anemoi/datasets/create/functions/sources/xarray/metadata.py +0 -148
  146. anemoi/datasets/create/functions/sources/xarray/patch.py +0 -44
  147. anemoi/datasets/create/functions/sources/xarray/time.py +0 -177
  148. anemoi/datasets/create/functions/sources/xarray/variable.py +0 -188
  149. anemoi/datasets/create/functions/sources/xarray_kerchunk.py +0 -42
  150. anemoi/datasets/create/functions/sources/xarray_zarr.py +0 -15
  151. anemoi/datasets/utils/fields.py +0 -47
  152. anemoi_datasets-0.5.16.dist-info/RECORD +0 -129
  153. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/entry_points.txt +0 -0
  154. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info/licenses}/LICENSE +0 -0
  155. {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.18.dist-info}/top_level.txt +0 -0
@@ -8,11 +8,22 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
 
11
+ import datetime
11
12
  import logging
12
13
  from functools import cached_property
14
+ from typing import Any
15
+ from typing import Dict
16
+ from typing import List
17
+ from typing import Optional
18
+ from typing import Tuple
19
+ from typing import Union
13
20
 
14
21
  import numpy as np
22
+ from numpy.typing import NDArray
15
23
 
24
+ from .dataset import Dataset
25
+ from .dataset import FullIndex
26
+ from .dataset import TupleIndex
16
27
  from .debug import Node
17
28
  from .debug import debug_indexing
18
29
  from .forwards import Forwards
@@ -24,8 +35,23 @@ from .indexing import update_tuple
24
35
  LOG = logging.getLogger(__name__)
25
36
 
26
37
 
27
- def make_rescale(variable, rescale):
38
+ def make_rescale(
39
+ variable: str, rescale: Union[Tuple[float, float], List[str], Dict[str, float]]
40
+ ) -> Tuple[float, float]:
41
+ """Create rescale parameters (scale and offset) based on the input rescale specification.
28
42
 
43
+ Parameters
44
+ ----------
45
+ variable : str
46
+ The variable name.
47
+ rescale : Union[Tuple[float, float], List[str], Dict[str, float]]
48
+ The rescale specification.
49
+
50
+ Returns
51
+ -------
52
+ Tuple[float, float]
53
+ The scale and offset values.
54
+ """
29
55
  if isinstance(rescale, (tuple, list)):
30
56
 
31
57
  assert len(rescale) == 2, rescale
@@ -57,7 +83,20 @@ def make_rescale(variable, rescale):
57
83
 
58
84
 
59
85
  class Rescale(Forwards):
60
- def __init__(self, dataset, rescale):
86
+ """A class to apply rescaling to dataset variables."""
87
+
88
+ def __init__(
89
+ self, dataset: Dataset, rescale: Dict[str, Union[Tuple[float, float], List[str], Dict[str, float]]]
90
+ ) -> None:
91
+ """Initialize the Rescale object.
92
+
93
+ Parameters
94
+ ----------
95
+ dataset : Dataset
96
+ The dataset to be rescaled.
97
+ rescale : Dict[str, Union[Tuple[float, float], List[str], Dict[str, float]]]
98
+ The rescale specifications.
99
+ """
61
100
  super().__init__(dataset)
62
101
  for n in rescale:
63
102
  assert n in dataset.variables, n
@@ -80,15 +119,41 @@ class Rescale(Forwards):
80
119
  self._a = self._a.astype(self.forward.dtype)
81
120
  self._b = self._b.astype(self.forward.dtype)
82
121
 
83
- def tree(self):
122
+ def tree(self) -> Node:
123
+ """Get the tree representation of the rescale operation.
124
+
125
+ Returns
126
+ -------
127
+ Node
128
+ The tree representation.
129
+ """
84
130
  return Node(self, [self.forward.tree()], rescale=self.rescale)
85
131
 
86
- def subclass_metadata_specific(self):
132
+ def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
133
+ """Get the metadata specific to the rescale subclass.
134
+
135
+ Returns
136
+ -------
137
+ Dict[str, Any]
138
+ The metadata dictionary.
139
+ """
87
140
  return dict(rescale=self.rescale)
88
141
 
89
142
  @debug_indexing
90
143
  @expand_list_indexing
91
- def _get_tuple(self, index):
144
+ def _get_tuple(self, index: TupleIndex) -> NDArray[Any]:
145
+ """Get a tuple of rescaled data based on the provided index.
146
+
147
+ Parameters
148
+ ----------
149
+ index : TupleIndex
150
+ The index to retrieve data.
151
+
152
+ Returns
153
+ -------
154
+ NDArray[Any]
155
+ The rescaled data.
156
+ """
92
157
  index, changes = index_to_slices(index, self.shape)
93
158
  index, previous = update_tuple(index, 1, slice(None))
94
159
  result = self.forward[index]
@@ -98,13 +163,36 @@ class Rescale(Forwards):
98
163
  return result
99
164
 
100
165
  @debug_indexing
101
- def __get_slice_(self, n):
166
+ def __get_slice_(self, n: slice) -> NDArray[Any]:
167
+ """Get a slice of rescaled data.
168
+
169
+ Parameters
170
+ ----------
171
+ n : slice
172
+ The slice to retrieve data.
173
+
174
+ Returns
175
+ -------
176
+ NDArray[Any]
177
+ The rescaled data.
178
+ """
102
179
  data = self.forward[n]
103
180
  return data * self._a + self._b
104
181
 
105
182
  @debug_indexing
106
- def __getitem__(self, n):
107
-
183
+ def __getitem__(self, n: FullIndex) -> NDArray[Any]:
184
+ """Get an item or slice of rescaled data based on the provided index.
185
+
186
+ Parameters
187
+ ----------
188
+ n : FullIndex
189
+ The index to retrieve data.
190
+
191
+ Returns
192
+ -------
193
+ NDArray[Any]
194
+ The rescaled data.
195
+ """
108
196
  if isinstance(n, tuple):
109
197
  return self._get_tuple(n)
110
198
 
@@ -116,7 +204,8 @@ class Rescale(Forwards):
116
204
  return data * self._a[0] + self._b[0]
117
205
 
118
206
  @cached_property
119
- def statistics(self):
207
+ def statistics(self) -> Dict[str, NDArray[Any]]:
208
+ """Get the statistics of the rescaled data."""
120
209
  result = {}
121
210
  a = self._a.squeeze()
122
211
  assert np.all(a >= 0)
@@ -135,7 +224,19 @@ class Rescale(Forwards):
135
224
 
136
225
  return result
137
226
 
138
- def statistics_tendencies(self, delta=None):
227
+ def statistics_tendencies(self, delta: Optional[datetime.timedelta] = None) -> Dict[str, NDArray[Any]]:
228
+ """Get the tendencies of the statistics of the rescaled data.
229
+
230
+ Parameters
231
+ ----------
232
+ delta : Optional[datetime.timedelta]
233
+ The time delta for tendencies calculation.
234
+
235
+ Returns
236
+ -------
237
+ Dict[str, NDArray[Any]]
238
+ The tendencies statistics dictionary.
239
+ """
139
240
  result = {}
140
241
  a = self._a.squeeze()
141
242
  assert np.all(a >= 0)
@@ -8,9 +8,20 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
 
11
+ import datetime
11
12
  import logging
12
13
  from functools import cached_property
14
+ from typing import Any
15
+ from typing import Dict
16
+ from typing import List
17
+ from typing import Optional
13
18
 
19
+ from numpy.typing import NDArray
20
+
21
+ from .dataset import Dataset
22
+ from .dataset import FullIndex
23
+ from .dataset import Shape
24
+ from .dataset import TupleIndex
14
25
  from .debug import Node
15
26
  from .debug import Source
16
27
  from .debug import debug_indexing
@@ -24,10 +35,20 @@ LOG = logging.getLogger(__name__)
24
35
 
25
36
 
26
37
  class Select(Forwards):
27
- """Select a subset of the variables."""
28
-
29
- def __init__(self, dataset, indices, reason):
30
-
38
+ """Class to select a subset of variables from a dataset."""
39
+
40
+ def __init__(self, dataset: Dataset, indices: List[int], reason: Dict[str, Any]) -> None:
41
+ """Initialize the Select class.
42
+
43
+ Parameters
44
+ ----------
45
+ dataset : Dataset
46
+ The dataset to select from.
47
+ indices : List[int]
48
+ The indices of the variables to select.
49
+ reason : Dict[str, Any]
50
+ The reason for the selection.
51
+ """
31
52
  reason = reason.copy()
32
53
 
33
54
  while isinstance(dataset, Select):
@@ -35,23 +56,53 @@ class Select(Forwards):
35
56
  reason.update(dataset.reason)
36
57
  dataset = dataset.dataset
37
58
 
38
- self.dataset = dataset
59
+ self.dataset: Dataset = dataset
39
60
  self.indices = list(indices)
40
61
  assert len(self.indices) > 0
41
62
  self.reason = reason or {"indices": self.indices}
42
63
 
43
- # Forward other properties to the main dataset
44
64
  super().__init__(dataset)
45
65
 
46
- def clone(self, dataset):
66
+ def clone(self, dataset: Dataset) -> Dataset:
67
+ """Clone the Select object with a new dataset.
68
+
69
+ Parameters
70
+ ----------
71
+ dataset : Dataset
72
+ The new dataset.
73
+
74
+ Returns
75
+ -------
76
+ Select
77
+ The cloned Select object.
78
+ """
47
79
  return self.__class__(dataset, self.indices, self.reason).mutate()
48
80
 
49
- def mutate(self):
81
+ def mutate(self) -> Dataset:
82
+ """Mutate the dataset.
83
+
84
+ Returns
85
+ -------
86
+ Dataset
87
+ The mutated dataset.
88
+ """
50
89
  return self.forward.swap_with_parent(parent=self)
51
90
 
52
91
  @debug_indexing
53
92
  @expand_list_indexing
54
- def _get_tuple(self, index):
93
+ def _get_tuple(self, index: TupleIndex) -> NDArray[Any]:
94
+ """Get a tuple of data.
95
+
96
+ Parameters
97
+ ----------
98
+ index : TupleIndex
99
+ The index to retrieve.
100
+
101
+ Returns
102
+ -------
103
+ NDArray[Any]
104
+ The retrieved data.
105
+ """
55
106
  index, changes = index_to_slices(index, self.shape)
56
107
  index, previous = update_tuple(index, 1, slice(None))
57
108
  result = self.dataset[index]
@@ -61,7 +112,19 @@ class Select(Forwards):
61
112
  return result
62
113
 
63
114
  @debug_indexing
64
- def __getitem__(self, n):
115
+ def __getitem__(self, n: FullIndex) -> NDArray[Any]:
116
+ """Get an item from the dataset.
117
+
118
+ Parameters
119
+ ----------
120
+ n : FullIndex
121
+ The index to retrieve.
122
+
123
+ Returns
124
+ -------
125
+ NDArray[Any]
126
+ The retrieved data.
127
+ """
65
128
  if isinstance(n, tuple):
66
129
  return self._get_tuple(n)
67
130
 
@@ -72,46 +135,112 @@ class Select(Forwards):
72
135
  return row[self.indices]
73
136
 
74
137
  @cached_property
75
- def shape(self):
138
+ def shape(self) -> Shape:
139
+ """Get the shape of the dataset."""
76
140
  return (len(self), len(self.indices)) + self.dataset.shape[2:]
77
141
 
78
142
  @cached_property
79
- def variables(self):
143
+ def variables(self) -> List[str]:
144
+ """Get the variables of the dataset."""
80
145
  return [self.dataset.variables[i] for i in self.indices]
81
146
 
82
147
  @cached_property
83
- def variables_metadata(self):
148
+ def variables_metadata(self) -> Dict[str, Any]:
149
+ """Get the metadata of the variables."""
84
150
  return {k: v for k, v in self.dataset.variables_metadata.items() if k in self.variables}
85
151
 
86
152
  @cached_property
87
- def name_to_index(self):
153
+ def name_to_index(self) -> Dict[str, int]:
154
+ """Get the mapping of variable names to indices."""
88
155
  return {k: i for i, k in enumerate(self.variables)}
89
156
 
90
157
  @cached_property
91
- def statistics(self):
158
+ def statistics(self) -> Dict[str, NDArray[Any]]:
159
+ """Get the statistics of the dataset."""
92
160
  return {k: v[self.indices] for k, v in self.dataset.statistics.items()}
93
161
 
94
- def statistics_tendencies(self, delta=None):
162
+ def statistics_tendencies(self, delta: Optional[datetime.timedelta] = None) -> Dict[str, NDArray[Any]]:
163
+ """Get the statistical tendencies of the dataset.
164
+
165
+ Parameters
166
+ ----------
167
+ delta : Optional[datetime.timedelta]
168
+ The time delta for the tendencies.
169
+
170
+ Returns
171
+ -------
172
+ Dict[str, NDArray[Any]]
173
+ The statistical tendencies.
174
+ """
95
175
  if delta is None:
96
176
  delta = self.frequency
97
177
  return {k: v[self.indices] for k, v in self.dataset.statistics_tendencies(delta).items()}
98
178
 
99
- def metadata_specific(self, **kwargs):
179
+ def metadata_specific(self, **kwargs: Any) -> Dict[str, Any]:
180
+ """Get the specific metadata of the dataset.
181
+
182
+ Parameters
183
+ ----------
184
+ **kwargs : Any
185
+ Additional keyword arguments.
186
+
187
+ Returns
188
+ -------
189
+ Dict[str, Any]
190
+ The specific metadata.
191
+ """
100
192
  return super().metadata_specific(indices=self.indices, **kwargs)
101
193
 
102
- def source(self, index):
194
+ def source(self, index: int) -> Source:
195
+ """Get the source of the dataset.
196
+
197
+ Parameters
198
+ ----------
199
+ index : int
200
+ The index of the source.
201
+
202
+ Returns
203
+ -------
204
+ Source
205
+ The source of the dataset.
206
+ """
103
207
  return Source(self, index, self.dataset.source(self.indices[index]))
104
208
 
105
- def tree(self):
209
+ def tree(self) -> Node:
210
+ """Get the tree representation of the dataset.
211
+
212
+ Returns
213
+ -------
214
+ Node
215
+ The tree representation of the dataset.
216
+ """
106
217
  return Node(self, [self.dataset.tree()], **self.reason)
107
218
 
108
- def subclass_metadata_specific(self):
219
+ def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
220
+ """Get the metadata specific to the subclass.
221
+
222
+ Returns
223
+ -------
224
+ Dict[str, Any]
225
+ The metadata specific to the subclass.
226
+ """
109
227
  # return dict(indices=self.indices)
110
228
  return dict(reason=self.reason)
111
229
 
112
230
 
113
231
  class Rename(Forwards):
114
- def __init__(self, dataset, rename):
232
+ """Class to rename variables in a dataset."""
233
+
234
+ def __init__(self, dataset: Dataset, rename: Dict[str, str]) -> None:
235
+ """Initialize the Rename class.
236
+
237
+ Parameters
238
+ ----------
239
+ dataset : Dataset
240
+ The dataset to rename.
241
+ rename : Dict[str, str]
242
+ The mapping of old names to new names.
243
+ """
115
244
  super().__init__(dataset)
116
245
  for n in rename:
117
246
  assert n in dataset.variables, n
@@ -122,19 +251,32 @@ class Rename(Forwards):
122
251
  self.rename = rename
123
252
 
124
253
  @property
125
- def variables(self):
254
+ def variables(self) -> List[str]:
255
+ """Get the renamed variables."""
126
256
  return self._variables
127
257
 
128
258
  @property
129
- def variables_metadata(self):
259
+ def variables_metadata(self) -> Dict[str, Any]:
260
+ """Get the renamed variables metadata."""
130
261
  return self._variables_metadata
131
262
 
132
263
  @cached_property
133
- def name_to_index(self):
264
+ def name_to_index(self) -> Dict[str, int]:
265
+ """Get the mapping of renamed variable names to indices."""
134
266
  return {k: i for i, k in enumerate(self.variables)}
135
267
 
136
- def tree(self):
268
+ def tree(self) -> Node:
269
+ """Get the tree representation of the dataset.
270
+
271
+ Returns:
272
+ Node: The tree representation of the dataset.
273
+ """
137
274
  return Node(self, [self.forward.tree()], rename=self.rename)
138
275
 
139
- def subclass_metadata_specific(self):
276
+ def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
277
+ """Get the metadata specific to the subclass.
278
+
279
+ Returns:
280
+ Dict[str, Any]: The metadata specific to the subclass.
281
+ """
140
282
  return dict(rename=self.rename)
@@ -8,10 +8,18 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
 
11
+ import datetime
11
12
  import logging
12
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 Set
18
+
19
+ from numpy.typing import NDArray
13
20
 
14
21
  from . import open_dataset
22
+ from .dataset import Dataset
15
23
  from .debug import Node
16
24
  from .forwards import Forwards
17
25
 
@@ -19,7 +27,26 @@ LOG = logging.getLogger(__name__)
19
27
 
20
28
 
21
29
  class Statistics(Forwards):
22
- def __init__(self, dataset, statistic):
30
+ """A class to represent statistics for a dataset.
31
+
32
+ Attributes
33
+ ----------
34
+ dataset : Dataset
35
+ The dataset object.
36
+ statistic : Any
37
+ The statistic data.
38
+ """
39
+
40
+ def __init__(self, dataset: Dataset, statistic: Any) -> None:
41
+ """Initialize the Statistics object.
42
+
43
+ Parameters
44
+ ----------
45
+ dataset : Dataset
46
+ The dataset object.
47
+ statistic : Any
48
+ The statistic data.
49
+ """
23
50
  super().__init__(dataset)
24
51
  self._statistic = open_dataset(statistic, select=dataset.variables)
25
52
  # TODO: relax that check to allow for a subset of variables
@@ -29,20 +56,54 @@ class Statistics(Forwards):
29
56
  )
30
57
 
31
58
  @cached_property
32
- def statistics(self):
59
+ def statistics(self) -> Dict[str, NDArray[Any]]:
60
+ """Get the statistics."""
33
61
  return self._statistic.statistics
34
62
 
35
- def statistics_tendencies(self, delta=None):
63
+ def statistics_tendencies(self, delta: Optional[datetime.timedelta] = None) -> Dict[str, NDArray[Any]]:
64
+ """Get the statistics tendencies.
65
+
66
+ Parameters
67
+ ----------
68
+ delta : Optional[datetime.timedelta]
69
+ The time delta.
70
+
71
+ Returns
72
+ -------
73
+ Dict[str, NDArray[Any]]
74
+ The statistics tendencies.
75
+ """
36
76
  if delta is None:
37
77
  delta = self.frequency
38
78
  return self._statistic.statistics_tendencies(delta)
39
79
 
40
- def subclass_metadata_specific(self):
80
+ def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
81
+ """Get the metadata specific to the forwards subclass.
82
+
83
+ Returns
84
+ -------
85
+ Dict[str, Any]
86
+ The metadata specific to the forwards subclass.
87
+ """
41
88
  return dict(statistics=self._statistic.metadata_specific())
42
89
 
43
- def tree(self):
90
+ def tree(self) -> Node:
91
+ """Get the tree representation of the statistics.
92
+
93
+ Returns
94
+ -------
95
+ Node
96
+ The tree representation of the statistics.
97
+ """
44
98
  return Node(self, [self.forward.tree()])
45
99
 
46
- def get_dataset_names(self, names):
100
+ def get_dataset_names(self, names: Set[str]) -> None:
101
+ """Get the dataset names.
102
+
103
+ Parameters
104
+ ----------
105
+ names : Set[str]
106
+ The set of dataset names.
107
+ """
47
108
  super().get_dataset_names(names)
48
109
  self._statistic.get_dataset_names(names)