anemoi-utils 0.1.6__py3-none-any.whl → 0.1.8__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.
Potentially problematic release.
This version of anemoi-utils might be problematic. Click here for more details.
- anemoi/utils/_version.py +2 -2
- anemoi/utils/caching.py +59 -0
- anemoi/utils/checkpoints.py +1 -2
- anemoi/utils/grib.py +65 -6
- anemoi/utils/provenance.py +1 -3
- anemoi/utils/text.py +1 -8
- {anemoi_utils-0.1.6.dist-info → anemoi_utils-0.1.8.dist-info}/METADATA +1 -1
- anemoi_utils-0.1.8.dist-info/RECORD +15 -0
- anemoi_utils-0.1.6.dist-info/RECORD +0 -14
- {anemoi_utils-0.1.6.dist-info → anemoi_utils-0.1.8.dist-info}/LICENSE +0 -0
- {anemoi_utils-0.1.6.dist-info → anemoi_utils-0.1.8.dist-info}/WHEEL +0 -0
- {anemoi_utils-0.1.6.dist-info → anemoi_utils-0.1.8.dist-info}/top_level.txt +0 -0
anemoi/utils/_version.py
CHANGED
anemoi/utils/caching.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# (C) Copyright 2024 European Centre for Medium-Range Weather Forecasts.
|
|
2
|
+
# This software is licensed under the terms of the Apache Licence Version 2.0
|
|
3
|
+
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
4
|
+
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
5
|
+
# granted to it by virtue of its status as an intergovernmental organisation
|
|
6
|
+
# nor does it submit to any jurisdiction.
|
|
7
|
+
|
|
8
|
+
import hashlib
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
import time
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def cache(key, proc, collection="default", expires=None):
|
|
15
|
+
path = os.path.join(os.path.expanduser("~"), ".cache", "anemoi", collection)
|
|
16
|
+
os.makedirs(path, exist_ok=True)
|
|
17
|
+
|
|
18
|
+
key = json.dumps(key, sort_keys=True)
|
|
19
|
+
m = hashlib.md5()
|
|
20
|
+
m.update(key.encode("utf-8"))
|
|
21
|
+
|
|
22
|
+
filename = os.path.join(path, m.hexdigest())
|
|
23
|
+
if os.path.exists(filename):
|
|
24
|
+
with open(filename, "r") as f:
|
|
25
|
+
data = json.load(f)
|
|
26
|
+
if expires is None or data["expires"] > time.time():
|
|
27
|
+
if data["key"] == key:
|
|
28
|
+
return data["value"]
|
|
29
|
+
|
|
30
|
+
value = proc()
|
|
31
|
+
data = {"key": key, "value": value}
|
|
32
|
+
if expires is not None:
|
|
33
|
+
data["expires"] = time.time() + expires
|
|
34
|
+
|
|
35
|
+
with open(filename, "w") as f:
|
|
36
|
+
json.dump(data, f)
|
|
37
|
+
|
|
38
|
+
return value
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class cached:
|
|
42
|
+
|
|
43
|
+
def __init__(self, collection="default", expires=None):
|
|
44
|
+
self.collection = collection
|
|
45
|
+
self.expires = expires
|
|
46
|
+
|
|
47
|
+
def __call__(self, func):
|
|
48
|
+
|
|
49
|
+
full = f"{func.__module__}.{func.__name__}"
|
|
50
|
+
|
|
51
|
+
def wrapped(*args, **kwargs):
|
|
52
|
+
return cache(
|
|
53
|
+
(full, args, kwargs),
|
|
54
|
+
lambda: func(*args, **kwargs),
|
|
55
|
+
self.collection,
|
|
56
|
+
self.expires,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return wrapped
|
anemoi/utils/checkpoints.py
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
7
7
|
# nor does it submit to any jurisdiction.
|
|
8
8
|
|
|
9
|
-
"""
|
|
10
|
-
Read and write extra metadata in PyTorch checkpoints files. These files
|
|
9
|
+
"""Read and write extra metadata in PyTorch checkpoints files. These files
|
|
11
10
|
are zip archives containing the model weights.
|
|
12
11
|
"""
|
|
13
12
|
|
anemoi/utils/grib.py
CHANGED
|
@@ -11,12 +11,26 @@ See https://codes.ecmwf.int/grib/param-db/ for more information.
|
|
|
11
11
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
+
import logging
|
|
14
15
|
import re
|
|
15
16
|
|
|
16
17
|
import requests
|
|
17
18
|
|
|
19
|
+
from .caching import cached
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
LOG = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@cached(collection="grib", expires=30 * 24 * 60 * 60)
|
|
25
|
+
def _units():
|
|
26
|
+
r = requests.get("https://codes.ecmwf.int/parameter-database/api/v1/unit/")
|
|
27
|
+
r.raise_for_status()
|
|
28
|
+
units = r.json()
|
|
29
|
+
return {str(u["id"]): u["name"] for u in units}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@cached(collection="grib", expires=30 * 24 * 60 * 60)
|
|
33
|
+
def _search_param(name):
|
|
20
34
|
name = re.escape(name)
|
|
21
35
|
r = requests.get(f"https://codes.ecmwf.int/parameter-database/api/v1/param/?search=^{name}$®ex=true")
|
|
22
36
|
r.raise_for_status()
|
|
@@ -26,7 +40,12 @@ def _search(name):
|
|
|
26
40
|
|
|
27
41
|
if len(results) > 1:
|
|
28
42
|
names = [f'{r.get("id")} ({r.get("name")})' for r in results]
|
|
29
|
-
|
|
43
|
+
dissemination = [r for r in results if "dissemination" in r.get("access_ids", [])]
|
|
44
|
+
if len(dissemination) == 1:
|
|
45
|
+
return dissemination[0]
|
|
46
|
+
|
|
47
|
+
results = sorted(results, key=lambda x: x["id"])
|
|
48
|
+
LOG.warning(f"{name} is ambiguous: {', '.join(names)}. Using param_id={results[0]['id']}")
|
|
30
49
|
|
|
31
50
|
return results[0]
|
|
32
51
|
|
|
@@ -44,12 +63,11 @@ def shortname_to_paramid(shortname: str) -> int:
|
|
|
44
63
|
int
|
|
45
64
|
Parameter id.
|
|
46
65
|
|
|
47
|
-
|
|
48
66
|
>>> shortname_to_paramid("2t")
|
|
49
67
|
167
|
|
50
68
|
|
|
51
69
|
"""
|
|
52
|
-
return
|
|
70
|
+
return _search_param(shortname)["id"]
|
|
53
71
|
|
|
54
72
|
|
|
55
73
|
def paramid_to_shortname(paramid: int) -> str:
|
|
@@ -65,9 +83,50 @@ def paramid_to_shortname(paramid: int) -> str:
|
|
|
65
83
|
str
|
|
66
84
|
Parameter shortname.
|
|
67
85
|
|
|
68
|
-
|
|
69
86
|
>>> paramid_to_shortname(167)
|
|
70
87
|
'2t'
|
|
71
88
|
|
|
72
89
|
"""
|
|
73
|
-
return
|
|
90
|
+
return _search_param(str(paramid))["shortname"]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def units(param) -> str:
|
|
94
|
+
"""Return the units of a GRIB parameter given its name or id.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
paramid : int or str
|
|
99
|
+
Parameter id ir name.
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
str
|
|
104
|
+
Parameter unit.
|
|
105
|
+
|
|
106
|
+
>>> unit(167)
|
|
107
|
+
'K'
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
unit_id = str(_search_param(str(param))["unit_id"])
|
|
112
|
+
return _units()[unit_id]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def must_be_positive(param):
|
|
116
|
+
"""Check if a parameter must be positive.
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
param : int or str
|
|
121
|
+
Parameter id or shortname.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
bool
|
|
126
|
+
True if the parameter must be positive.
|
|
127
|
+
|
|
128
|
+
>>> must_be_positive("tp")
|
|
129
|
+
True
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
return units(param) in ["m", "kg kg**-1", "m of water equivalent"]
|
anemoi/utils/provenance.py
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
6
6
|
# nor does it submit to any jurisdiction.
|
|
7
7
|
|
|
8
|
-
"""
|
|
9
|
-
Collect information about the current environment, like:
|
|
8
|
+
"""Collect information about the current environment, like:
|
|
10
9
|
|
|
11
10
|
- The Python version
|
|
12
11
|
- The versions of the modules which are currently loaded
|
|
@@ -215,7 +214,6 @@ def git_check(*args):
|
|
|
215
214
|
dict
|
|
216
215
|
An object with the git information for the given arguments.
|
|
217
216
|
|
|
218
|
-
|
|
219
217
|
>>> {
|
|
220
218
|
"anemoi.utils": {
|
|
221
219
|
"sha1": "c999d83ae283bcbb99f68d92c42d24315922129f",
|
anemoi/utils/text.py
CHANGED
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
6
6
|
# nor does it submit to any jurisdiction.
|
|
7
7
|
|
|
8
|
-
"""
|
|
9
|
-
Text utilities
|
|
10
|
-
"""
|
|
8
|
+
"""Text utilities"""
|
|
11
9
|
|
|
12
10
|
import sys
|
|
13
11
|
from collections import defaultdict
|
|
@@ -58,9 +56,6 @@ def boxed(text, min_width=80, max_width=80) -> str:
|
|
|
58
56
|
str
|
|
59
57
|
A boxed version of the input text
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
59
|
"""
|
|
65
60
|
|
|
66
61
|
lines = text.split("\n")
|
|
@@ -266,7 +261,6 @@ def table(rows, header, align, margin=0):
|
|
|
266
261
|
margin : int, optional
|
|
267
262
|
Extra spaces on the left side of the table, by default 0
|
|
268
263
|
|
|
269
|
-
|
|
270
264
|
Returns
|
|
271
265
|
-------
|
|
272
266
|
str
|
|
@@ -339,7 +333,6 @@ def progress(done, todo, width=80) -> str:
|
|
|
339
333
|
str
|
|
340
334
|
_description_
|
|
341
335
|
|
|
342
|
-
|
|
343
336
|
"""
|
|
344
337
|
done = min(int(done / todo * width + 0.5), width)
|
|
345
338
|
return green("█" * done) + red("█" * (width - done))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: anemoi-utils
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
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
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
anemoi/utils/__init__.py,sha256=zZZpbKIoGWwdCOuo6YSruLR7C0GzvzI1Wzhyqaa0K7M,456
|
|
2
|
+
anemoi/utils/_version.py,sha256=PdJ7dZoz_SyEgX0MdrMfQYBFlGcwpemv6ibF8NKALBY,411
|
|
3
|
+
anemoi/utils/caching.py,sha256=HrC9aFHlcCTaM2Z5u0ivGIXz7eFu35UQQhUuwwuG2pk,1743
|
|
4
|
+
anemoi/utils/checkpoints.py,sha256=IR86FFNh5JR_uQVlgybnZG74PyU0CNLhyocqARwZIrs,2069
|
|
5
|
+
anemoi/utils/config.py,sha256=XEesqODvkuE3ZA7dnEnZ-ooBRtU6ecPmkfP65FtialA,2147
|
|
6
|
+
anemoi/utils/dates.py,sha256=ZabXLecHMio9ecIJbUxNcfOFoGfkcotSwy_xw1kNQ9w,6474
|
|
7
|
+
anemoi/utils/grib.py,sha256=gVfo4KYQv31iRyoqRDwk5tiqZDUgOIvhag_kO0qjYD0,3067
|
|
8
|
+
anemoi/utils/humanize.py,sha256=LD6dGnqChxA5j3tMhSybsAGRQzi33d_qS9pUoUHubkc,10330
|
|
9
|
+
anemoi/utils/provenance.py,sha256=v54L9jF1JgYcclOhg3iojRl1v3ajbiWz_oc289xTgO4,9574
|
|
10
|
+
anemoi/utils/text.py,sha256=pGWtDvRFoDxAnSuZJiA-GOGJOJLHsw2dAm0tfVvPKno,8599
|
|
11
|
+
anemoi_utils-0.1.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
12
|
+
anemoi_utils-0.1.8.dist-info/METADATA,sha256=bEA_bMbWJubncfBmc6tMi6cJLtFgZrgth899Z60i5Yg,15079
|
|
13
|
+
anemoi_utils-0.1.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
14
|
+
anemoi_utils-0.1.8.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
|
|
15
|
+
anemoi_utils-0.1.8.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
anemoi/utils/__init__.py,sha256=zZZpbKIoGWwdCOuo6YSruLR7C0GzvzI1Wzhyqaa0K7M,456
|
|
2
|
-
anemoi/utils/_version.py,sha256=L9DFp_i-1xztMRdin6ZHqLFMlDKUn5bsVgheqXFwTTc,411
|
|
3
|
-
anemoi/utils/checkpoints.py,sha256=j1QMmffpo6Blo6kmAJDdUzK3dqq30UWIsWghFqsY4QU,2070
|
|
4
|
-
anemoi/utils/config.py,sha256=XEesqODvkuE3ZA7dnEnZ-ooBRtU6ecPmkfP65FtialA,2147
|
|
5
|
-
anemoi/utils/dates.py,sha256=ZabXLecHMio9ecIJbUxNcfOFoGfkcotSwy_xw1kNQ9w,6474
|
|
6
|
-
anemoi/utils/grib.py,sha256=8fxp2O7tXrFvvp0h68IZ0OhDkyH7GQFTX_6qwJ-hzBs,1692
|
|
7
|
-
anemoi/utils/humanize.py,sha256=LD6dGnqChxA5j3tMhSybsAGRQzi33d_qS9pUoUHubkc,10330
|
|
8
|
-
anemoi/utils/provenance.py,sha256=RiDpevwTbCzTAkU0oL7pNwST37xt4W9GOkeNNDqbAgk,9576
|
|
9
|
-
anemoi/utils/text.py,sha256=mBCPH9NwLyWCU9GkXzB0K4xiDN6UQ1XGlD4T5d8x8Vk,8606
|
|
10
|
-
anemoi_utils-0.1.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
11
|
-
anemoi_utils-0.1.6.dist-info/METADATA,sha256=gGK2zftLCNffyYnA0FhMXja0k5MOKzoixlL24O29dhk,15079
|
|
12
|
-
anemoi_utils-0.1.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
13
|
-
anemoi_utils-0.1.6.dist-info/top_level.txt,sha256=DYn8VPs-fNwr7fNH9XIBqeXIwiYYd2E2k5-dUFFqUz0,7
|
|
14
|
-
anemoi_utils-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|