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.
- anemoi/datasets/_version.py +2 -2
- anemoi/datasets/commands/inspect.py +4 -0
- anemoi/datasets/create/__init__.py +4 -39
- anemoi/datasets/create/functions/sources/xarray/__init__.py +1 -1
- anemoi/datasets/create/functions/sources/xarray/coordinates.py +8 -0
- anemoi/datasets/create/functions/sources/xarray/flavour.py +23 -15
- anemoi/datasets/create/functions/sources/xarray/grid.py +1 -0
- anemoi/datasets/create/functions/sources/xarray/time.py +37 -2
- anemoi/datasets/create/input/result.py +37 -1
- anemoi/datasets/create/persistent.py +4 -1
- anemoi/datasets/create/statistics/__init__.py +4 -1
- anemoi/datasets/create/zarr.py +5 -1
- anemoi/datasets/data/forwards.py +4 -1
- anemoi/datasets/data/join.py +13 -0
- anemoi/datasets/data/select.py +11 -0
- anemoi/datasets/data/stores.py +4 -0
- anemoi/datasets/data/unchecked.py +5 -0
- anemoi/datasets/testing.py +59 -0
- {anemoi_datasets-0.5.5.dist-info → anemoi_datasets-0.5.7.dist-info}/METADATA +1 -1
- {anemoi_datasets-0.5.5.dist-info → anemoi_datasets-0.5.7.dist-info}/RECORD +24 -23
- {anemoi_datasets-0.5.5.dist-info → anemoi_datasets-0.5.7.dist-info}/LICENSE +0 -0
- {anemoi_datasets-0.5.5.dist-info → anemoi_datasets-0.5.7.dist-info}/WHEEL +0 -0
- {anemoi_datasets-0.5.5.dist-info → anemoi_datasets-0.5.7.dist-info}/entry_points.txt +0 -0
- {anemoi_datasets-0.5.5.dist-info → anemoi_datasets-0.5.7.dist-info}/top_level.txt +0 -0
anemoi/datasets/_version.py
CHANGED
|
@@ -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.
|
|
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"] =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
292
|
+
grid = UnstructuredProjectionGrid(x, y, grid_mapping)
|
|
291
293
|
else:
|
|
292
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
194
|
+
with open(path, "w") as f:
|
|
192
195
|
json.dump(out, f)
|
|
193
196
|
|
|
194
197
|
def create(self, exist_ok):
|
anemoi/datasets/create/zarr.py
CHANGED
|
@@ -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()
|
anemoi/datasets/data/forwards.py
CHANGED
|
@@ -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)
|
anemoi/datasets/data/join.py
CHANGED
|
@@ -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)}
|
anemoi/datasets/data/select.py
CHANGED
|
@@ -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)}
|
anemoi/datasets/data/stores.py
CHANGED
|
@@ -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.
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
65
|
-
anemoi/datasets/create/functions/sources/xarray/coordinates.py,sha256=
|
|
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=
|
|
69
|
-
anemoi/datasets/create/functions/sources/xarray/grid.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
117
|
-
anemoi_datasets-0.5.
|
|
118
|
-
anemoi_datasets-0.5.
|
|
119
|
-
anemoi_datasets-0.5.
|
|
120
|
-
anemoi_datasets-0.5.
|
|
121
|
-
anemoi_datasets-0.5.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|