anemoi-datasets 0.5.20__py3-none-any.whl → 0.5.22__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/_version.py +2 -2
- anemoi/datasets/check.py +93 -0
- anemoi/datasets/commands/check.py +101 -0
- anemoi/datasets/commands/copy.py +43 -3
- anemoi/datasets/commands/create.py +2 -3
- anemoi/datasets/commands/grib-index.py +0 -3
- anemoi/datasets/commands/inspect.py +2 -2
- anemoi/datasets/commands/scan.py +17 -5
- anemoi/datasets/create/__init__.py +19 -8
- anemoi/datasets/create/check.py +19 -1
- anemoi/datasets/create/input/action.py +2 -0
- anemoi/datasets/create/input/result.py +6 -2
- anemoi/datasets/create/sources/accumulations.py +400 -34
- anemoi/datasets/create/sources/forcings.py +1 -1
- anemoi/datasets/create/sources/grib.py +27 -181
- anemoi/datasets/create/sources/xarray_support/metadata.py +6 -0
- anemoi/datasets/create/sources/xarray_zarr.py +1 -1
- anemoi/datasets/create/writer.py +1 -1
- anemoi/datasets/data/complement.py +28 -11
- anemoi/datasets/data/forwards.py +4 -0
- anemoi/datasets/data/grids.py +3 -3
- anemoi/datasets/data/misc.py +1 -1
- anemoi/datasets/data/stores.py +36 -4
- {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/METADATA +5 -3
- {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/RECORD +29 -27
- {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/WHEEL +1 -1
- {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/entry_points.txt +0 -0
- {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/licenses/LICENSE +0 -0
- {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/top_level.txt +0 -0
|
@@ -68,9 +68,11 @@ class Accumulation:
|
|
|
68
68
|
number: int,
|
|
69
69
|
step: List[int],
|
|
70
70
|
frequency: int,
|
|
71
|
+
accumulations_reset_frequency: Optional[int] = None,
|
|
72
|
+
user_date: Optional[str] = None,
|
|
71
73
|
**kwargs: Any,
|
|
72
74
|
) -> None:
|
|
73
|
-
"""
|
|
75
|
+
"""Initialises an Accumulation instance.
|
|
74
76
|
|
|
75
77
|
Parameters
|
|
76
78
|
----------
|
|
@@ -88,6 +90,10 @@ class Accumulation:
|
|
|
88
90
|
List of steps.
|
|
89
91
|
frequency : int
|
|
90
92
|
Frequency of accumulation.
|
|
93
|
+
accumulations_reset_frequency : Optional[int], optional
|
|
94
|
+
Frequency at which accumulations reset. Defaults to None.
|
|
95
|
+
user_date : Optional[str], optional
|
|
96
|
+
User-defined date. Defaults to None.
|
|
91
97
|
**kwargs : Any
|
|
92
98
|
Additional keyword arguments.
|
|
93
99
|
"""
|
|
@@ -103,7 +109,9 @@ class Accumulation:
|
|
|
103
109
|
self.endStep: Optional[int] = None
|
|
104
110
|
self.done = False
|
|
105
111
|
self.frequency = frequency
|
|
112
|
+
self.accumulations_reset_frequency = accumulations_reset_frequency
|
|
106
113
|
self._check = None
|
|
114
|
+
self.user_date = user_date
|
|
107
115
|
|
|
108
116
|
@property
|
|
109
117
|
def key(self) -> Tuple[str, int, int, List[int], int]:
|
|
@@ -161,14 +169,28 @@ class Accumulation:
|
|
|
161
169
|
f"Negative values when computing accumutation for {self.param} ({self.date} {self.time}): min={np.amin(self.values)} max={np.amax(self.values)}"
|
|
162
170
|
)
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
# In GRIB1, is the step is greater that 254 (one byte), we cannot use a range, because both P1 and P2 values
|
|
173
|
+
# are used to store the end step
|
|
174
|
+
|
|
175
|
+
edition = template.metadata("edition")
|
|
176
|
+
|
|
177
|
+
if edition == 1 and self.endStep > 254:
|
|
178
|
+
self.out.write(
|
|
179
|
+
self.values,
|
|
180
|
+
template=template,
|
|
181
|
+
stepType="instant",
|
|
182
|
+
step=self.endStep,
|
|
183
|
+
check_nans=True,
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
self.out.write(
|
|
187
|
+
self.values,
|
|
188
|
+
template=template,
|
|
189
|
+
stepType="accum",
|
|
190
|
+
startStep=self.startStep,
|
|
191
|
+
endStep=self.endStep,
|
|
192
|
+
check_nans=True,
|
|
193
|
+
)
|
|
172
194
|
self.values = None
|
|
173
195
|
self.done = True
|
|
174
196
|
|
|
@@ -179,7 +201,7 @@ class Accumulation:
|
|
|
179
201
|
----------
|
|
180
202
|
field : Any
|
|
181
203
|
The field containing the values.
|
|
182
|
-
values :
|
|
204
|
+
values : NDArray[Any]
|
|
183
205
|
The values to add.
|
|
184
206
|
"""
|
|
185
207
|
self.check(field)
|
|
@@ -189,7 +211,7 @@ class Accumulation:
|
|
|
189
211
|
return
|
|
190
212
|
|
|
191
213
|
if not np.all(values >= 0):
|
|
192
|
-
warnings.warn(f"Negative values for {field}: {np.
|
|
214
|
+
warnings.warn(f"Negative values for {field}: {np.nanmin(values)} {np.nanmax(values)}")
|
|
193
215
|
|
|
194
216
|
assert not self.done, (self.key, step)
|
|
195
217
|
assert step not in self.seen, (self.key, step)
|
|
@@ -197,8 +219,8 @@ class Accumulation:
|
|
|
197
219
|
startStep = field.metadata("startStep")
|
|
198
220
|
endStep = field.metadata("endStep")
|
|
199
221
|
|
|
200
|
-
if
|
|
201
|
-
startStep =
|
|
222
|
+
if startStep == endStep:
|
|
223
|
+
startStep, endStep = self.adjust_steps(startStep, endStep)
|
|
202
224
|
|
|
203
225
|
assert step == endStep, (startStep, endStep, step)
|
|
204
226
|
|
|
@@ -212,12 +234,15 @@ class Accumulation:
|
|
|
212
234
|
@classmethod
|
|
213
235
|
def mars_date_time_steps(
|
|
214
236
|
cls,
|
|
237
|
+
*,
|
|
215
238
|
dates: List[datetime.datetime],
|
|
216
239
|
step1: int,
|
|
217
240
|
step2: int,
|
|
218
241
|
frequency: Optional[int],
|
|
219
242
|
base_times: List[int],
|
|
220
243
|
adjust_step: bool,
|
|
244
|
+
accumulations_reset_frequency: Optional[int],
|
|
245
|
+
user_date: Optional[str],
|
|
221
246
|
) -> Generator[Tuple[int, int, Tuple[int, ...]], None, None]:
|
|
222
247
|
"""Generates MARS date-time steps.
|
|
223
248
|
|
|
@@ -235,6 +260,10 @@ class Accumulation:
|
|
|
235
260
|
List of base times.
|
|
236
261
|
adjust_step : bool
|
|
237
262
|
Whether to adjust the step.
|
|
263
|
+
accumulations_reset_frequency : Optional[int], optional
|
|
264
|
+
Frequency at which accumulations reset. Defaults to None.
|
|
265
|
+
user_date : Optional[str], optional
|
|
266
|
+
User-defined date. Defaults to None.
|
|
238
267
|
|
|
239
268
|
Returns
|
|
240
269
|
-------
|
|
@@ -244,8 +273,16 @@ class Accumulation:
|
|
|
244
273
|
# assert step1 > 0, (step1, step2, frequency)
|
|
245
274
|
|
|
246
275
|
for valid_date in dates:
|
|
247
|
-
base_date = valid_date - datetime.timedelta(hours=step2)
|
|
248
276
|
add_step = 0
|
|
277
|
+
base_date = valid_date - datetime.timedelta(hours=step2)
|
|
278
|
+
if user_date is not None:
|
|
279
|
+
assert user_date == "????-??-01", user_date
|
|
280
|
+
new_base_date = base_date.replace(day=1)
|
|
281
|
+
assert new_base_date <= base_date, (new_base_date, base_date)
|
|
282
|
+
add_step = int((base_date - new_base_date).total_seconds() // 3600)
|
|
283
|
+
|
|
284
|
+
base_date = new_base_date
|
|
285
|
+
|
|
249
286
|
if base_date.hour not in base_times:
|
|
250
287
|
if not adjust_step:
|
|
251
288
|
raise ValueError(
|
|
@@ -257,23 +294,93 @@ class Accumulation:
|
|
|
257
294
|
base_date -= datetime.timedelta(hours=1)
|
|
258
295
|
add_step += 1
|
|
259
296
|
|
|
260
|
-
yield cls._mars_date_time_step(
|
|
297
|
+
yield cls._mars_date_time_step(
|
|
298
|
+
base_date=base_date,
|
|
299
|
+
step1=step1,
|
|
300
|
+
step2=step2,
|
|
301
|
+
add_step=add_step,
|
|
302
|
+
frequency=frequency,
|
|
303
|
+
accumulations_reset_frequency=accumulations_reset_frequency,
|
|
304
|
+
user_date=user_date,
|
|
305
|
+
requested_date=valid_date,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
def compute(self, values: NDArray[Any], startStep: int, endStep: int) -> None:
|
|
309
|
+
"""Computes the accumulation.
|
|
261
310
|
|
|
262
|
-
|
|
263
|
-
|
|
311
|
+
Parameters
|
|
312
|
+
----------
|
|
313
|
+
values : NDArray[Any]
|
|
314
|
+
The values to accumulate.
|
|
315
|
+
startStep : int
|
|
316
|
+
The start step.
|
|
317
|
+
endStep : int
|
|
318
|
+
The end step.
|
|
319
|
+
"""
|
|
320
|
+
pass
|
|
321
|
+
|
|
322
|
+
@classmethod
|
|
323
|
+
def _mars_date_time_step(
|
|
324
|
+
cls,
|
|
325
|
+
*,
|
|
326
|
+
base_date: datetime.datetime,
|
|
327
|
+
step1: int,
|
|
328
|
+
step2: int,
|
|
329
|
+
add_step: int,
|
|
330
|
+
frequency: Optional[int],
|
|
331
|
+
accumulations_reset_frequency: Optional[int],
|
|
332
|
+
user_date: Optional[str],
|
|
333
|
+
requested_date: Optional[datetime.datetime] = None,
|
|
334
|
+
) -> Tuple[int, int, Tuple[int, ...]]:
|
|
335
|
+
"""Generates a MARS date-time step.
|
|
336
|
+
|
|
337
|
+
Parameters
|
|
338
|
+
----------
|
|
339
|
+
base_date : datetime.datetime
|
|
340
|
+
The base date.
|
|
341
|
+
step1 : int
|
|
342
|
+
First step.
|
|
343
|
+
step2 : int
|
|
344
|
+
Second step.
|
|
345
|
+
add_step : int
|
|
346
|
+
Additional step.
|
|
347
|
+
frequency : Optional[int]
|
|
348
|
+
Frequency of accumulation.
|
|
349
|
+
accumulations_reset_frequency : Optional[int], optional
|
|
350
|
+
Frequency at which accumulations reset. Defaults to None.
|
|
351
|
+
user_date : Optional[str], optional
|
|
352
|
+
User-defined date. Defaults to None.
|
|
353
|
+
requested_date : Optional[datetime.datetime], optional
|
|
354
|
+
Requested date. Defaults to None.
|
|
264
355
|
|
|
265
356
|
Returns
|
|
266
357
|
-------
|
|
267
|
-
|
|
268
|
-
|
|
358
|
+
Tuple[int, int, Tuple[int, ...]]
|
|
359
|
+
A tuple representing the MARS date-time step.
|
|
269
360
|
"""
|
|
270
|
-
|
|
361
|
+
pass
|
|
271
362
|
|
|
272
363
|
|
|
273
364
|
class AccumulationFromStart(Accumulation):
|
|
274
365
|
"""Class to handle data accumulation from the start of the forecast."""
|
|
275
366
|
|
|
276
|
-
|
|
367
|
+
def adjust_steps(self, startStep: int, endStep: int) -> Tuple[int, int]:
|
|
368
|
+
"""Adjusts the start and end steps.
|
|
369
|
+
|
|
370
|
+
Parameters
|
|
371
|
+
----------
|
|
372
|
+
startStep : int
|
|
373
|
+
The start step.
|
|
374
|
+
endStep : int
|
|
375
|
+
The end step.
|
|
376
|
+
|
|
377
|
+
Returns
|
|
378
|
+
-------
|
|
379
|
+
Tuple[int, int]
|
|
380
|
+
The adjusted start and end steps.
|
|
381
|
+
"""
|
|
382
|
+
assert endStep == startStep
|
|
383
|
+
return (0, endStep)
|
|
277
384
|
|
|
278
385
|
def compute(self, values: NDArray[Any], startStep: int, endStep: int) -> None:
|
|
279
386
|
"""Computes the accumulation from the start.
|
|
@@ -314,7 +421,16 @@ class AccumulationFromStart(Accumulation):
|
|
|
314
421
|
|
|
315
422
|
@classmethod
|
|
316
423
|
def _mars_date_time_step(
|
|
317
|
-
cls,
|
|
424
|
+
cls,
|
|
425
|
+
*,
|
|
426
|
+
base_date: datetime.datetime,
|
|
427
|
+
step1: int,
|
|
428
|
+
step2: int,
|
|
429
|
+
add_step: int,
|
|
430
|
+
frequency: Optional[int],
|
|
431
|
+
accumulations_reset_frequency: Optional[int],
|
|
432
|
+
user_date: Optional[str],
|
|
433
|
+
requested_date: Optional[datetime.datetime] = None,
|
|
318
434
|
) -> Tuple[int, int, Tuple[int, ...]]:
|
|
319
435
|
"""Generates a MARS date-time step.
|
|
320
436
|
|
|
@@ -330,12 +446,19 @@ class AccumulationFromStart(Accumulation):
|
|
|
330
446
|
Additional step.
|
|
331
447
|
frequency : Optional[int]
|
|
332
448
|
Frequency of accumulation.
|
|
449
|
+
accumulations_reset_frequency : Optional[int], optional
|
|
450
|
+
Frequency at which accumulations reset. Defaults to None.
|
|
451
|
+
user_date : Optional[str], optional
|
|
452
|
+
User-defined date. Defaults to None.
|
|
453
|
+
requested_date : Optional[datetime.datetime], optional
|
|
454
|
+
Requested date. Defaults to None.
|
|
333
455
|
|
|
334
456
|
Returns
|
|
335
457
|
-------
|
|
336
458
|
Tuple[int, int, Tuple[int, ...]]
|
|
337
459
|
A tuple representing the MARS date-time step.
|
|
338
460
|
"""
|
|
461
|
+
assert user_date is None, user_date
|
|
339
462
|
assert not frequency, frequency
|
|
340
463
|
|
|
341
464
|
steps = (step1 + add_step, step2 + add_step)
|
|
@@ -352,8 +475,6 @@ class AccumulationFromStart(Accumulation):
|
|
|
352
475
|
class AccumulationFromLastStep(Accumulation):
|
|
353
476
|
"""Class to handle data accumulation from the last step of the forecast."""
|
|
354
477
|
|
|
355
|
-
buggy_steps = False
|
|
356
|
-
|
|
357
478
|
def compute(self, values: NDArray[Any], startStep: int, endStep: int) -> None:
|
|
358
479
|
"""Computes the accumulation from the last step.
|
|
359
480
|
|
|
@@ -389,7 +510,16 @@ class AccumulationFromLastStep(Accumulation):
|
|
|
389
510
|
|
|
390
511
|
@classmethod
|
|
391
512
|
def _mars_date_time_step(
|
|
392
|
-
cls,
|
|
513
|
+
cls,
|
|
514
|
+
*,
|
|
515
|
+
base_date: datetime.datetime,
|
|
516
|
+
step1: int,
|
|
517
|
+
step2: int,
|
|
518
|
+
add_step: int,
|
|
519
|
+
frequency: int,
|
|
520
|
+
accumulations_reset_frequency: Optional[int],
|
|
521
|
+
user_date: Optional[str] = None,
|
|
522
|
+
requested_date: Optional[datetime.datetime] = None,
|
|
393
523
|
) -> Tuple[int, int, Tuple[int, ...]]:
|
|
394
524
|
"""Generates a MARS date-time step.
|
|
395
525
|
|
|
@@ -405,18 +535,221 @@ class AccumulationFromLastStep(Accumulation):
|
|
|
405
535
|
Additional step.
|
|
406
536
|
frequency : int
|
|
407
537
|
Frequency of accumulation.
|
|
538
|
+
accumulations_reset_frequency : Optional[int], optional
|
|
539
|
+
Frequency at which accumulations reset. Defaults to None.
|
|
540
|
+
user_date : Optional[str], optional
|
|
541
|
+
User-defined date. Defaults to None.
|
|
542
|
+
requested_date : Optional[datetime.datetime], optional
|
|
543
|
+
Requested date. Defaults to None.
|
|
408
544
|
|
|
409
545
|
Returns
|
|
410
546
|
-------
|
|
411
547
|
Tuple[int, int, Tuple[int, ...]]
|
|
412
548
|
A tuple representing the MARS date-time step.
|
|
413
549
|
"""
|
|
550
|
+
|
|
551
|
+
assert user_date is None, user_date
|
|
552
|
+
|
|
414
553
|
assert frequency > 0, frequency
|
|
415
554
|
# assert step1 > 0, (step1, step2, frequency, add_step, base_date)
|
|
416
555
|
|
|
417
556
|
steps = []
|
|
418
557
|
for step in range(step1 + frequency, step2 + frequency, frequency):
|
|
419
558
|
steps.append(step + add_step)
|
|
559
|
+
|
|
560
|
+
return (
|
|
561
|
+
base_date.year * 10000 + base_date.month * 100 + base_date.day,
|
|
562
|
+
base_date.hour * 100 + base_date.minute,
|
|
563
|
+
tuple(steps),
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
class AccumulationFromLastReset(Accumulation):
|
|
568
|
+
"""Class to handle data accumulation from the last step of the forecast."""
|
|
569
|
+
|
|
570
|
+
def adjust_steps(self, startStep: int, endStep: int) -> Tuple[int, int]:
|
|
571
|
+
"""Adjusts the start and end steps.
|
|
572
|
+
|
|
573
|
+
Parameters
|
|
574
|
+
----------
|
|
575
|
+
startStep : int
|
|
576
|
+
The start step.
|
|
577
|
+
endStep : int
|
|
578
|
+
The end step.
|
|
579
|
+
|
|
580
|
+
Returns
|
|
581
|
+
-------
|
|
582
|
+
Tuple[int, int]
|
|
583
|
+
The adjusted start and end steps.
|
|
584
|
+
"""
|
|
585
|
+
return self.__class__._adjust_steps(startStep, endStep, self.frequency, self.accumulations_reset_frequency)
|
|
586
|
+
|
|
587
|
+
@classmethod
|
|
588
|
+
def _adjust_steps(
|
|
589
|
+
self, startStep: int, endStep: int, frequency: int, accumulations_reset_frequency: int
|
|
590
|
+
) -> Tuple[int, int]:
|
|
591
|
+
"""Adjusts the start and end steps.
|
|
592
|
+
|
|
593
|
+
Parameters
|
|
594
|
+
----------
|
|
595
|
+
startStep : int
|
|
596
|
+
The start step.
|
|
597
|
+
endStep : int
|
|
598
|
+
The end step.
|
|
599
|
+
frequency : int
|
|
600
|
+
Frequency of accumulation.
|
|
601
|
+
accumulations_reset_frequency : int
|
|
602
|
+
Frequency at which accumulations reset.
|
|
603
|
+
|
|
604
|
+
Returns
|
|
605
|
+
-------
|
|
606
|
+
Tuple[int, int]
|
|
607
|
+
The adjusted start and end steps.
|
|
608
|
+
"""
|
|
609
|
+
|
|
610
|
+
assert frequency == 1, (frequency, startStep, endStep)
|
|
611
|
+
assert endStep - startStep <= accumulations_reset_frequency, (startStep, endStep)
|
|
612
|
+
|
|
613
|
+
return ((startStep // accumulations_reset_frequency) * accumulations_reset_frequency, endStep)
|
|
614
|
+
|
|
615
|
+
@classmethod
|
|
616
|
+
def _steps(
|
|
617
|
+
cls,
|
|
618
|
+
valid_date: datetime.datetime,
|
|
619
|
+
base_date: datetime.datetime,
|
|
620
|
+
frequency: int,
|
|
621
|
+
accumulations_reset_frequency: int,
|
|
622
|
+
) -> Tuple[int, int]:
|
|
623
|
+
"""Calculates the steps for accumulation.
|
|
624
|
+
|
|
625
|
+
Parameters
|
|
626
|
+
----------
|
|
627
|
+
valid_date : datetime.datetime
|
|
628
|
+
The valid date.
|
|
629
|
+
base_date : datetime.datetime
|
|
630
|
+
The base date.
|
|
631
|
+
frequency : int
|
|
632
|
+
Frequency of accumulation.
|
|
633
|
+
accumulations_reset_frequency : int
|
|
634
|
+
Frequency at which accumulations reset.
|
|
635
|
+
|
|
636
|
+
Returns
|
|
637
|
+
-------
|
|
638
|
+
Tuple[int, int]
|
|
639
|
+
A tuple representing the steps for accumulation.
|
|
640
|
+
"""
|
|
641
|
+
|
|
642
|
+
assert base_date.day == 1, (base_date, valid_date)
|
|
643
|
+
|
|
644
|
+
step = (valid_date - base_date).total_seconds()
|
|
645
|
+
assert int(step) == step, (valid_date, base_date, step)
|
|
646
|
+
assert int(step) % 3600 == 0, (valid_date, base_date, step)
|
|
647
|
+
step = int(step // 3600)
|
|
648
|
+
start, end = cls._adjust_steps(step, step, frequency, accumulations_reset_frequency)
|
|
649
|
+
|
|
650
|
+
return start + frequency, end
|
|
651
|
+
|
|
652
|
+
def compute(self, values: NDArray[Any], startStep: int, endStep: int) -> None:
|
|
653
|
+
"""Computes the accumulation from the last step.
|
|
654
|
+
|
|
655
|
+
Parameters
|
|
656
|
+
----------
|
|
657
|
+
values : NDArray[Any]
|
|
658
|
+
The values to accumulate.
|
|
659
|
+
startStep : int
|
|
660
|
+
The start step.
|
|
661
|
+
endStep : int
|
|
662
|
+
The end step.
|
|
663
|
+
"""
|
|
664
|
+
|
|
665
|
+
assert self.frequency == 1
|
|
666
|
+
|
|
667
|
+
assert startStep % self.accumulations_reset_frequency == 0, (
|
|
668
|
+
startStep,
|
|
669
|
+
endStep,
|
|
670
|
+
self.accumulations_reset_frequency,
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
if self.values is None:
|
|
674
|
+
|
|
675
|
+
self.values = np.copy(values)
|
|
676
|
+
self.startStep = startStep
|
|
677
|
+
self.endStep = endStep
|
|
678
|
+
|
|
679
|
+
if len(self.steps) == 1:
|
|
680
|
+
assert self.startStep == self.endStep - self.frequency, (self.startStep, self.endStep)
|
|
681
|
+
|
|
682
|
+
else:
|
|
683
|
+
assert endStep != self.endStep, (self.endStep, endStep)
|
|
684
|
+
|
|
685
|
+
if endStep > self.endStep:
|
|
686
|
+
# assert endStep - self.endStep == self.stepping, (self.endStep, endStep, self.stepping)
|
|
687
|
+
self.values = values - self.values
|
|
688
|
+
self.startStep = self.endStep
|
|
689
|
+
self.endStep = endStep
|
|
690
|
+
else:
|
|
691
|
+
# assert self.endStep - endStep == self.stepping, (self.endStep, endStep, self.stepping)
|
|
692
|
+
self.values = self.values - values
|
|
693
|
+
self.startStep = endStep
|
|
694
|
+
|
|
695
|
+
assert self.endStep - self.startStep <= self.accumulations_reset_frequency, (self.startStep, startStep)
|
|
696
|
+
|
|
697
|
+
@classmethod
|
|
698
|
+
def _mars_date_time_step(
|
|
699
|
+
cls,
|
|
700
|
+
*,
|
|
701
|
+
base_date: datetime.datetime,
|
|
702
|
+
step1: int,
|
|
703
|
+
step2: int,
|
|
704
|
+
add_step: int,
|
|
705
|
+
frequency: int,
|
|
706
|
+
accumulations_reset_frequency: Optional[int],
|
|
707
|
+
user_date: Optional[str],
|
|
708
|
+
requested_date: Optional[datetime.datetime] = None,
|
|
709
|
+
) -> Tuple[int, int, Tuple[int, ...]]:
|
|
710
|
+
"""Generates a MARS date-time step.
|
|
711
|
+
|
|
712
|
+
Parameters
|
|
713
|
+
----------
|
|
714
|
+
base_date : datetime.datetime
|
|
715
|
+
The base date.
|
|
716
|
+
step1 : int
|
|
717
|
+
First step.
|
|
718
|
+
step2 : int
|
|
719
|
+
Second step.
|
|
720
|
+
add_step : int
|
|
721
|
+
Additional step.
|
|
722
|
+
frequency : int
|
|
723
|
+
Frequency of accumulation.
|
|
724
|
+
accumulations_reset_frequency : Optional[int]
|
|
725
|
+
Frequency at which accumulations reset.
|
|
726
|
+
user_date : Optional[str]
|
|
727
|
+
User-defined date.
|
|
728
|
+
requested_date : Optional[datetime.datetime], optional
|
|
729
|
+
Requested date. Defaults to None.
|
|
730
|
+
|
|
731
|
+
Returns
|
|
732
|
+
-------
|
|
733
|
+
Tuple[int, int, Tuple[int, ...]]
|
|
734
|
+
A tuple representing the MARS date-time step.
|
|
735
|
+
"""
|
|
736
|
+
# assert frequency > 0, frequency
|
|
737
|
+
# assert step1 > 0, (step1, step2, frequency, add_step, base_date)
|
|
738
|
+
|
|
739
|
+
step1 += add_step
|
|
740
|
+
step2 += add_step
|
|
741
|
+
|
|
742
|
+
assert step2 - step1 == frequency, (step1, step2, frequency)
|
|
743
|
+
|
|
744
|
+
adjust_step1 = cls._adjust_steps(step1, step1, frequency, accumulations_reset_frequency)
|
|
745
|
+
adjust_step2 = cls._adjust_steps(step2, step2, frequency, accumulations_reset_frequency)
|
|
746
|
+
|
|
747
|
+
if adjust_step1[1] % accumulations_reset_frequency == 0:
|
|
748
|
+
# First step of a new accumulation
|
|
749
|
+
steps = (adjust_step2[1],)
|
|
750
|
+
else:
|
|
751
|
+
steps = (adjust_step1[1], adjust_step2[1])
|
|
752
|
+
|
|
420
753
|
return (
|
|
421
754
|
base_date.year * 10000 + base_date.month * 100 + base_date.day,
|
|
422
755
|
base_date.hour * 100 + base_date.minute,
|
|
@@ -446,6 +779,8 @@ def _compute_accumulations(
|
|
|
446
779
|
request: Dict[str, Any],
|
|
447
780
|
user_accumulation_period: Union[int, Tuple[int, int]] = 6,
|
|
448
781
|
data_accumulation_period: Optional[int] = None,
|
|
782
|
+
accumulations_reset_frequency: Optional[int] = None,
|
|
783
|
+
user_date: Optional[str] = None,
|
|
449
784
|
patch: Any = _identity,
|
|
450
785
|
base_times: Optional[List[int]] = None,
|
|
451
786
|
use_cdsapi_dataset: Optional[str] = None,
|
|
@@ -464,6 +799,10 @@ def _compute_accumulations(
|
|
|
464
799
|
User-defined accumulation period. Defaults to 6.
|
|
465
800
|
data_accumulation_period : Optional[int], optional
|
|
466
801
|
Data accumulation period. Defaults to None.
|
|
802
|
+
accumulations_reset_frequency : Optional[int], optional
|
|
803
|
+
Frequency at which accumulations reset. Defaults to None.
|
|
804
|
+
user_date : Optional[str], optional
|
|
805
|
+
User-defined date. Defaults to None.
|
|
467
806
|
patch : Any, optional
|
|
468
807
|
Patch function. Defaults to _identity.
|
|
469
808
|
base_times : Optional[List[int]], optional
|
|
@@ -485,20 +824,36 @@ def _compute_accumulations(
|
|
|
485
824
|
step1, step2 = user_accumulation_period
|
|
486
825
|
assert step1 < step2, user_accumulation_period
|
|
487
826
|
|
|
827
|
+
if data_accumulation_period is None:
|
|
828
|
+
data_accumulation_period = user_accumulation_period[1] - user_accumulation_period[0]
|
|
829
|
+
|
|
488
830
|
if base_times is None:
|
|
489
|
-
|
|
831
|
+
if "time" in request:
|
|
832
|
+
time = request.pop("time")
|
|
833
|
+
if time > 100:
|
|
834
|
+
time = time // 100
|
|
835
|
+
base_times = [time]
|
|
836
|
+
else:
|
|
837
|
+
base_times = [0, 6, 12, 18]
|
|
490
838
|
|
|
491
839
|
base_times = [t // 100 if t > 100 else t for t in base_times]
|
|
492
840
|
|
|
493
|
-
|
|
841
|
+
if accumulations_reset_frequency is not None:
|
|
842
|
+
AccumulationClass = AccumulationFromLastReset
|
|
843
|
+
else:
|
|
844
|
+
AccumulationClass = AccumulationFromStart if data_accumulation_period in (0, None) else AccumulationFromLastStep
|
|
845
|
+
|
|
846
|
+
LOG.info(f"XXXXXXXXXXX {step1=}, {step2=}, {data_accumulation_period=}, {base_times=}, {adjust_step=}")
|
|
494
847
|
|
|
495
848
|
mars_date_time_steps = AccumulationClass.mars_date_time_steps(
|
|
496
|
-
dates,
|
|
497
|
-
step1,
|
|
498
|
-
step2,
|
|
499
|
-
data_accumulation_period,
|
|
500
|
-
base_times,
|
|
501
|
-
adjust_step,
|
|
849
|
+
dates=dates,
|
|
850
|
+
step1=step1,
|
|
851
|
+
step2=step2,
|
|
852
|
+
frequency=data_accumulation_period,
|
|
853
|
+
base_times=base_times,
|
|
854
|
+
adjust_step=adjust_step,
|
|
855
|
+
accumulations_reset_frequency=accumulations_reset_frequency,
|
|
856
|
+
user_date=user_date,
|
|
502
857
|
)
|
|
503
858
|
|
|
504
859
|
request = deepcopy(request)
|
|
@@ -527,18 +882,25 @@ def _compute_accumulations(
|
|
|
527
882
|
accumulations = {}
|
|
528
883
|
|
|
529
884
|
for date, time, steps in mars_date_time_steps:
|
|
885
|
+
LOG.info(f"Accumulation request: { date, time, steps}")
|
|
530
886
|
for p in param:
|
|
531
887
|
for n in number:
|
|
532
888
|
r = dict(request, param=p, date=date, time=time, step=sorted(steps), number=n)
|
|
533
889
|
|
|
534
890
|
requests.append(patch(r))
|
|
535
891
|
|
|
892
|
+
for r in requests:
|
|
893
|
+
LOG.info(f"Accumulation request: {r}")
|
|
894
|
+
|
|
536
895
|
ds = mars(
|
|
537
896
|
context, dates, *requests, request_already_using_valid_datetime=True, use_cdsapi_dataset=use_cdsapi_dataset
|
|
538
897
|
)
|
|
539
898
|
|
|
540
899
|
accumulations = {}
|
|
541
|
-
for a in [
|
|
900
|
+
for a in [
|
|
901
|
+
AccumulationClass(out, frequency=frequency, accumulations_reset_frequency=accumulations_reset_frequency, **r)
|
|
902
|
+
for r in requests
|
|
903
|
+
]:
|
|
542
904
|
for s in a.steps:
|
|
543
905
|
key = (a.param, a.date, a.time, s, a.number)
|
|
544
906
|
accumulations.setdefault(key, []).append(a)
|
|
@@ -654,6 +1016,8 @@ def accumulations(
|
|
|
654
1016
|
stream = request.get("stream", "oper")
|
|
655
1017
|
|
|
656
1018
|
user_accumulation_period = request.pop("accumulation_period", 6)
|
|
1019
|
+
accumulations_reset_frequency = request.pop("accumulations_reset_frequency", None)
|
|
1020
|
+
user_date = request.pop("date", None)
|
|
657
1021
|
|
|
658
1022
|
# If `data_accumulation_period` is not set, this means that the accumulations are from the start
|
|
659
1023
|
# of the forecast.
|
|
@@ -677,7 +1041,9 @@ def accumulations(
|
|
|
677
1041
|
dates,
|
|
678
1042
|
request,
|
|
679
1043
|
user_accumulation_period=user_accumulation_period,
|
|
1044
|
+
accumulations_reset_frequency=accumulations_reset_frequency,
|
|
680
1045
|
use_cdsapi_dataset=use_cdsapi_dataset,
|
|
1046
|
+
user_date=user_date,
|
|
681
1047
|
**kwargs,
|
|
682
1048
|
)
|
|
683
1049
|
|
|
@@ -25,7 +25,7 @@ def forcings(context: Any, dates: List[str], template: str, param: str) -> Any:
|
|
|
25
25
|
The context in which the function is executed.
|
|
26
26
|
dates : list
|
|
27
27
|
List of dates for which data is to be loaded.
|
|
28
|
-
template :
|
|
28
|
+
template : FieldList
|
|
29
29
|
Template for the data source.
|
|
30
30
|
param : str
|
|
31
31
|
Parameter for the data source.
|