anemoi-datasets 0.5.26__py3-none-any.whl → 0.5.27__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 (105) hide show
  1. anemoi/datasets/__init__.py +1 -2
  2. anemoi/datasets/_version.py +16 -3
  3. anemoi/datasets/commands/check.py +1 -1
  4. anemoi/datasets/commands/copy.py +1 -2
  5. anemoi/datasets/commands/create.py +1 -1
  6. anemoi/datasets/commands/inspect.py +27 -35
  7. anemoi/datasets/commands/validate.py +59 -0
  8. anemoi/datasets/compute/recentre.py +3 -6
  9. anemoi/datasets/create/__init__.py +22 -25
  10. anemoi/datasets/create/check.py +10 -12
  11. anemoi/datasets/create/chunks.py +1 -2
  12. anemoi/datasets/create/config.py +3 -6
  13. anemoi/datasets/create/filter.py +1 -2
  14. anemoi/datasets/create/input/__init__.py +1 -2
  15. anemoi/datasets/create/input/action.py +3 -5
  16. anemoi/datasets/create/input/concat.py +5 -8
  17. anemoi/datasets/create/input/context.py +3 -6
  18. anemoi/datasets/create/input/data_sources.py +5 -8
  19. anemoi/datasets/create/input/empty.py +1 -2
  20. anemoi/datasets/create/input/filter.py +2 -3
  21. anemoi/datasets/create/input/function.py +1 -2
  22. anemoi/datasets/create/input/join.py +4 -5
  23. anemoi/datasets/create/input/misc.py +4 -6
  24. anemoi/datasets/create/input/repeated_dates.py +13 -18
  25. anemoi/datasets/create/input/result.py +29 -33
  26. anemoi/datasets/create/input/step.py +4 -8
  27. anemoi/datasets/create/input/template.py +3 -4
  28. anemoi/datasets/create/input/trace.py +1 -1
  29. anemoi/datasets/create/patch.py +1 -2
  30. anemoi/datasets/create/persistent.py +3 -5
  31. anemoi/datasets/create/size.py +1 -3
  32. anemoi/datasets/create/sources/accumulations.py +47 -52
  33. anemoi/datasets/create/sources/accumulations2.py +4 -8
  34. anemoi/datasets/create/sources/constants.py +1 -3
  35. anemoi/datasets/create/sources/empty.py +1 -2
  36. anemoi/datasets/create/sources/fdb.py +133 -0
  37. anemoi/datasets/create/sources/forcings.py +1 -2
  38. anemoi/datasets/create/sources/grib.py +6 -10
  39. anemoi/datasets/create/sources/grib_index.py +13 -15
  40. anemoi/datasets/create/sources/hindcasts.py +2 -5
  41. anemoi/datasets/create/sources/legacy.py +1 -1
  42. anemoi/datasets/create/sources/mars.py +17 -21
  43. anemoi/datasets/create/sources/netcdf.py +1 -2
  44. anemoi/datasets/create/sources/opendap.py +1 -3
  45. anemoi/datasets/create/sources/patterns.py +4 -6
  46. anemoi/datasets/create/sources/recentre.py +8 -11
  47. anemoi/datasets/create/sources/source.py +3 -6
  48. anemoi/datasets/create/sources/tendencies.py +2 -5
  49. anemoi/datasets/create/sources/xarray.py +4 -6
  50. anemoi/datasets/create/sources/xarray_support/__init__.py +12 -13
  51. anemoi/datasets/create/sources/xarray_support/coordinates.py +8 -12
  52. anemoi/datasets/create/sources/xarray_support/field.py +16 -12
  53. anemoi/datasets/create/sources/xarray_support/fieldlist.py +11 -15
  54. anemoi/datasets/create/sources/xarray_support/flavour.py +42 -42
  55. anemoi/datasets/create/sources/xarray_support/grid.py +15 -9
  56. anemoi/datasets/create/sources/xarray_support/metadata.py +19 -128
  57. anemoi/datasets/create/sources/xarray_support/patch.py +4 -6
  58. anemoi/datasets/create/sources/xarray_support/time.py +10 -13
  59. anemoi/datasets/create/sources/xarray_support/variable.py +21 -21
  60. anemoi/datasets/create/sources/xarray_zarr.py +1 -2
  61. anemoi/datasets/create/sources/zenodo.py +3 -5
  62. anemoi/datasets/create/statistics/__init__.py +3 -6
  63. anemoi/datasets/create/testing.py +4 -0
  64. anemoi/datasets/create/typing.py +1 -2
  65. anemoi/datasets/create/utils.py +1 -2
  66. anemoi/datasets/create/zarr.py +7 -2
  67. anemoi/datasets/data/__init__.py +15 -6
  68. anemoi/datasets/data/complement.py +7 -12
  69. anemoi/datasets/data/concat.py +5 -8
  70. anemoi/datasets/data/dataset.py +42 -47
  71. anemoi/datasets/data/debug.py +7 -9
  72. anemoi/datasets/data/ensemble.py +4 -6
  73. anemoi/datasets/data/fill_missing.py +7 -10
  74. anemoi/datasets/data/forwards.py +22 -26
  75. anemoi/datasets/data/grids.py +12 -16
  76. anemoi/datasets/data/indexing.py +9 -12
  77. anemoi/datasets/data/interpolate.py +7 -15
  78. anemoi/datasets/data/join.py +8 -12
  79. anemoi/datasets/data/masked.py +6 -11
  80. anemoi/datasets/data/merge.py +5 -9
  81. anemoi/datasets/data/misc.py +41 -45
  82. anemoi/datasets/data/missing.py +11 -16
  83. anemoi/datasets/data/observations/__init__.py +8 -14
  84. anemoi/datasets/data/padded.py +3 -5
  85. anemoi/datasets/data/records/backends/__init__.py +2 -2
  86. anemoi/datasets/data/rescale.py +5 -12
  87. anemoi/datasets/data/select.py +13 -16
  88. anemoi/datasets/data/statistics.py +4 -7
  89. anemoi/datasets/data/stores.py +16 -21
  90. anemoi/datasets/data/subset.py +8 -11
  91. anemoi/datasets/data/unchecked.py +7 -11
  92. anemoi/datasets/data/xy.py +25 -21
  93. anemoi/datasets/dates/__init__.py +13 -18
  94. anemoi/datasets/dates/groups.py +7 -10
  95. anemoi/datasets/grids.py +5 -9
  96. anemoi/datasets/testing.py +93 -7
  97. anemoi/datasets/validate.py +598 -0
  98. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/METADATA +4 -4
  99. anemoi_datasets-0.5.27.dist-info/RECORD +134 -0
  100. anemoi/datasets/utils/__init__.py +0 -8
  101. anemoi_datasets-0.5.26.dist-info/RECORD +0 -131
  102. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/WHEEL +0 -0
  103. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/entry_points.txt +0 -0
  104. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/licenses/LICENSE +0 -0
  105. {anemoi_datasets-0.5.26.dist-info → anemoi_datasets-0.5.27.dist-info}/top_level.txt +0 -0
@@ -14,10 +14,6 @@ import warnings
14
14
  from abc import abstractmethod
15
15
  from functools import cached_property
16
16
  from typing import Any
17
- from typing import Dict
18
- from typing import List
19
- from typing import Optional
20
- from typing import Set
21
17
 
22
18
  import numpy as np
23
19
  from numpy.typing import NDArray
@@ -75,7 +71,7 @@ class Forwards(Dataset):
75
71
  return self.forward[n]
76
72
 
77
73
  @property
78
- def name(self) -> Optional[str]:
74
+ def name(self) -> str | None:
79
75
  """Returns the name of the forward dataset."""
80
76
  if self._name is not None:
81
77
  return self._name
@@ -112,26 +108,26 @@ class Forwards(Dataset):
112
108
  return self.forward.longitudes
113
109
 
114
110
  @property
115
- def name_to_index(self) -> Dict[str, int]:
111
+ def name_to_index(self) -> dict[str, int]:
116
112
  """Returns a dictionary mapping variable names to their indices."""
117
113
  return self.forward.name_to_index
118
114
 
119
115
  @property
120
- def variables(self) -> List[str]:
116
+ def variables(self) -> list[str]:
121
117
  """Returns the variables of the forward dataset."""
122
118
  return self.forward.variables
123
119
 
124
120
  @property
125
- def variables_metadata(self) -> Dict[str, Any]:
121
+ def variables_metadata(self) -> dict[str, Any]:
126
122
  """Returns the metadata of the variables in the forward dataset."""
127
123
  return self.forward.variables_metadata
128
124
 
129
125
  @property
130
- def statistics(self) -> Dict[str, NDArray[Any]]:
126
+ def statistics(self) -> dict[str, NDArray[Any]]:
131
127
  """Returns the statistics of the forward dataset."""
132
128
  return self.forward.statistics
133
129
 
134
- def statistics_tendencies(self, delta: Optional[datetime.timedelta] = None) -> Dict[str, NDArray[Any]]:
130
+ def statistics_tendencies(self, delta: datetime.timedelta | None = None) -> dict[str, NDArray[Any]]:
135
131
  """Returns the statistics tendencies of the forward dataset.
136
132
 
137
133
  Parameters
@@ -159,7 +155,7 @@ class Forwards(Dataset):
159
155
  return self.forward.dtype
160
156
 
161
157
  @property
162
- def missing(self) -> Set[int]:
158
+ def missing(self) -> set[int]:
163
159
  """Returns the missing data information of the forward dataset."""
164
160
  return self.forward.missing
165
161
 
@@ -168,7 +164,7 @@ class Forwards(Dataset):
168
164
  """Returns the grids of the forward dataset."""
169
165
  return self.forward.grids
170
166
 
171
- def metadata_specific(self, **kwargs: Any) -> Dict[str, Any]:
167
+ def metadata_specific(self, **kwargs: Any) -> dict[str, Any]:
172
168
  """Returns metadata specific to the forward dataset.
173
169
 
174
170
  Parameters
@@ -187,7 +183,7 @@ class Forwards(Dataset):
187
183
  **kwargs,
188
184
  )
189
185
 
190
- def collect_supporting_arrays(self, collected: List[Any], *path: Any) -> None:
186
+ def collect_supporting_arrays(self, collected: list[Any], *path: Any) -> None:
191
187
  """Collects supporting arrays from the forward dataset.
192
188
 
193
189
  Parameters
@@ -199,7 +195,7 @@ class Forwards(Dataset):
199
195
  """
200
196
  self.forward.collect_supporting_arrays(collected, *path)
201
197
 
202
- def collect_input_sources(self, collected: List[Any]) -> None:
198
+ def collect_input_sources(self, collected: list[Any]) -> None:
203
199
  """Collects input sources from the forward dataset.
204
200
 
205
201
  Parameters
@@ -225,11 +221,11 @@ class Forwards(Dataset):
225
221
  return self.forward.source(index)
226
222
 
227
223
  @abstractmethod
228
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
224
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
229
225
  """Returns metadata specific to the subclass."""
230
226
  pass
231
227
 
232
- def get_dataset_names(self, names: Set[str]) -> None:
228
+ def get_dataset_names(self, names: set[str]) -> None:
233
229
  """Collects the names of the datasets.
234
230
 
235
231
  Parameters
@@ -240,7 +236,7 @@ class Forwards(Dataset):
240
236
  self.forward.get_dataset_names(names)
241
237
 
242
238
  @property
243
- def constant_fields(self) -> List[str]:
239
+ def constant_fields(self) -> list[str]:
244
240
  """Returns the constant fields of the forward dataset."""
245
241
  return self.forward.constant_fields
246
242
 
@@ -248,7 +244,7 @@ class Forwards(Dataset):
248
244
  class Combined(Forwards):
249
245
  """A class to combine multiple datasets into a single dataset."""
250
246
 
251
- def __init__(self, datasets: List[Dataset]) -> None:
247
+ def __init__(self, datasets: list[Dataset]) -> None:
252
248
  """Initializes a Combined object.
253
249
 
254
250
  Parameters
@@ -466,7 +462,7 @@ class Combined(Forwards):
466
462
  self.check_same_variables(d1, d2)
467
463
  self.check_same_dates(d1, d2)
468
464
 
469
- def provenance(self) -> List[Any]:
465
+ def provenance(self) -> list[Any]:
470
466
  """Returns the provenance of the combined datasets.
471
467
 
472
468
  Returns
@@ -487,7 +483,7 @@ class Combined(Forwards):
487
483
  lst = ", ".join(repr(d) for d in self.datasets)
488
484
  return f"{self.__class__.__name__}({lst})"
489
485
 
490
- def metadata_specific(self, **kwargs: Any) -> Dict[str, Any]:
486
+ def metadata_specific(self, **kwargs: Any) -> dict[str, Any]:
491
487
  """Returns metadata specific to the combined datasets.
492
488
 
493
489
  Parameters
@@ -508,7 +504,7 @@ class Combined(Forwards):
508
504
  **kwargs,
509
505
  )
510
506
 
511
- def collect_supporting_arrays(self, collected: List[Any], *path: Any) -> None:
507
+ def collect_supporting_arrays(self, collected: list[Any], *path: Any) -> None:
512
508
  """Collects supporting arrays from the combined datasets.
513
509
 
514
510
  Parameters
@@ -524,7 +520,7 @@ class Combined(Forwards):
524
520
  d.collect_supporting_arrays(collected, *path, name)
525
521
 
526
522
  @property
527
- def missing(self) -> Set[int]:
523
+ def missing(self) -> set[int]:
528
524
  """Returns the missing data information of the combined datasets.
529
525
 
530
526
  Raises
@@ -534,7 +530,7 @@ class Combined(Forwards):
534
530
  """
535
531
  raise NotImplementedError("missing() not implemented for Combined")
536
532
 
537
- def get_dataset_names(self, names: Set[str]) -> None:
533
+ def get_dataset_names(self, names: set[str]) -> None:
538
534
  """Collects the names of the combined datasets.
539
535
 
540
536
  Parameters
@@ -549,7 +545,7 @@ class Combined(Forwards):
549
545
  class GivenAxis(Combined):
550
546
  """A class to combine datasets along a given axis."""
551
547
 
552
- def __init__(self, datasets: List[Any], axis: int) -> None:
548
+ def __init__(self, datasets: list[Any], axis: int) -> None:
553
549
  """Initializes a GivenAxis object.
554
550
 
555
551
  Parameters
@@ -656,10 +652,10 @@ class GivenAxis(Combined):
656
652
  return np.concatenate([d[n] for d in self.datasets], axis=self.axis - 1)
657
653
 
658
654
  @cached_property
659
- def missing(self) -> Set[int]:
655
+ def missing(self) -> set[int]:
660
656
  """Returns the missing data information of the combined dataset along the given axis."""
661
657
  offset = 0
662
- result: Set[int] = set()
658
+ result: set[int] = set()
663
659
  for d in self.datasets:
664
660
  result.update(offset + m for m in d.missing)
665
661
  if self.axis == 0: # Advance if axis is time
@@ -11,10 +11,6 @@
11
11
  import logging
12
12
  from functools import cached_property
13
13
  from typing import Any
14
- from typing import Dict
15
- from typing import List
16
- from typing import Optional
17
- from typing import Tuple
18
14
 
19
15
  import numpy as np
20
16
  from numpy.typing import NDArray
@@ -189,7 +185,7 @@ class Concat(Combined):
189
185
  class GridsBase(GivenAxis):
190
186
  """A base class for handling grids in datasets."""
191
187
 
192
- def __init__(self, datasets: List[Any], axis: int) -> None:
188
+ def __init__(self, datasets: list[Any], axis: int) -> None:
193
189
  """Initializes a GridsBase object.
194
190
 
195
191
  Parameters
@@ -229,7 +225,7 @@ class GridsBase(GivenAxis):
229
225
  # We don't check the resolution, because we want to be able to combine
230
226
  pass
231
227
 
232
- def metadata_specific(self, **kwargs: Any) -> Dict[str, Any]:
228
+ def metadata_specific(self, **kwargs: Any) -> dict[str, Any]:
233
229
  """Returns metadata specific to the GridsBase object.
234
230
 
235
231
  Parameters
@@ -246,7 +242,7 @@ class GridsBase(GivenAxis):
246
242
  multi_grids=True,
247
243
  )
248
244
 
249
- def collect_input_sources(self, collected: List[Any]) -> None:
245
+ def collect_input_sources(self, collected: list[Any]) -> None:
250
246
  """Collects input sources from the datasets.
251
247
 
252
248
  Parameters
@@ -275,7 +271,7 @@ class Grids(GridsBase):
275
271
  return np.concatenate([d.longitudes for d in self.datasets])
276
272
 
277
273
  @property
278
- def grids(self) -> Tuple[Any, ...]:
274
+ def grids(self) -> tuple[Any, ...]:
279
275
  """Returns the grids of all datasets."""
280
276
  result = []
281
277
  for d in self.datasets:
@@ -292,7 +288,7 @@ class Grids(GridsBase):
292
288
  """
293
289
  return Node(self, [d.tree() for d in self.datasets], mode="concat")
294
290
 
295
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
291
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
296
292
  """Get the metadata specific to the forwards subclass.
297
293
 
298
294
  Returns:
@@ -306,12 +302,12 @@ class Cutout(GridsBase):
306
302
 
307
303
  def __init__(
308
304
  self,
309
- datasets: List[Any],
305
+ datasets: list[Any],
310
306
  axis: int = 3,
311
307
  cropping_distance: float = 2.0,
312
308
  neighbours: int = 5,
313
- min_distance_km: Optional[float] = None,
314
- plot: Optional[bool] = None,
309
+ min_distance_km: float | None = None,
310
+ plot: bool | None = None,
315
311
  ) -> None:
316
312
  """Initializes a Cutout object for hierarchical management of Limited Area
317
313
  Models (LAMs) and a global dataset, handling overlapping regions.
@@ -487,7 +483,7 @@ class Cutout(GridsBase):
487
483
 
488
484
  return apply_index_to_slices_changes(result, changes)
489
485
 
490
- def collect_supporting_arrays(self, collected: List[Any], *path: Any) -> None:
486
+ def collect_supporting_arrays(self, collected: list[Any], *path: Any) -> None:
491
487
  """Collect supporting arrays, including masks for each LAM and the global dataset.
492
488
 
493
489
  Parameters
@@ -577,7 +573,7 @@ class Cutout(GridsBase):
577
573
  """
578
574
  return Node(self, [d.tree() for d in self.datasets])
579
575
 
580
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
576
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
581
577
  """Returns metadata specific to the Cutout object.
582
578
 
583
579
  Returns
@@ -588,7 +584,7 @@ class Cutout(GridsBase):
588
584
  return {}
589
585
 
590
586
 
591
- def grids_factory(args: Tuple[Any, ...], kwargs: dict) -> Dataset:
587
+ def grids_factory(args: tuple[Any, ...], kwargs: dict) -> Dataset:
592
588
  """Factory function to create a Grids object.
593
589
 
594
590
  Parameters
@@ -618,7 +614,7 @@ def grids_factory(args: Tuple[Any, ...], kwargs: dict) -> Dataset:
618
614
  return Grids(datasets, axis=axis)._subset(**kwargs)
619
615
 
620
616
 
621
- def cutout_factory(args: Tuple[Any, ...], kwargs: Dict[str, Any]) -> Dataset:
617
+ def cutout_factory(args: tuple[Any, ...], kwargs: dict[str, Any]) -> Dataset:
622
618
  """Factory function to create a Cutout object.
623
619
 
624
620
  Parameters
@@ -8,12 +8,9 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
 
11
+ from collections.abc import Callable
11
12
  from functools import wraps
12
13
  from typing import Any
13
- from typing import Callable
14
- from typing import List
15
- from typing import Tuple
16
- from typing import Union
17
14
 
18
15
  import numpy as np
19
16
  from numpy.typing import NDArray
@@ -23,7 +20,7 @@ from .dataset import Shape
23
20
  from .dataset import TupleIndex
24
21
 
25
22
 
26
- def _tuple_with_slices(t: TupleIndex, shape: Shape) -> Tuple[TupleIndex, Tuple[int, ...]]:
23
+ def _tuple_with_slices(t: TupleIndex, shape: Shape) -> tuple[TupleIndex, tuple[int, ...]]:
27
24
  """Replace all integers in a tuple with slices, so we preserve the dimensionality.
28
25
 
29
26
  Parameters:
@@ -87,7 +84,7 @@ def _index_to_tuple(index: FullIndex, shape: Shape) -> TupleIndex:
87
84
  raise ValueError(f"Invalid index: {index}")
88
85
 
89
86
 
90
- def index_to_slices(index: Union[int, slice, Tuple], shape: Shape) -> Tuple[TupleIndex, Tuple[int, ...]]:
87
+ def index_to_slices(index: int | slice | tuple, shape: Shape) -> tuple[TupleIndex, tuple[int, ...]]:
91
88
  """Convert an index to a tuple of slices, with the same dimensionality as the shape.
92
89
 
93
90
  Parameters:
@@ -100,7 +97,7 @@ def index_to_slices(index: Union[int, slice, Tuple], shape: Shape) -> Tuple[Tupl
100
97
  return _tuple_with_slices(_index_to_tuple(index, shape), shape)
101
98
 
102
99
 
103
- def apply_index_to_slices_changes(result: NDArray[Any], changes: Tuple[int, ...]) -> NDArray[Any]:
100
+ def apply_index_to_slices_changes(result: NDArray[Any], changes: tuple[int, ...]) -> NDArray[Any]:
104
101
  """Apply changes to the result array based on the slices.
105
102
 
106
103
  Parameters:
@@ -118,7 +115,7 @@ def apply_index_to_slices_changes(result: NDArray[Any], changes: Tuple[int, ...]
118
115
  return result
119
116
 
120
117
 
121
- def update_tuple(t: Tuple, index: int, value: Any) -> Tuple[Tuple, Any]:
118
+ def update_tuple(t: tuple, index: int, value: Any) -> tuple[tuple, Any]:
122
119
  """Replace the elements of a tuple at the given index with a new value.
123
120
 
124
121
  Parameters:
@@ -135,7 +132,7 @@ def update_tuple(t: Tuple, index: int, value: Any) -> Tuple[Tuple, Any]:
135
132
  return tuple(t), prev
136
133
 
137
134
 
138
- def length_to_slices(index: slice, lengths: List[int]) -> List[Union[slice, None]]:
135
+ def length_to_slices(index: slice, lengths: list[int]) -> list[slice | None]:
139
136
  """Convert an index to a list of slices, given the lengths of the dimensions.
140
137
 
141
138
  Parameters:
@@ -174,7 +171,7 @@ def length_to_slices(index: slice, lengths: List[int]) -> List[Union[slice, None
174
171
  return result
175
172
 
176
173
 
177
- def _as_tuples(index: Tuple) -> Tuple:
174
+ def _as_tuples(index: tuple) -> tuple:
178
175
  """Convert elements of the index to tuples if they are lists or arrays.
179
176
 
180
177
  Parameters:
@@ -219,7 +216,7 @@ def expand_list_indexing(method: Callable[..., NDArray[Any]]) -> Callable[..., N
219
216
  if not any(isinstance(i, (list, tuple)) for i in index):
220
217
  return method(self, index)
221
218
 
222
- which: List[int] = []
219
+ which: list[int] = []
223
220
  for i, idx in enumerate(index):
224
221
  if isinstance(idx, (list, tuple)):
225
222
  which.append(i)
@@ -241,7 +238,7 @@ def expand_list_indexing(method: Callable[..., NDArray[Any]]) -> Callable[..., N
241
238
  return wrapper
242
239
 
243
240
 
244
- def make_slice_or_index_from_list_or_tuple(indices: List[int]) -> Union[List[int], slice]:
241
+ def make_slice_or_index_from_list_or_tuple(indices: list[int]) -> list[int] | slice:
245
242
  """Convert a list or tuple of indices to a slice or an index, if possible.
246
243
 
247
244
  Parameters:
@@ -12,12 +12,6 @@ import datetime
12
12
  import logging
13
13
  from functools import cached_property
14
14
  from typing import Any
15
- from typing import Dict
16
- from typing import List
17
- from typing import Optional
18
- from typing import Set
19
- from typing import Tuple
20
- from typing import Union
21
15
 
22
16
  import numpy as np
23
17
  from anemoi.utils.dates import frequency_to_timedelta
@@ -193,7 +187,7 @@ class InterpolateFrequency(Forwards):
193
187
  return Node(self, [self.forward.tree()], frequency=self.frequency)
194
188
 
195
189
  @cached_property
196
- def missing(self) -> Set[int]:
190
+ def missing(self) -> set[int]:
197
191
  """Get the missing data indices."""
198
192
  result = []
199
193
  j = 0
@@ -204,10 +198,10 @@ class InterpolateFrequency(Forwards):
204
198
  result.append(j)
205
199
  j += 1
206
200
 
207
- result = set(x for x in result if x < self._len)
201
+ result = {x for x in result if x < self._len}
208
202
  return result
209
203
 
210
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
204
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
211
205
  """Get the metadata specific to the InterpolateFrequency subclass.
212
206
 
213
207
  Returns
@@ -221,9 +215,7 @@ class InterpolateFrequency(Forwards):
221
215
 
222
216
 
223
217
  class InterpolateNearest(Forwards):
224
- def __init__(
225
- self, dataset: Dataset, interpolate_variables: List[str], max_distance: Optional[float] = None
226
- ) -> None:
218
+ def __init__(self, dataset: Dataset, interpolate_variables: list[str], max_distance: float | None = None) -> None:
227
219
  """Initialize the InterpolateNearest class.
228
220
 
229
221
  Parameters
@@ -262,7 +254,7 @@ class InterpolateNearest(Forwards):
262
254
  return self.forward.shape
263
255
 
264
256
  @property
265
- def metadata(self) -> Dict[str, Any]:
257
+ def metadata(self) -> dict[str, Any]:
266
258
  return self.forward.metadata()
267
259
 
268
260
  @staticmethod
@@ -281,12 +273,12 @@ class InterpolateNearest(Forwards):
281
273
  result = target_data[(slice(None),) + index[1:]]
282
274
  return apply_index_to_slices_changes(result, changes)
283
275
 
284
- def __getitem__(self, index: Union[int, slice, Tuple[Union[int, slice], ...]]) -> NDArray[Any]:
276
+ def __getitem__(self, index: int | slice | tuple[int | slice, ...]) -> NDArray[Any]:
285
277
  if isinstance(index, (int, slice)):
286
278
  index = (index, slice(None), slice(None), slice(None))
287
279
  return self._get_tuple(index)
288
280
 
289
- def subclass_metadata_specific(self) -> Dict[str, Any]:
281
+ def subclass_metadata_specific(self) -> dict[str, Any]:
290
282
  return {
291
283
  "interpolate_variables": self.vars,
292
284
  }
@@ -12,10 +12,6 @@ import datetime
12
12
  import logging
13
13
  from functools import cached_property
14
14
  from typing import Any
15
- from typing import Dict
16
- from typing import List
17
- from typing import Optional
18
- from typing import Set
19
15
 
20
16
  import numpy as np
21
17
  from numpy.typing import NDArray
@@ -182,10 +178,10 @@ class Join(Combined):
182
178
  return Select(self, indices, {"overlay": variables})
183
179
 
184
180
  @cached_property
185
- def variables(self) -> List[str]:
181
+ def variables(self) -> list[str]:
186
182
  """Get the variables of the joined dataset."""
187
183
  seen = set()
188
- result: List[str] = []
184
+ result: list[str] = []
189
185
  for d in reversed(self.datasets):
190
186
  for v in reversed(d.variables):
191
187
  while v in seen:
@@ -196,7 +192,7 @@ class Join(Combined):
196
192
  return result
197
193
 
198
194
  @property
199
- def variables_metadata(self) -> Dict[str, Any]:
195
+ def variables_metadata(self) -> dict[str, Any]:
200
196
  """Get the metadata of the variables."""
201
197
  result = {}
202
198
  variables = [v for v in self.variables if not (v.startswith("(") and v.endswith(")"))]
@@ -216,18 +212,18 @@ class Join(Combined):
216
212
  return result
217
213
 
218
214
  @cached_property
219
- def name_to_index(self) -> Dict[str, int]:
215
+ def name_to_index(self) -> dict[str, int]:
220
216
  """Get the mapping of variable names to indices."""
221
217
  return {k: i for i, k in enumerate(self.variables)}
222
218
 
223
219
  @property
224
- def statistics(self) -> Dict[str, NDArray[Any]]:
220
+ def statistics(self) -> dict[str, NDArray[Any]]:
225
221
  """Get the statistics of the joined dataset."""
226
222
  return {
227
223
  k: np.concatenate([d.statistics[k] for d in self.datasets], axis=0) for k in self.datasets[0].statistics
228
224
  }
229
225
 
230
- def statistics_tendencies(self, delta: Optional[datetime.timedelta] = None) -> Dict[str, NDArray[Any]]:
226
+ def statistics_tendencies(self, delta: datetime.timedelta | None = None) -> dict[str, NDArray[Any]]:
231
227
  """Get the statistics tendencies of the joined dataset.
232
228
 
233
229
  Parameters
@@ -268,9 +264,9 @@ class Join(Combined):
268
264
  assert False
269
265
 
270
266
  @cached_property
271
- def missing(self) -> Set[int]:
267
+ def missing(self) -> set[int]:
272
268
  """Get the missing data indices."""
273
- result: Set[int] = set()
269
+ result: set[int] = set()
274
270
  for d in self.datasets:
275
271
  result = result | d.missing
276
272
  return result
@@ -11,11 +11,6 @@
11
11
  import logging
12
12
  from functools import cached_property
13
13
  from typing import Any
14
- from typing import Dict
15
- from typing import List
16
- from typing import Optional
17
- from typing import Tuple
18
- from typing import Union
19
14
 
20
15
  import numpy as np
21
16
  from numpy.typing import NDArray
@@ -117,7 +112,7 @@ class Masked(Forwards):
117
112
  result = apply_index_to_slices_changes(result, changes)
118
113
  return result
119
114
 
120
- def collect_supporting_arrays(self, collected: List[Tuple], *path: Any) -> None:
115
+ def collect_supporting_arrays(self, collected: list[tuple], *path: Any) -> None:
121
116
  """Collect supporting arrays.
122
117
 
123
118
  Parameters
@@ -134,7 +129,7 @@ class Masked(Forwards):
134
129
  class Thinning(Masked):
135
130
  """A class to represent a thinned dataset."""
136
131
 
137
- def __init__(self, forward: Dataset, thinning: Optional[int], method: str) -> None:
132
+ def __init__(self, forward: Dataset, thinning: int | None, method: str) -> None:
138
133
  """Initialize the Thinning class.
139
134
 
140
135
  Parameters
@@ -195,7 +190,7 @@ class Thinning(Masked):
195
190
  """
196
191
  return Node(self, [self.forward.tree()], thinning=self.thinning, method=self.method)
197
192
 
198
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
193
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
199
194
  """Get the metadata specific to the Thinning subclass.
200
195
 
201
196
  Returns
@@ -209,7 +204,7 @@ class Thinning(Masked):
209
204
  class Cropping(Masked):
210
205
  """A class to represent a cropped dataset."""
211
206
 
212
- def __init__(self, forward: Dataset, area: Union[Dataset, Tuple[float, float, float, float]]) -> None:
207
+ def __init__(self, forward: Dataset, area: Dataset | tuple[float, float, float, float]) -> None:
213
208
  """Initialize the Cropping class.
214
209
 
215
210
  Parameters
@@ -245,7 +240,7 @@ class Cropping(Masked):
245
240
  """
246
241
  return Node(self, [self.forward.tree()], area=self.area)
247
242
 
248
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
243
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
249
244
  """Get the metadata specific to the Cropping subclass.
250
245
 
251
246
  Returns
@@ -314,7 +309,7 @@ class TrimEdge(Masked):
314
309
  """
315
310
  return Node(self, [self.forward.tree()], edge=self.edge)
316
311
 
317
- def forwards_subclass_metadata_specific(self) -> Dict[str, Any]:
312
+ def forwards_subclass_metadata_specific(self) -> dict[str, Any]:
318
313
  """Get the metadata specific to the TrimEdge subclass.
319
314
 
320
315
  Returns
@@ -12,10 +12,6 @@ import datetime
12
12
  import logging
13
13
  from functools import cached_property
14
14
  from typing import Any
15
- from typing import Dict
16
- from typing import List
17
- from typing import Set
18
- from typing import Tuple
19
15
 
20
16
  import numpy as np
21
17
  from numpy.typing import NDArray
@@ -40,7 +36,7 @@ LOG = logging.getLogger(__name__)
40
36
  class Merge(Combined):
41
37
  """A class to merge multiple datasets along the dates axis, handling gaps in dates if allowed."""
42
38
 
43
- def __init__(self, datasets: List[Dataset], allow_gaps_in_dates: bool = False) -> None:
39
+ def __init__(self, datasets: list[Dataset], allow_gaps_in_dates: bool = False) -> None:
44
40
  """Initialize the Merge object.
45
41
 
46
42
  Parameters
@@ -128,10 +124,10 @@ class Merge(Combined):
128
124
  return self._frequency
129
125
 
130
126
  @cached_property
131
- def missing(self) -> Set[int]:
127
+ def missing(self) -> set[int]:
132
128
  """Get the indices of missing dates in the merged dataset."""
133
129
  # TODO: optimize
134
- result: Set[int] = set()
130
+ result: set[int] = set()
135
131
 
136
132
  for i, (dataset, row) in enumerate(self._indices):
137
133
  if dataset == self._missing_index:
@@ -192,7 +188,7 @@ class Merge(Combined):
192
188
  """
193
189
  return Node(self, [d.tree() for d in self.datasets], allow_gaps_in_dates=self.allow_gaps_in_dates)
194
190
 
195
- def metadata_specific(self) -> Dict[str, Any]:
191
+ def metadata_specific(self) -> dict[str, Any]:
196
192
  """Get the specific metadata for the merged dataset.
197
193
 
198
194
  Returns
@@ -265,7 +261,7 @@ class Merge(Combined):
265
261
  return np.stack([self[i] for i in range(*s.indices(self._len))])
266
262
 
267
263
 
268
- def merge_factory(args: Tuple, kwargs: Dict[str, Any]) -> Dataset:
264
+ def merge_factory(args: tuple, kwargs: dict[str, Any]) -> Dataset:
269
265
  """Factory function to create a merged dataset.
270
266
 
271
267
  Parameters