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.
Files changed (29) hide show
  1. anemoi/datasets/_version.py +2 -2
  2. anemoi/datasets/check.py +93 -0
  3. anemoi/datasets/commands/check.py +101 -0
  4. anemoi/datasets/commands/copy.py +43 -3
  5. anemoi/datasets/commands/create.py +2 -3
  6. anemoi/datasets/commands/grib-index.py +0 -3
  7. anemoi/datasets/commands/inspect.py +2 -2
  8. anemoi/datasets/commands/scan.py +17 -5
  9. anemoi/datasets/create/__init__.py +19 -8
  10. anemoi/datasets/create/check.py +19 -1
  11. anemoi/datasets/create/input/action.py +2 -0
  12. anemoi/datasets/create/input/result.py +6 -2
  13. anemoi/datasets/create/sources/accumulations.py +400 -34
  14. anemoi/datasets/create/sources/forcings.py +1 -1
  15. anemoi/datasets/create/sources/grib.py +27 -181
  16. anemoi/datasets/create/sources/xarray_support/metadata.py +6 -0
  17. anemoi/datasets/create/sources/xarray_zarr.py +1 -1
  18. anemoi/datasets/create/writer.py +1 -1
  19. anemoi/datasets/data/complement.py +28 -11
  20. anemoi/datasets/data/forwards.py +4 -0
  21. anemoi/datasets/data/grids.py +3 -3
  22. anemoi/datasets/data/misc.py +1 -1
  23. anemoi/datasets/data/stores.py +36 -4
  24. {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/METADATA +5 -3
  25. {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/RECORD +29 -27
  26. {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/WHEEL +1 -1
  27. {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/entry_points.txt +0 -0
  28. {anemoi_datasets-0.5.20.dist-info → anemoi_datasets-0.5.22.dist-info}/licenses/LICENSE +0 -0
  29. {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
- """Initializes an Accumulation instance.
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
- self.out.write(
165
- self.values,
166
- template=template,
167
- stepType="accum",
168
- startStep=self.startStep,
169
- endStep=self.endStep,
170
- check_nans=True,
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 : np.ndarray
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.amin(values)} {np.amax(values)}")
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 self.buggy_steps and startStep == endStep:
201
- startStep = 0
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(base_date, step1, step2, add_step, frequency)
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
- def __repr__(self) -> str:
263
- """Returns a string representation of the Accumulation instance.
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
- str
268
- String representation of the Accumulation instance.
358
+ Tuple[int, int, Tuple[int, ...]]
359
+ A tuple representing the MARS date-time step.
269
360
  """
270
- return f"{self.__class__.__name__}({self.key})"
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
- buggy_steps = True
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, base_date: datetime.datetime, step1: int, step2: int, add_step: int, frequency: Optional[int]
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, base_date: datetime.datetime, step1: int, step2: int, add_step: int, frequency: int
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
- base_times = [0, 6, 12, 18]
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
- AccumulationClass = AccumulationFromStart if data_accumulation_period in (0, None) else AccumulationFromLastStep
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 [AccumulationClass(out, frequency=frequency, **r) for r in requests]:
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 : str
28
+ template : FieldList
29
29
  Template for the data source.
30
30
  param : str
31
31
  Parameter for the data source.