anemoi-datasets 0.5.5__py3-none-any.whl → 0.5.7__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.
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.5.5'
16
- __version_tuple__ = version_tuple = (0, 5, 5)
15
+ __version__ = version = '0.5.7'
16
+ __version_tuple__ = version_tuple = (0, 5, 7)
@@ -506,6 +506,10 @@ class Version0_6(Version):
506
506
  def variables(self):
507
507
  return self.metadata["variables"]
508
508
 
509
+ @property
510
+ def variables_metadata(self):
511
+ return self.metadata.get("variables_metadata", {})
512
+
509
513
 
510
514
  class Version0_12(Version0_6):
511
515
  def details(self):
@@ -25,6 +25,7 @@ from anemoi.utils.dates import frequency_to_string
25
25
  from anemoi.utils.dates import frequency_to_timedelta
26
26
  from anemoi.utils.humanize import compress_dates
27
27
  from anemoi.utils.humanize import seconds_to_human
28
+ from anemoi.utils.sanitise import sanitise
28
29
  from earthkit.data.core.order import build_remapping
29
30
 
30
31
  from anemoi.datasets import MissingDateError
@@ -52,7 +53,7 @@ from .writer import ViewCacheArray
52
53
 
53
54
  LOG = logging.getLogger(__name__)
54
55
 
55
- VERSION = "0.20"
56
+ VERSION = "0.30"
56
57
 
57
58
 
58
59
  def json_tidy(o):
@@ -325,43 +326,6 @@ def build_input_(main_config, output_config):
325
326
  return builder
326
327
 
327
328
 
328
- def tidy_recipe(config: object):
329
- """Remove potentially private information in the config"""
330
- config = deepcopy(config)
331
- if isinstance(config, (tuple, list)):
332
- return [tidy_recipe(_) for _ in config]
333
- if isinstance(config, (dict, DotDict)):
334
- for k, v in config.items():
335
- if k.startswith("_"):
336
- config[k] = "*** REMOVED FOR SECURITY ***"
337
- else:
338
- config[k] = tidy_recipe(v)
339
- if isinstance(config, str):
340
- if config.startswith("_"):
341
- return "*** REMOVED FOR SECURITY ***"
342
- if config.startswith("s3://"):
343
- return "*** REMOVED FOR SECURITY ***"
344
- if config.startswith("gs://"):
345
- return "*** REMOVED FOR SECURITY ***"
346
- if config.startswith("http"):
347
- return "*** REMOVED FOR SECURITY ***"
348
- if config.startswith("ftp"):
349
- return "*** REMOVED FOR SECURITY ***"
350
- if config.startswith("file"):
351
- return "*** REMOVED FOR SECURITY ***"
352
- if config.startswith("ssh"):
353
- return "*** REMOVED FOR SECURITY ***"
354
- if config.startswith("scp"):
355
- return "*** REMOVED FOR SECURITY ***"
356
- if config.startswith("rsync"):
357
- return "*** REMOVED FOR SECURITY ***"
358
- if config.startswith("/"):
359
- return "*** REMOVED FOR SECURITY ***"
360
- if "@" in config:
361
- return "*** REMOVED FOR SECURITY ***"
362
- return config
363
-
364
-
365
329
  class Init(Actor, HasRegistryMixin, HasStatisticTempMixin, HasElementForDataMixin):
366
330
  dataset_class = NewDataset
367
331
  def __init__(self, path, config, check_name=False, overwrite=False, use_threads=False, statistics_temp_dir=None, progress=None, test=False, cache=None, **kwargs): # fmt: skip
@@ -448,7 +412,7 @@ class Init(Actor, HasRegistryMixin, HasStatisticTempMixin, HasElementForDataMixi
448
412
  metadata.update(self.main_config.get("add_metadata", {}))
449
413
 
450
414
  metadata["_create_yaml_config"] = self.main_config.get_serialisable_dict()
451
- metadata["recipe"] = tidy_recipe(self.main_config.get_serialisable_dict())
415
+ metadata["recipe"] = sanitise(self.main_config.get_serialisable_dict())
452
416
 
453
417
  metadata["description"] = self.main_config.description
454
418
  metadata["licence"] = self.main_config["licence"]
@@ -467,6 +431,7 @@ class Init(Actor, HasRegistryMixin, HasStatisticTempMixin, HasElementForDataMixi
467
431
  metadata["data_request"] = self.minimal_input.data_request
468
432
  metadata["field_shape"] = self.minimal_input.field_shape
469
433
  metadata["proj_string"] = self.minimal_input.proj_string
434
+ metadata["variables_metadata"] = self.minimal_input.variables_metadata
470
435
 
471
436
  metadata["start_date"] = dates[0].isoformat()
472
437
  metadata["end_date"] = dates[-1].isoformat()
@@ -42,7 +42,7 @@ def load_one(emoji, context, dates, dataset, options={}, flavour=None, **kwargs)
42
42
  We have seen this bug triggered when we run many clients in parallel, for example, when we create a new dataset using `xarray-zarr`.
43
43
  """
44
44
 
45
- context.trace(emoji, dataset, options)
45
+ context.trace(emoji, dataset, options, kwargs)
46
46
 
47
47
  if isinstance(dataset, str) and ".zarr" in dataset:
48
48
  data = xr.open_zarr(name_to_zarr_store(dataset), **options)
@@ -30,6 +30,8 @@ def extract_single_value(variable):
30
30
  if np.issubdtype(variable.values.dtype, np.datetime64):
31
31
  if len(shape) == 0:
32
32
  return to_datetime(variable.values) # Convert to python datetime
33
+ if shape == (1,):
34
+ return to_datetime(variable.values[0])
33
35
  assert False, (shape, variable.values[:2])
34
36
 
35
37
  if np.issubdtype(variable.values.dtype, np.timedelta64):
@@ -244,3 +246,9 @@ class ScalarCoordinate(Coordinate):
244
246
  @property
245
247
  def mars_names(self):
246
248
  return (self.variable.name,)
249
+
250
+
251
+ class UnsupportedCoordinate(Coordinate):
252
+ @property
253
+ def mars_names(self):
254
+ return (self.variable.name,)
@@ -18,6 +18,7 @@ from .coordinates import LongitudeCoordinate
18
18
  from .coordinates import ScalarCoordinate
19
19
  from .coordinates import StepCoordinate
20
20
  from .coordinates import TimeCoordinate
21
+ from .coordinates import UnsupportedCoordinate
21
22
  from .coordinates import XCoordinate
22
23
  from .coordinates import YCoordinate
23
24
  from .coordinates import is_scalar
@@ -157,11 +158,13 @@ class CoordinateGuesser:
157
158
  if c.shape in ((1,), tuple()):
158
159
  return ScalarCoordinate(c)
159
160
 
160
- raise NotImplementedError(
161
+ LOG.warning(
161
162
  f"Coordinate {coord} not supported\n{axis=}, {name=},"
162
163
  f" {long_name=}, {standard_name=}, units\n\n{c}\n\n{type(c.values)} {c.shape}"
163
164
  )
164
165
 
166
+ return UnsupportedCoordinate(c)
167
+
165
168
  def grid(self, coordinates, variable):
166
169
  lat = [c for c in coordinates if c.is_lat]
167
170
  lon = [c for c in coordinates if c.is_lon]
@@ -225,20 +228,15 @@ class CoordinateGuesser:
225
228
  x = x[0]
226
229
  y = y[0]
227
230
 
228
- _, unstructured = self._check_dims(variable, x, y)
229
-
230
- if x.variable.dims != y.variable.dims:
231
- raise ValueError(f"Dimensions do not match {x.name}{x.variable.dims} != {y.name}{y.variable.dims}")
232
-
233
- if (x.name, y.name) in self._cache:
234
- return self._cache[(x.name, y.name)]
231
+ dim_vars, unstructured = self._check_dims(variable, x, y)
235
232
 
236
- if (x.name, y.name) in self._cache:
237
- return self._cache[(x.name, y.name)]
238
-
239
- assert len(x.variable.shape) == len(y.variable.shape), (x.variable.shape, y.variable.shape)
233
+ if (x.name, y.name, dim_vars) in self._cache:
234
+ return self._cache[(x.name, y.name, dim_vars)]
240
235
 
241
236
  grid_mapping = variable.attrs.get("grid_mapping", None)
237
+ if grid_mapping is not None:
238
+ print(f"grid_mapping: {grid_mapping}")
239
+ print(self.ds[grid_mapping])
242
240
 
243
241
  if grid_mapping is None:
244
242
  LOG.warning(f"No 'grid_mapping' attribute provided for '{variable.name}'")
@@ -285,11 +283,19 @@ class CoordinateGuesser:
285
283
  grid_mapping = self.ds.attrs["crs"]
286
284
  LOG.warning(f"Using CRS {grid_mapping} from global attributes")
287
285
 
286
+ grid = None
288
287
  if grid_mapping is not None:
288
+
289
+ grid_mapping = dict(self.ds[grid_mapping].attrs)
290
+
289
291
  if unstructured:
290
- return UnstructuredProjectionGrid(x, y, grid_mapping)
292
+ grid = UnstructuredProjectionGrid(x, y, grid_mapping)
291
293
  else:
292
- return MeshProjectionGrid(x, y, grid_mapping)
294
+ grid = MeshProjectionGrid(x, y, grid_mapping)
295
+
296
+ if grid is not None:
297
+ self._cache[(x.name, y.name, dim_vars)] = grid
298
+ return grid
293
299
 
294
300
  LOG.error("Could not fine a candidate for 'grid_mapping'")
295
301
  raise NotImplementedError(f"Unstructured grid {x.name} {y.name}")
@@ -337,12 +343,14 @@ class DefaultCoordinateGuesser(CoordinateGuesser):
337
343
  if standard_name == "time":
338
344
  return TimeCoordinate(c)
339
345
 
340
- if name == "time":
346
+ # That is the output of `cfgrib` for forecasts
347
+ if name == "time" and standard_name != "forecast_reference_time":
341
348
  return TimeCoordinate(c)
342
349
 
343
350
  def _is_date(self, c, *, axis, name, long_name, standard_name, units):
344
351
  if standard_name == "forecast_reference_time":
345
352
  return DateCoordinate(c)
353
+
346
354
  if name == "forecast_reference_time":
347
355
  return DateCoordinate(c)
348
356
 
@@ -100,6 +100,7 @@ class ProjectionGrid(XYGrid):
100
100
  data_crs = CRS.from_cf(self.projection)
101
101
  else:
102
102
  data_crs = self.projection
103
+
103
104
  wgs84_crs = CRS.from_epsg(4326) # WGS84
104
105
 
105
106
  return Transformer.from_crs(data_crs, wgs84_crs, always_xy=True)
@@ -9,9 +9,12 @@
9
9
 
10
10
 
11
11
  import datetime
12
+ import logging
12
13
 
13
14
  from anemoi.utils.dates import as_datetime
14
15
 
16
+ LOG = logging.getLogger(__name__)
17
+
15
18
 
16
19
  class Time:
17
20
 
@@ -36,7 +39,28 @@ class Time:
36
39
  if len(date_coordinate) == 1 and len(time_coordinate) == 0 and len(step_coordinate) == 1:
37
40
  return ForecastFromBaseTimeAndDate(date_coordinate[0], step_coordinate[0])
38
41
 
39
- raise NotImplementedError(f"{date_coordinate=} {time_coordinate=} {step_coordinate=}")
42
+ if len(date_coordinate) == 1 and len(time_coordinate) == 1 and len(step_coordinate) == 1:
43
+ return ForecastFromValidTimeAndStep(time_coordinate[0], step_coordinate[0], date_coordinate[0])
44
+
45
+ LOG.error("")
46
+ LOG.error(f"{len(date_coordinate)} date_coordinate")
47
+ for c in date_coordinate:
48
+ LOG.error(" %s %s %s %s", c, c.is_date, c.is_time, c.is_step)
49
+ # LOG.error(' %s', c.variable)
50
+
51
+ LOG.error("")
52
+ LOG.error(f"{len(time_coordinate)} time_coordinate")
53
+ for c in time_coordinate:
54
+ LOG.error(" %s %s %s %s", c, c.is_date, c.is_time, c.is_step)
55
+ # LOG.error(' %s', c.variable)
56
+
57
+ LOG.error("")
58
+ LOG.error(f"{len(step_coordinate)} step_coordinate")
59
+ for c in step_coordinate:
60
+ LOG.error(" %s %s %s %s", c, c.is_date, c.is_time, c.is_step)
61
+ # LOG.error(' %s', c.variable)
62
+
63
+ raise NotImplementedError(f"{len(date_coordinate)=} {len(time_coordinate)=} {len(step_coordinate)=}")
40
64
 
41
65
 
42
66
  class Constant(Time):
@@ -62,9 +86,10 @@ class Analysis(Time):
62
86
 
63
87
  class ForecastFromValidTimeAndStep(Time):
64
88
 
65
- def __init__(self, time_coordinate, step_coordinate):
89
+ def __init__(self, time_coordinate, step_coordinate, date_coordinate=None):
66
90
  self.time_coordinate_name = time_coordinate.variable.name
67
91
  self.step_coordinate_name = step_coordinate.variable.name
92
+ self.date_coordinate_name = date_coordinate.variable.name if date_coordinate else None
68
93
 
69
94
  def fill_time_metadata(self, coords_values, metadata):
70
95
  valid_datetime = coords_values[self.time_coordinate_name]
@@ -79,6 +104,16 @@ class ForecastFromValidTimeAndStep(Time):
79
104
  metadata["date"] = as_datetime(base_datetime).strftime("%Y%m%d")
80
105
  metadata["time"] = as_datetime(base_datetime).strftime("%H%M")
81
106
  metadata["step"] = int(hours)
107
+
108
+ # When date is present, it should be compatible with time and step
109
+
110
+ if self.date_coordinate_name is not None:
111
+ # Not sure that this is the correct assumption
112
+ assert coords_values[self.date_coordinate_name] == base_datetime, (
113
+ coords_values[self.date_coordinate_name],
114
+ base_datetime,
115
+ )
116
+
82
117
  return valid_datetime
83
118
 
84
119
 
@@ -30,6 +30,31 @@ from .trace import trace_datasource
30
30
  LOG = logging.getLogger(__name__)
31
31
 
32
32
 
33
+ def _fields_metatata(variables, cube):
34
+ assert isinstance(variables, tuple), variables
35
+
36
+ result = {}
37
+ for i, c in enumerate(cube.iterate_cubelets()):
38
+ assert c._coords_names[1] == variables[i], (c._coords_names[1], variables[i])
39
+ f = cube[c.coords]
40
+ md = f.metadata(namespace="mars")
41
+ if not md:
42
+ md = f.metadata(namespace="default")
43
+
44
+ if md.get("param") == "~":
45
+ md["param"] = f.metadata("param")
46
+ assert md["param"] not in ("~", "unknown"), (md, f.metadata("param"))
47
+
48
+ if md.get("param") == "unknown":
49
+ md["param"] = str(f.metadata("paramId", default="unknown"))
50
+ # assert md['param'] != 'unknown', (md, f.metadata('param'))
51
+
52
+ result[variables[i]] = md
53
+
54
+ assert i + 1 == len(variables), (i + 1, len(variables))
55
+ return result
56
+
57
+
33
58
  def _data_request(data):
34
59
  date = None
35
60
  params_levels = defaultdict(set)
@@ -312,7 +337,10 @@ class Result:
312
337
  def build_coords(self):
313
338
  if self._coords_already_built:
314
339
  return
315
- from_data = self.get_cube().user_coords
340
+
341
+ cube = self.get_cube()
342
+
343
+ from_data = cube.user_coords
316
344
  from_config = self.context.order_by
317
345
 
318
346
  keys_from_config = list(from_config.keys())
@@ -359,11 +387,19 @@ class Result:
359
387
  self._field_shape = first_field.shape
360
388
  self._proj_string = first_field.proj_string if hasattr(first_field, "proj_string") else None
361
389
 
390
+ self._cube = cube
391
+
392
+ self._coords_already_built = True
393
+
362
394
  @property
363
395
  def variables(self):
364
396
  self.build_coords()
365
397
  return self._variables
366
398
 
399
+ @property
400
+ def variables_metadata(self):
401
+ return _fields_metatata(self.variables, self._cube)
402
+
367
403
  @property
368
404
  def ensembles(self):
369
405
  self.build_coords()
@@ -56,8 +56,11 @@ class PersistentDict:
56
56
  yield pickle.load(f)
57
57
 
58
58
  def add_provenance(self, **kwargs):
59
+ path = os.path.join(self.dirname, "provenance.json")
60
+ if os.path.exists(path):
61
+ return
59
62
  out = dict(provenance=gather_provenance_info(), **kwargs)
60
- with open(os.path.join(self.dirname, "provenance.json"), "w") as f:
63
+ with open(path, "w") as f:
61
64
  json.dump(out, f)
62
65
 
63
66
  def add(self, elt, *, key):
@@ -187,8 +187,11 @@ class TmpStatistics:
187
187
 
188
188
  def add_provenance(self, **kwargs):
189
189
  self.create(exist_ok=True)
190
+ path = os.path.join(self.dirname, "provenance.json")
191
+ if os.path.exists(path):
192
+ return
190
193
  out = dict(provenance=gather_provenance_info(), **kwargs)
191
- with open(os.path.join(self.dirname, "provenance.json"), "w") as f:
194
+ with open(path, "w") as f:
192
195
  json.dump(out, f)
193
196
 
194
197
  def create(self, exist_ok):
@@ -168,7 +168,11 @@ class ZarrBuiltRegistry:
168
168
  return self.create(lengths, overwrite=True)
169
169
 
170
170
  def add_provenance(self, name):
171
+ z = self._open_write()
172
+
173
+ if name in z.attrs:
174
+ return
175
+
171
176
  from anemoi.utils.provenance import gather_provenance_info
172
177
 
173
- z = self._open_write()
174
178
  z.attrs[name] = gather_provenance_info()
@@ -63,6 +63,10 @@ class Forwards(Dataset):
63
63
  def variables(self):
64
64
  return self.forward.variables
65
65
 
66
+ @property
67
+ def variables_metadata(self):
68
+ return self.forward.variables_metadata
69
+
66
70
  @property
67
71
  def statistics(self):
68
72
  return self.forward.statistics
@@ -253,7 +257,6 @@ class GivenAxis(Combined):
253
257
  offset = 0
254
258
  result = set()
255
259
  for d in self.datasets:
256
- print("--->", d.missing, d)
257
260
  result.update(offset + m for m in d.missing)
258
261
  if self.axis == 0: # Advance if axis is time
259
262
  offset += len(d)
@@ -111,6 +111,19 @@ class Join(Combined):
111
111
 
112
112
  return result
113
113
 
114
+ @cached_property
115
+ def variables_metadata(self):
116
+ seen = set()
117
+ result = {}
118
+ for d in reversed(self.datasets):
119
+ for v in reversed(d.variables):
120
+ while v in seen:
121
+ v = f"({v})"
122
+ seen.add(v)
123
+ result[v] = d.variables_metadata[v]
124
+
125
+ return result
126
+
114
127
  @cached_property
115
128
  def name_to_index(self):
116
129
  return {k: i for i, k in enumerate(self.variables)}
@@ -76,6 +76,10 @@ class Select(Forwards):
76
76
  def variables(self):
77
77
  return [self.dataset.variables[i] for i in self.indices]
78
78
 
79
+ @cached_property
80
+ def variables_metadata(self):
81
+ return {k: v for k, v in self.dataset.variables_metadata.items() if k in self.variables}
82
+
79
83
  @cached_property
80
84
  def name_to_index(self):
81
85
  return {k: i for i, k in enumerate(self.variables)}
@@ -108,13 +112,20 @@ class Rename(Forwards):
108
112
  super().__init__(dataset)
109
113
  for n in rename:
110
114
  assert n in dataset.variables, n
115
+
111
116
  self._variables = [rename.get(v, v) for v in dataset.variables]
117
+ self._variables_metadata = {rename.get(k, k): v for k, v in dataset.variables_metadata.items()}
118
+
112
119
  self.rename = rename
113
120
 
114
121
  @property
115
122
  def variables(self):
116
123
  return self._variables
117
124
 
125
+ @property
126
+ def variables_metadata(self):
127
+ return self._variables_metadata
128
+
118
129
  @cached_property
119
130
  def name_to_index(self):
120
131
  return {k: i for i, k in enumerate(self.variables)}
@@ -302,6 +302,10 @@ class Zarr(Dataset):
302
302
  )
303
303
  ]
304
304
 
305
+ @property
306
+ def variables_metadata(self):
307
+ return self.z.attrs.get("variables_metadata", {})
308
+
305
309
  def __repr__(self):
306
310
  return self.path
307
311
 
@@ -91,6 +91,11 @@ class Unchecked(Combined):
91
91
  def variables(self):
92
92
  raise NotImplementedError()
93
93
 
94
+ @property
95
+ @check("check_same_variables")
96
+ def variables_metadata(self):
97
+ raise NotImplementedError()
98
+
94
99
  @property
95
100
  @check("check_same_variables")
96
101
  def statistics(self):
@@ -0,0 +1,59 @@
1
+ # (C) Copyright 2024 ECMWF.
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
+ # In applying this licence, ECMWF does not waive the privileges and immunities
6
+ # granted to it by virtue of its status as an intergovernmental organisation
7
+ # nor does it submit to any jurisdiction.
8
+ #
9
+
10
+ # A collection of functions to support pytest testing
11
+
12
+ import logging
13
+
14
+ LOG = logging.getLogger(__name__)
15
+
16
+
17
+ def assert_field_list(fs, size=None, start=None, end=None, constant=False, skip=None):
18
+ import numpy as np
19
+
20
+ if size is None:
21
+ assert len(fs) > 0, fs
22
+ else:
23
+ assert len(fs) == size, (len(fs), size)
24
+
25
+ first = fs[0]
26
+ last = fs[-1]
27
+
28
+ if constant:
29
+ # TODO: add a check for constant fields
30
+ pass
31
+ else:
32
+ assert start is None or first.metadata("valid_datetime") == start, (first.metadata("valid_datetime"), start)
33
+ assert end is None or last.metadata("valid_datetime") == end, (last.metadata("valid_datetime"), end)
34
+ print(first.datetime())
35
+
36
+ print(last.metadata())
37
+
38
+ first = first
39
+ latitudes, longitudes = first.grid_points()
40
+
41
+ assert len(latitudes.shape) == 1, latitudes.shape
42
+ assert len(longitudes.shape) == 1, longitudes.shape
43
+
44
+ assert len(latitudes) == len(longitudes), (len(latitudes), len(longitudes))
45
+ data = first.to_numpy(flatten=True)
46
+
47
+ assert len(data) == len(latitudes), (len(data), len(latitudes))
48
+
49
+ north = np.max(latitudes)
50
+ south = np.min(latitudes)
51
+ east = np.max(longitudes)
52
+ west = np.min(longitudes)
53
+
54
+ assert north >= south, (north, south)
55
+ assert east >= west, (east, west)
56
+ assert north <= 90, north
57
+ assert south >= -90, south
58
+ assert east <= 360, east
59
+ assert west >= -180, west
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: anemoi-datasets
3
- Version: 0.5.5
3
+ Version: 0.5.7
4
4
  Summary: A package to hold various functions to support training of ML models on ECMWF data.
5
5
  Author-email: "European Centre for Medium-Range Weather Forecasts (ECMWF)" <software.support@ecmwf.int>
6
6
  License: Apache License
@@ -1,8 +1,9 @@
1
1
  anemoi/datasets/__init__.py,sha256=Z1gqZWhecLcT0RZQqYBLlz01MUlUZd0kWEj_RavbITM,782
2
2
  anemoi/datasets/__main__.py,sha256=cLA2PidDTOUHaDGzd0_E5iioKYNe-PSTv567Y2fuwQk,723
3
- anemoi/datasets/_version.py,sha256=q2mmmMeZBj38-RlMPxNZk3zblQ8jPjzN_oIC744dsOc,411
3
+ anemoi/datasets/_version.py,sha256=WG2gUkVRG4TIqG0-naezn012emNIbgERkkZYUI1CHww,411
4
4
  anemoi/datasets/fields.py,sha256=95TYAfqS_kZp1bzj84GngurVfyVvziVBy3zpUyoturI,1968
5
5
  anemoi/datasets/grids.py,sha256=xgvIbpMGuN2GKi2wIBhOLEMzj940nY9PH-toD0rCmPo,8980
6
+ anemoi/datasets/testing.py,sha256=xtJBYywbsciaMp9NZ4jkjI4TdddCSkqqCCwSEHNwaNM,1810
6
7
  anemoi/datasets/commands/__init__.py,sha256=qAybFZPBBQs0dyx7dZ3X5JsLpE90pwrqt1vSV7cqEIw,706
7
8
  anemoi/datasets/commands/cleanup.py,sha256=_BkzGPUgvSqnuleymBfBx-sIyIM55hjK61m-v7yK0T8,1062
8
9
  anemoi/datasets/commands/compare.py,sha256=svEhyR7pOS1847_RJr1I6vF7ZDPB9AVlcrhy_gxQVms,3263
@@ -12,7 +13,7 @@ anemoi/datasets/commands/finalise-additions.py,sha256=876K37hVjslHJiu9VXZfre4YJh
12
13
  anemoi/datasets/commands/finalise.py,sha256=oPul5za7E__eJqkf5fRwvdL_0n2nG5Xk3JraRZQe64k,913
13
14
  anemoi/datasets/commands/init-additions.py,sha256=K3eKH5V_6ERiBKKyqIUuI1cfvAsjWV9ZAFzbtjIDyjs,1146
14
15
  anemoi/datasets/commands/init.py,sha256=7BpWaZ4gzMMiRqD9djHRciQNa0W2R4cOzoy5R-UJ0ck,2033
15
- anemoi/datasets/commands/inspect.py,sha256=kaEQhj_PcrcQwbz5uRhDblaa_IwZmKpGaboSrsQNi0Y,18714
16
+ anemoi/datasets/commands/inspect.py,sha256=RFOkw0rB72kR3CGb-JRyb0-oh9zKois8ddeQwDWWKhQ,18822
16
17
  anemoi/datasets/commands/load-additions.py,sha256=Tg4FX0xealmwyB--zv03ZBrqTAGddkT0rKrHlcu4VW0,1234
17
18
  anemoi/datasets/commands/load.py,sha256=3jhL3DKUg07C8D6L8RsRWciq8korYsJ40_9atp-p68U,1304
18
19
  anemoi/datasets/commands/patch.py,sha256=gHY16r46GHxARItaAUHVjKSOm0Q7ZyZvSZmXqg1Wnig,841
@@ -20,16 +21,16 @@ anemoi/datasets/commands/publish.py,sha256=HV8W4wFOD7RB-Fn0qzkwyVoyZyaGsx8MUGFa5
20
21
  anemoi/datasets/commands/scan.py,sha256=MaTdne4JrtlqO3LhOUr43DZhZ6O-RZwC7uQ7C6PG7Os,2910
21
22
  anemoi/datasets/compute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  anemoi/datasets/compute/recentre.py,sha256=CMvRxTMv2H1hF1KqaZHT3Maa9P01GtsgAxr1YHbvH_o,4939
23
- anemoi/datasets/create/__init__.py,sha256=e5DaAuUdqUGeTaPnF-6vmV-_Rl2xWTt3elyB36E7W24,36554
24
+ anemoi/datasets/create/__init__.py,sha256=rJjN17VUExSeGXPN1UwU005a1x_ERfWMeZGZje0BJfI,35221
24
25
  anemoi/datasets/create/check.py,sha256=j0vaA7y7dEYsgvAJVGhTZgjhWgvu7DDF1Bl-JkKxFcU,6128
25
26
  anemoi/datasets/create/chunks.py,sha256=1Inh3sIBn-2sNguErb-BsLns6W_HtDiOJAjIb29lp-U,2442
26
27
  anemoi/datasets/create/config.py,sha256=IqWsW_AVcp0uA2M1IPB-TT0IWjquvZL2R7PeiviOb4Y,8882
27
28
  anemoi/datasets/create/patch.py,sha256=c8cWoqxFzcY9mKREosLjuQCUeJMJL6sbNNkoVvhCZDA,3800
28
- anemoi/datasets/create/persistent.py,sha256=isENKsd6OievmNfe1rF6_3mY7X4HjaXGIrVIfH82JKY,4294
29
+ anemoi/datasets/create/persistent.py,sha256=ts4p4ouQdin9Mu9mZMQDgENjFTjUgmzXogeRcqF6EZ0,4366
29
30
  anemoi/datasets/create/size.py,sha256=k4COEjs3wud0oKHH5P3n8Fap35xddXs002ucPjpBC88,1040
30
31
  anemoi/datasets/create/utils.py,sha256=v0dyQUk3hWOVQeZ82pnH3GmRwENXIHSwlwB7qqnomuU,2708
31
32
  anemoi/datasets/create/writer.py,sha256=G1qAPvdn8anGnpWYhvSSP4u3Km_tHKPdMXm0G4skKSk,1379
32
- anemoi/datasets/create/zarr.py,sha256=5m6YdC2Bj9iZObPohDcR1MacFQ9v1wA0OV4kSUwZtj8,5442
33
+ anemoi/datasets/create/zarr.py,sha256=eNhopqcNSWtuJ_ltQIGdHVL2bGFRhS4Q6KkxAZ9s-Jw,5491
33
34
  anemoi/datasets/create/functions/__init__.py,sha256=5HmelLkXDjFOhNhX0Z78aV3ZlW2txiJliJwT4jfLEN4,945
34
35
  anemoi/datasets/create/functions/filters/__init__.py,sha256=Xe9G54CKvCI3ji-7k0R5l0WZZdhlydRgawsXuBcX_hg,379
35
36
  anemoi/datasets/create/functions/filters/empty.py,sha256=QGj7YEfbo3gwlmwHi1lPATjST0332TH2-uc6_wKENjI,621
@@ -61,14 +62,14 @@ anemoi/datasets/create/functions/sources/tendencies.py,sha256=4hFPGU51KnxXp-KteS
61
62
  anemoi/datasets/create/functions/sources/xarray_kerchunk.py,sha256=JsuGjTs5BQdJIPRI8TuUNde680UQkT4GbUhOt6wYy38,1432
62
63
  anemoi/datasets/create/functions/sources/xarray_zarr.py,sha256=qI_fEKo28hu_B_qMPx67gigysw8qw5ePMU9P0wbDcIc,531
63
64
  anemoi/datasets/create/functions/sources/zenodo.py,sha256=n7_sfZHJVDjVnSwc07muO9kS7TwOM4S8DIlJf5pnDiU,1237
64
- anemoi/datasets/create/functions/sources/xarray/__init__.py,sha256=Ft3p7k8WEz3kBc26b1hWuk2y_13_SdPuizwKRb6cLi0,2954
65
- anemoi/datasets/create/functions/sources/xarray/coordinates.py,sha256=0iOu2qKTBfaegLYXQA1EEi2bRDL5m2H1hwYfuLjBQk4,6001
65
+ anemoi/datasets/create/functions/sources/xarray/__init__.py,sha256=0HMGeuI2y-DlQJiikYvBLkZeLwdKCWggAadzXnRiMho,2962
66
+ anemoi/datasets/create/functions/sources/xarray/coordinates.py,sha256=NgOlA7426pdhq20IKJv2-mrBnjFSFO4asPgcXQph05c,6198
66
67
  anemoi/datasets/create/functions/sources/xarray/field.py,sha256=3xy14ywRxYydvxucDlE8g6PeKfP5mcc5NL-2mGDv9nU,3658
67
68
  anemoi/datasets/create/functions/sources/xarray/fieldlist.py,sha256=GnYbierm_TuTPMG9WOn99QBi1DxaFo0hra69KGvSiEg,5589
68
- anemoi/datasets/create/functions/sources/xarray/flavour.py,sha256=8jkV-wUlze2IVQ2WLnfj9-5INYhat3Gw3ERFOrf_VqM,14667
69
- anemoi/datasets/create/functions/sources/xarray/grid.py,sha256=h3O20PsdpJc9V_oae_WEUw8qMnalV_4yjFNAZHvuxPI,3629
69
+ anemoi/datasets/create/functions/sources/xarray/flavour.py,sha256=17bnp_VQ4lRIEMYz4JC6_XBbn56UoknX74SYVhgO_Yk,14841
70
+ anemoi/datasets/create/functions/sources/xarray/grid.py,sha256=ND9TSNxg-_8gGhXLzCo_CFoTrZXLWLYjsF-d88AKr28,3630
70
71
  anemoi/datasets/create/functions/sources/xarray/metadata.py,sha256=TSFQ_2ijVtEiXdwnjYr9wPRsTBwqfo_pNNZDFPXFAts,4558
71
- anemoi/datasets/create/functions/sources/xarray/time.py,sha256=6IXwu9gI1e4LjZ6L6-Bgnq2LgRXvSmkujFWEFTxOymA,4491
72
+ anemoi/datasets/create/functions/sources/xarray/time.py,sha256=494pqiQ2p9cryXobGsuf5AgvMBzionKTpnyVoI0HtiA,5973
72
73
  anemoi/datasets/create/functions/sources/xarray/variable.py,sha256=tJUiJCPJ6Ft-U9isaEv8vLzPk52Dnnss9zTJX1hXQvI,4522
73
74
  anemoi/datasets/create/input/__init__.py,sha256=v9hJbgkH5hl3Zp5papYHwyEJ3JF2u4ILiTfnjJ1oOpI,2135
74
75
  anemoi/datasets/create/input/action.py,sha256=qMKyQLTjAJDBey_1_iIbI6_bqdNVyXarJzDtCH4kiRM,4188
@@ -82,11 +83,11 @@ anemoi/datasets/create/input/join.py,sha256=uvsIio-KMP3aaZyHK2k_7sdsqYbgIoqKQQ3D
82
83
  anemoi/datasets/create/input/misc.py,sha256=HhCVxVeONqdV7WiiYiAeZb3_QeoR0gcVgAAanon6U4Y,2306
83
84
  anemoi/datasets/create/input/pipe.py,sha256=YBEAypMXaaWRzwZQCRG0oQwvwSmZhNCAa_1hPlYJuvc,1170
84
85
  anemoi/datasets/create/input/repeated_dates.py,sha256=NueAwQ8uwD54FQEOzHfPGEC8iw7HRiTmdSR2ytFdWrw,6536
85
- anemoi/datasets/create/input/result.py,sha256=p903jet3hY9g0_Um-COUUsdSIqmGsgD8BUlx16_ZAks,13754
86
+ anemoi/datasets/create/input/result.py,sha256=35wCEKwmybe5uuTigqmESh_y_JB-KgTqLT_f2_lIqhQ,14804
86
87
  anemoi/datasets/create/input/step.py,sha256=Jvl3QpkNgSIkhdc2ekrCMlqSWmP9fPXD0CvPYcocAsM,3133
87
88
  anemoi/datasets/create/input/template.py,sha256=-prOGI7vbcqph4uS-Mf5-mQ1ws3LbdFzKZxx4d7Ojp8,1844
88
89
  anemoi/datasets/create/input/trace.py,sha256=J-8jDy28wNZa4aSV1KIQMwc1KolcoH3R2xjLl-_eLzM,2183
89
- anemoi/datasets/create/statistics/__init__.py,sha256=oMwWQ-LteeaVFqu6hzKEcsRz_5KMjzDbwIZ_1HEIvto,12699
90
+ anemoi/datasets/create/statistics/__init__.py,sha256=HphcJfdD6mYxhH8hzDMAcSFH3wblHW_ZONT70qX-BYI,12771
90
91
  anemoi/datasets/create/statistics/summary.py,sha256=sgmhA24y3VRyjmDUgTnPIqcHSlWBbFA0qynx6gJ9Xw8,3370
91
92
  anemoi/datasets/data/__init__.py,sha256=usTH1SLkeveBbYkbBTc7rP4G3mCGNa8A74vPjXjlOSw,1067
92
93
  anemoi/datasets/data/concat.py,sha256=SYASNNngnAyz3rC4ENzrGAu91rnhd6uwP0kGX9aMZAQ,5269
@@ -94,28 +95,28 @@ anemoi/datasets/data/dataset.py,sha256=GS-V1rHze1qynIBz56PQOpQMVzWcSpbIppZ7-SLtY
94
95
  anemoi/datasets/data/debug.css,sha256=z2X_ZDSnZ9C3pyZPWnQiEyAxuMxUaxJxET4oaCImTAQ,211
95
96
  anemoi/datasets/data/debug.py,sha256=xNpFeJqdlN9Qhlhbp4pxXJP0dQTf0V4bm2cK4hsrSJM,6326
96
97
  anemoi/datasets/data/ensemble.py,sha256=AsP7Xx0ZHLoZs6a4EC0jtyGYIcOvZvvKXhgNsIvqIN8,1137
97
- anemoi/datasets/data/forwards.py,sha256=SfB3o8Y-nQEOkS5gI_6wtipvzB5peF_YkwW9cOMhLMg,8167
98
+ anemoi/datasets/data/forwards.py,sha256=-5h18GgkSOH_sNRpwJ8ZGv_KuJkPqzmCDwljPStAQHI,8223
98
99
  anemoi/datasets/data/grids.py,sha256=KiHpN1Ne0DnQM42buBy0sIAZHNaC2kuEFwkk6ohIooU,8046
99
100
  anemoi/datasets/data/indexing.py,sha256=625m__JG5m_tDMrkz1hB6Vydenwt0oHuyAlc-o3Zwos,4799
100
101
  anemoi/datasets/data/interpolate.py,sha256=usnYgjoDPfnUNg_lZl3KsFTsJ7kOsf7YaHwarsBU7Ag,4163
101
- anemoi/datasets/data/join.py,sha256=dtCBbMTicqrRPxfBULi3RwEcQBLhQpIcvCjdN5A3XUU,4892
102
+ anemoi/datasets/data/join.py,sha256=mmCSJVLsdY1qBLJ5pLQvC5n6-cJB-u40xoUP5ffaOd0,5244
102
103
  anemoi/datasets/data/masked.py,sha256=GKAKHwiiVrDX13V_mDiQ3G1Y7zXSksc0IkABPEvVw-M,3825
103
104
  anemoi/datasets/data/misc.py,sha256=8ZaLhgHmUmP77X0_6scp36BJJzz544nHVQRAamW6x-Y,9821
104
105
  anemoi/datasets/data/missing.py,sha256=OyW8cRow1v641Vgv-IY5BnUxH2Ob5P2QjgrVR1Szjl0,7157
105
106
  anemoi/datasets/data/rescale.py,sha256=c_onY5f-2XDGmLP5mawNFueQWNS-BnTpo6xaBJF4aWA,4138
106
- anemoi/datasets/data/select.py,sha256=tProUPIiRwSe_H9cwwn_4iMX1uZEIQ7q5KsegBgSmdc,3971
107
+ anemoi/datasets/data/select.py,sha256=HiTFpZm5RVD2Vck4tjtFABUuIQYuYz_F09GrnIvnFDU,4319
107
108
  anemoi/datasets/data/statistics.py,sha256=lZCcKw9s7ttMBEp6ANyxtbXoZZvchhE7SClq-D4AUR8,1645
108
- anemoi/datasets/data/stores.py,sha256=7CRqiAzOq71pzRezC2f_elTRDmJQzfu8bi0vrnylatI,12194
109
+ anemoi/datasets/data/stores.py,sha256=w8SgIGV7YlysazF6FLAVd81EQcAyWbj9RhR6svp1_iU,12301
109
110
  anemoi/datasets/data/subset.py,sha256=peyHlIvno0uUzqW0HS9zjqThmyXn6rpvVWh-925XHnE,4692
110
- anemoi/datasets/data/unchecked.py,sha256=xLOCU-O3OpfAi3bd-XZEpfDTnZfFGqdhh55d8D_u3wQ,4184
111
+ anemoi/datasets/data/unchecked.py,sha256=4qqHuDJNQ89HDOQFsSVACRYpT34xgxYpiH4T6J16HXE,4304
111
112
  anemoi/datasets/data/xy.py,sha256=_k1z_2INvA0v7zsm5lxfVvf7ymBFu6Tr9PxvtdB9kFg,3002
112
113
  anemoi/datasets/dates/__init__.py,sha256=-RcoD33OQl4GOL92r7ksT8014KhvURjUCb1C9SNXjp0,7970
113
114
  anemoi/datasets/dates/groups.py,sha256=7zXEtMwFWFFQarKNyNDLxpTu7OFiZWSYIrvAIeWLEPg,5391
114
115
  anemoi/datasets/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
116
  anemoi/datasets/utils/fields.py,sha256=VWf9PPmJ1WU1-oJ5tNkbC3_ik9gqnFxqwrc1EFysBYk,1397
116
- anemoi_datasets-0.5.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
117
- anemoi_datasets-0.5.5.dist-info/METADATA,sha256=IXuERodLJ1TIa4E3qplvDYy2ULOqGzZwvTaIntkLoo8,16324
118
- anemoi_datasets-0.5.5.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
119
- anemoi_datasets-0.5.5.dist-info/entry_points.txt,sha256=yR-o-4uiPEA_GLBL81SkMYnUoxq3CAV3hHulQiRtGG0,66
120
- anemoi_datasets-0.5.5.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
121
- anemoi_datasets-0.5.5.dist-info/RECORD,,
117
+ anemoi_datasets-0.5.7.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
118
+ anemoi_datasets-0.5.7.dist-info/METADATA,sha256=UTGUJaqsj9oc2Z3-iLLc709HlXxBxp1KPp7CHVfrEhE,16324
119
+ anemoi_datasets-0.5.7.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
120
+ anemoi_datasets-0.5.7.dist-info/entry_points.txt,sha256=yR-o-4uiPEA_GLBL81SkMYnUoxq3CAV3hHulQiRtGG0,66
121
+ anemoi_datasets-0.5.7.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
122
+ anemoi_datasets-0.5.7.dist-info/RECORD,,