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
@@ -11,20 +11,41 @@ import datetime
11
11
  import logging
12
12
  import warnings
13
13
  from copy import deepcopy
14
+ from typing import Any
15
+ from typing import Dict
16
+ from typing import Generator
17
+ from typing import List
18
+ from typing import Optional
19
+ from typing import Tuple
20
+ from typing import Union
14
21
 
15
22
  import earthkit.data as ekd
16
23
  import numpy as np
17
24
  from earthkit.data.core.temporary import temp_file
18
25
  from earthkit.data.readers.grib.output import new_grib_output
26
+ from numpy.typing import NDArray
19
27
 
20
28
  from anemoi.datasets.create.utils import to_datetime_list
21
29
 
30
+ from .legacy import legacy_source
22
31
  from .mars import mars
23
32
 
24
33
  LOG = logging.getLogger(__name__)
25
34
 
26
35
 
27
- def _member(field):
36
+ def _member(field: Any) -> int:
37
+ """Retrieves the member number from the field metadata.
38
+
39
+ Parameters
40
+ ----------
41
+ field : Any
42
+ The field from which to retrieve the member number.
43
+
44
+ Returns
45
+ -------
46
+ int
47
+ The member number.
48
+ """
28
49
  # Bug in eccodes has number=0 randomly
29
50
  number = field.metadata("number", default=0)
30
51
  if number is None:
@@ -33,26 +54,70 @@ def _member(field):
33
54
 
34
55
 
35
56
  class Accumulation:
36
- def __init__(self, out, /, param, date, time, number, step, frequency, **kwargs):
57
+ """Class to handle data accumulation for a specific parameter, date, time, and member."""
58
+
59
+ buggy_steps: bool = False
60
+
61
+ def __init__(
62
+ self,
63
+ out: Any,
64
+ /,
65
+ param: str,
66
+ date: int,
67
+ time: int,
68
+ number: int,
69
+ step: List[int],
70
+ frequency: int,
71
+ **kwargs: Any,
72
+ ) -> None:
73
+ """Initializes an Accumulation instance.
74
+
75
+ Parameters
76
+ ----------
77
+ out : Any
78
+ Output object for writing data.
79
+ param : str
80
+ Parameter name.
81
+ date : int
82
+ Date of the accumulation.
83
+ time : int
84
+ Time of the accumulation.
85
+ number : int
86
+ Member number.
87
+ step : List[int]
88
+ List of steps.
89
+ frequency : int
90
+ Frequency of accumulation.
91
+ **kwargs : Any
92
+ Additional keyword arguments.
93
+ """
37
94
  self.out = out
38
95
  self.param = param
39
96
  self.date = date
40
97
  self.time = time
41
98
  self.steps = step
42
99
  self.number = number
43
- self.values = None
100
+ self.values: Optional[NDArray[None]] = None
44
101
  self.seen = set()
45
- self.startStep = None
46
- self.endStep = None
102
+ self.startStep: Optional[int] = None
103
+ self.endStep: Optional[int] = None
47
104
  self.done = False
48
105
  self.frequency = frequency
49
106
  self._check = None
50
107
 
51
108
  @property
52
- def key(self):
109
+ def key(self) -> Tuple[str, int, int, List[int], int]:
110
+ """Returns the key for the accumulation."""
53
111
  return (self.param, self.date, self.time, self.steps, self.number)
54
112
 
55
- def check(self, field):
113
+ def check(self, field: Any) -> None:
114
+ """Checks the field metadata against the accumulation parameters.
115
+
116
+ Parameters
117
+ ----------
118
+ field : Any
119
+ The field to check.
120
+ """
56
121
  if self._check is None:
57
122
  self._check = field.metadata(namespace="mars")
58
123
 
@@ -82,8 +147,14 @@ class Accumulation:
82
147
  if k not in ("step",):
83
148
  assert self._check[k] == mars[k], (k, self._check[k], mars[k])
84
149
 
85
- def write(self, template):
150
+ def write(self, template: Any) -> None:
151
+ """Writes the accumulated values to the output.
86
152
 
153
+ Parameters
154
+ ----------
155
+ template : Any
156
+ Template for writing the output.
157
+ """
87
158
  assert self.startStep != self.endStep, (self.startStep, self.endStep)
88
159
  if np.all(self.values < 0):
89
160
  LOG.warning(
@@ -101,8 +172,16 @@ class Accumulation:
101
172
  self.values = None
102
173
  self.done = True
103
174
 
104
- def add(self, field, values):
175
+ def add(self, field: Any, values: NDArray[Any]) -> None:
176
+ """Adds values to the accumulation.
105
177
 
178
+ Parameters
179
+ ----------
180
+ field : Any
181
+ The field containing the values.
182
+ values : np.ndarray
183
+ The values to add.
184
+ """
106
185
  self.check(field)
107
186
 
108
187
  step = field.metadata("step")
@@ -131,8 +210,37 @@ class Accumulation:
131
210
  self.write(template=field)
132
211
 
133
212
  @classmethod
134
- def mars_date_time_steps(cls, dates, step1, step2, frequency, base_times, adjust_step):
135
-
213
+ def mars_date_time_steps(
214
+ cls,
215
+ dates: List[datetime.datetime],
216
+ step1: int,
217
+ step2: int,
218
+ frequency: Optional[int],
219
+ base_times: List[int],
220
+ adjust_step: bool,
221
+ ) -> Generator[Tuple[int, int, Tuple[int, ...]], None, None]:
222
+ """Generates MARS date-time steps.
223
+
224
+ Parameters
225
+ ----------
226
+ dates : List[datetime.datetime]
227
+ List of dates.
228
+ step1 : int
229
+ First step.
230
+ step2 : int
231
+ Second step.
232
+ frequency : Optional[int]
233
+ Frequency of accumulation.
234
+ base_times : List[int]
235
+ List of base times.
236
+ adjust_step : bool
237
+ Whether to adjust the step.
238
+
239
+ Returns
240
+ -------
241
+ Generator[Tuple[int, int, Tuple[int, ...]], None, None]
242
+ A generator of MARS date-time steps.
243
+ """
136
244
  # assert step1 > 0, (step1, step2, frequency)
137
245
 
138
246
  for valid_date in dates:
@@ -152,14 +260,33 @@ class Accumulation:
152
260
  yield cls._mars_date_time_step(base_date, step1, step2, add_step, frequency)
153
261
 
154
262
  def __repr__(self) -> str:
263
+ """Returns a string representation of the Accumulation instance.
264
+
265
+ Returns
266
+ -------
267
+ str
268
+ String representation of the Accumulation instance.
269
+ """
155
270
  return f"{self.__class__.__name__}({self.key})"
156
271
 
157
272
 
158
273
  class AccumulationFromStart(Accumulation):
159
- buggy_steps = True
274
+ """Class to handle data accumulation from the start of the forecast."""
160
275
 
161
- def compute(self, values, startStep, endStep):
276
+ buggy_steps = True
162
277
 
278
+ def compute(self, values: NDArray[Any], startStep: int, endStep: int) -> None:
279
+ """Computes the accumulation from the start.
280
+
281
+ Parameters
282
+ ----------
283
+ values : np.ndarray
284
+ The values to accumulate.
285
+ startStep : int
286
+ The start step.
287
+ endStep : int
288
+ The end step.
289
+ """
163
290
  assert startStep == 0, startStep
164
291
 
165
292
  if self.values is None:
@@ -186,7 +313,29 @@ class AccumulationFromStart(Accumulation):
186
313
  self.values = np.maximum(self.values, 0)
187
314
 
188
315
  @classmethod
189
- def _mars_date_time_step(cls, base_date, step1, step2, add_step, frequency):
316
+ def _mars_date_time_step(
317
+ cls, base_date: datetime.datetime, step1: int, step2: int, add_step: int, frequency: Optional[int]
318
+ ) -> Tuple[int, int, Tuple[int, ...]]:
319
+ """Generates a MARS date-time step.
320
+
321
+ Parameters
322
+ ----------
323
+ base_date : datetime.datetime
324
+ The base date.
325
+ step1 : int
326
+ First step.
327
+ step2 : int
328
+ Second step.
329
+ add_step : int
330
+ Additional step.
331
+ frequency : Optional[int]
332
+ Frequency of accumulation.
333
+
334
+ Returns
335
+ -------
336
+ Tuple[int, int, Tuple[int, ...]]
337
+ A tuple representing the MARS date-time step.
338
+ """
190
339
  assert not frequency, frequency
191
340
 
192
341
  steps = (step1 + add_step, step2 + add_step)
@@ -201,10 +350,22 @@ class AccumulationFromStart(Accumulation):
201
350
 
202
351
 
203
352
  class AccumulationFromLastStep(Accumulation):
204
- buggy_steps = False
353
+ """Class to handle data accumulation from the last step of the forecast."""
205
354
 
206
- def compute(self, values, startStep, endStep):
355
+ buggy_steps = False
207
356
 
357
+ def compute(self, values: NDArray[Any], startStep: int, endStep: int) -> None:
358
+ """Computes the accumulation from the last step.
359
+
360
+ Parameters
361
+ ----------
362
+ values : np.ndarray
363
+ The values to accumulate.
364
+ startStep : int
365
+ The start step.
366
+ endStep : int
367
+ The end step.
368
+ """
208
369
  assert endStep - startStep == self.frequency, (
209
370
  startStep,
210
371
  endStep,
@@ -227,7 +388,29 @@ class AccumulationFromLastStep(Accumulation):
227
388
  self.values += values
228
389
 
229
390
  @classmethod
230
- def _mars_date_time_step(cls, base_date, step1, step2, add_step, frequency):
391
+ def _mars_date_time_step(
392
+ cls, base_date: datetime.datetime, step1: int, step2: int, add_step: int, frequency: int
393
+ ) -> Tuple[int, int, Tuple[int, ...]]:
394
+ """Generates a MARS date-time step.
395
+
396
+ Parameters
397
+ ----------
398
+ base_date : datetime.datetime
399
+ The base date.
400
+ step1 : int
401
+ First step.
402
+ step2 : int
403
+ Second step.
404
+ add_step : int
405
+ Additional step.
406
+ frequency : int
407
+ Frequency of accumulation.
408
+
409
+ Returns
410
+ -------
411
+ Tuple[int, int, Tuple[int, ...]]
412
+ A tuple representing the MARS date-time step.
413
+ """
231
414
  assert frequency > 0, frequency
232
415
  # assert step1 > 0, (step1, step2, frequency, add_step, base_date)
233
416
 
@@ -241,20 +424,58 @@ class AccumulationFromLastStep(Accumulation):
241
424
  )
242
425
 
243
426
 
244
- def _identity(x):
427
+ def _identity(x: Any) -> Any:
428
+ """Identity function that returns the input as is.
429
+
430
+ Parameters
431
+ ----------
432
+ x : Any
433
+ Input value.
434
+
435
+ Returns
436
+ -------
437
+ Any
438
+ The input value.
439
+ """
245
440
  return x
246
441
 
247
442
 
248
443
  def _compute_accumulations(
249
- context,
250
- dates,
251
- request,
252
- user_accumulation_period=6,
253
- data_accumulation_period=None,
254
- patch=_identity,
255
- base_times=None,
256
- use_cdsapi_dataset=None,
257
- ):
444
+ context: Any,
445
+ dates: List[datetime.datetime],
446
+ request: Dict[str, Any],
447
+ user_accumulation_period: Union[int, Tuple[int, int]] = 6,
448
+ data_accumulation_period: Optional[int] = None,
449
+ patch: Any = _identity,
450
+ base_times: Optional[List[int]] = None,
451
+ use_cdsapi_dataset: Optional[str] = None,
452
+ ) -> Any:
453
+ """Computes accumulations based on the provided parameters.
454
+
455
+ Parameters
456
+ ----------
457
+ context : Any
458
+ Context for the computation.
459
+ dates : List[datetime.datetime]
460
+ List of dates.
461
+ request : Dict[str, Any]
462
+ Request parameters.
463
+ user_accumulation_period : Union[int, Tuple[int, int]], optional
464
+ User-defined accumulation period. Defaults to 6.
465
+ data_accumulation_period : Optional[int], optional
466
+ Data accumulation period. Defaults to None.
467
+ patch : Any, optional
468
+ Patch function. Defaults to _identity.
469
+ base_times : Optional[List[int]], optional
470
+ List of base times. Defaults to None.
471
+ use_cdsapi_dataset : Optional[str], optional
472
+ CDSAPI dataset to use. Defaults to None.
473
+
474
+ Returns
475
+ -------
476
+ Any
477
+ The computed accumulations.
478
+ """
258
479
  adjust_step = isinstance(user_accumulation_period, int)
259
480
 
260
481
  if not isinstance(user_accumulation_period, (list, tuple)):
@@ -355,13 +576,37 @@ def _compute_accumulations(
355
576
  return ds
356
577
 
357
578
 
358
- def _to_list(x):
579
+ def _to_list(x: Union[List[Any], Tuple[Any], Any]) -> List[Any]:
580
+ """Converts the input to a list if it is not already a list or tuple.
581
+
582
+ Parameters
583
+ ----------
584
+ x : Union[List[Any], Tuple[Any], Any]
585
+ Input value.
586
+
587
+ Returns
588
+ -------
589
+ List[Any]
590
+ The input value as a list.
591
+ """
359
592
  if isinstance(x, (list, tuple)):
360
593
  return x
361
594
  return [x]
362
595
 
363
596
 
364
- def _scda(request):
597
+ def _scda(request: Dict[str, Any]) -> Dict[str, Any]:
598
+ """Modifies the request stream based on the time.
599
+
600
+ Parameters
601
+ ----------
602
+ request : Dict[str, Any]
603
+ Request parameters.
604
+
605
+ Returns
606
+ -------
607
+ Dict[str, Any]
608
+ The modified request parameters.
609
+ """
365
610
  if request["time"] in (6, 18, 600, 1800):
366
611
  request["stream"] = "scda"
367
612
  else:
@@ -369,7 +614,28 @@ def _scda(request):
369
614
  return request
370
615
 
371
616
 
372
- def accumulations(context, dates, use_cdsapi_dataset=None, **request):
617
+ @legacy_source(__file__)
618
+ def accumulations(
619
+ context: Any, dates: List[datetime.datetime], use_cdsapi_dataset: Optional[str] = None, **request: Any
620
+ ) -> Any:
621
+ """Computes accumulations based on the provided context, dates, and request parameters.
622
+
623
+ Parameters
624
+ ----------
625
+ context : Any
626
+ Context for the computation.
627
+ dates : List[datetime.datetime]
628
+ List of dates.
629
+ use_cdsapi_dataset : Optional[str], optional
630
+ CDSAPI dataset to use. Defaults to None.
631
+ **request : Any
632
+ Additional request parameters.
633
+
634
+ Returns
635
+ -------
636
+ Any
637
+ The computed accumulations.
638
+ """
373
639
  _to_list(request["param"])
374
640
  class_ = request.get("class", "od")
375
641
  stream = request.get("stream", "oper")
@@ -7,10 +7,35 @@
7
7
  # granted to it by virtue of its status as an intergovernmental organisation
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
+ from typing import Any
11
+ from typing import Dict
12
+ from typing import List
13
+
10
14
  from earthkit.data import from_source
11
15
 
16
+ from .legacy import legacy_source
17
+
18
+
19
+ @legacy_source(__file__)
20
+ def constants(context: Any, dates: List[str], template: Dict[str, Any], param: str) -> Any:
21
+ """Deprecated function to retrieve constants data.
22
+
23
+ Parameters
24
+ ----------
25
+ context : Any
26
+ The context object for tracing.
27
+ dates : list of str
28
+ List of dates for which data is required.
29
+ template : dict of str to Any
30
+ Template dictionary for the data source.
31
+ param : str
32
+ Parameter to retrieve.
12
33
 
13
- def constants(context, dates, template, param):
34
+ Returns
35
+ -------
36
+ Any
37
+ Data retrieved from the source.
38
+ """
14
39
  from warnings import warn
15
40
 
16
41
  warn(
@@ -25,4 +50,4 @@ def constants(context, dates, template, param):
25
50
  return from_source("forcings", source_or_dataset=template, date=dates, param=param)
26
51
 
27
52
 
28
- execute = constants
53
+ execute: Any = constants
@@ -8,9 +8,13 @@
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
10
 
11
- from .xarray import load_many
11
+ from . import source_registry
12
+ from .xarray import XarraySourceBase
12
13
 
13
14
 
14
- def execute(context, dates, path, *args, **kwargs):
15
+ @source_registry.register("eccc_fstd")
16
+ class XarrayECCCSource(XarraySourceBase):
17
+ """An Xarray data source that uses the `fstd` engine."""
18
+
19
+ emoji = "🍁"
15
20
  options = {"engine": "fstd"}
16
- return load_many("🍁", context, dates, path, *args, options=options, **kwargs)
@@ -0,0 +1,37 @@
1
+ # (C) Copyright 2024 Anemoi contributors.
2
+ #
3
+ # This software is licensed under the terms of the Apache Licence Version 2.0
4
+ # which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5
+ #
6
+ # In applying this licence, ECMWF does not waive the privileges and immunities
7
+ # granted to it by virtue of its status as an intergovernmental organisation
8
+ # nor does it submit to any jurisdiction.
9
+
10
+
11
+ from typing import Any
12
+ from typing import List
13
+
14
+ import earthkit.data as ekd
15
+
16
+ from .legacy import legacy_source
17
+
18
+
19
+ @legacy_source(__file__)
20
+ def execute(context: Any, dates: List[str], **kwargs: Any) -> ekd.FieldList:
21
+ """Executes the loading of an empty data source.
22
+
23
+ Parameters
24
+ ----------
25
+ context : object
26
+ The context in which the function is executed.
27
+ dates : list
28
+ List of dates for which data is to be loaded.
29
+ **kwargs : dict
30
+ Additional keyword arguments.
31
+
32
+ Returns
33
+ -------
34
+ ekd.FieldList
35
+ Loaded empty data source.
36
+ """
37
+ return ekd.from_source("empty")
@@ -7,10 +7,34 @@
7
7
  # granted to it by virtue of its status as an intergovernmental organisation
8
8
  # nor does it submit to any jurisdiction.
9
9
 
10
+ from typing import Any
11
+ from typing import List
12
+
10
13
  from earthkit.data import from_source
11
14
 
15
+ from .legacy import legacy_source
16
+
17
+
18
+ @legacy_source(__file__)
19
+ def forcings(context: Any, dates: List[str], template: str, param: str) -> Any:
20
+ """Loads forcing data from a specified source.
21
+
22
+ Parameters
23
+ ----------
24
+ context : object
25
+ The context in which the function is executed.
26
+ dates : list
27
+ List of dates for which data is to be loaded.
28
+ template : str
29
+ Template for the data source.
30
+ param : str
31
+ Parameter for the data source.
12
32
 
13
- def forcings(context, dates, template, param):
33
+ Returns
34
+ -------
35
+ object
36
+ Loaded forcing data.
37
+ """
14
38
  context.trace("✅", f"from_source(forcings, {template}, {param}")
15
39
  return from_source("forcings", source_or_dataset=template, date=dates, param=param)
16
40