anemoi-utils 0.1.6__tar.gz → 0.1.8__tar.gz

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.

Files changed (42) hide show
  1. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/.pre-commit-config.yaml +5 -5
  2. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/PKG-INFO +1 -1
  3. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/_version.py +2 -2
  4. anemoi_utils-0.1.8/src/anemoi/utils/caching.py +59 -0
  5. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/checkpoints.py +1 -2
  6. anemoi_utils-0.1.8/src/anemoi/utils/grib.py +132 -0
  7. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/provenance.py +1 -3
  8. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/text.py +1 -8
  9. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi_utils.egg-info/PKG-INFO +1 -1
  10. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi_utils.egg-info/SOURCES.txt +1 -0
  11. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/tests/test_utils.py +8 -1
  12. anemoi_utils-0.1.6/src/anemoi/utils/grib.py +0 -73
  13. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/.github/workflows/python-publish.yml +0 -0
  14. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/.gitignore +0 -0
  15. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/.readthedocs.yaml +0 -0
  16. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/LICENSE +0 -0
  17. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/README.md +0 -0
  18. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/Makefile +0 -0
  19. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/_static/logo.png +0 -0
  20. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/_static/style.css +0 -0
  21. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/_templates/.gitkeep +0 -0
  22. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/conf.py +0 -0
  23. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/index.rst +0 -0
  24. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/installing.rst +0 -0
  25. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/checkpoints.rst +0 -0
  26. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/config.rst +0 -0
  27. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/dates.rst +0 -0
  28. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/grib.rst +0 -0
  29. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/humanize.rst +0 -0
  30. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/provenance.rst +0 -0
  31. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/modules/text.rst +0 -0
  32. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/docs/requirements.txt +0 -0
  33. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/pyproject.toml +0 -0
  34. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/setup.cfg +0 -0
  35. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/__init__.py +0 -0
  36. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/config.py +0 -0
  37. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/dates.py +0 -0
  38. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi/utils/humanize.py +0 -0
  39. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi_utils.egg-info/dependency_links.txt +0 -0
  40. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi_utils.egg-info/requires.txt +0 -0
  41. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/src/anemoi_utils.egg-info/top_level.txt +0 -0
  42. {anemoi_utils-0.1.6 → anemoi_utils-0.1.8}/tests/requirements.txt +0 -0
@@ -62,8 +62,8 @@ repos:
62
62
  hooks:
63
63
  - id: rstfmt
64
64
 
65
- # - repo: ../pre-commit-docconvert
66
- # rev: 07f5748
67
- # hooks:
68
- # - id: docconvert
69
- # args: ["--in-place", "--output", "numpy"]
65
+ - repo: https://github.com/b8raoult/pre-commit-docconvert
66
+ rev: "0.1.4"
67
+ hooks:
68
+ - id: docconvert
69
+ args: ["numpy"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: anemoi-utils
3
- Version: 0.1.6
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
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.1.6'
16
- __version_tuple__ = version_tuple = (0, 1, 6)
15
+ __version__ = version = '0.1.8'
16
+ __version_tuple__ = version_tuple = (0, 1, 8)
@@ -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
@@ -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
 
@@ -0,0 +1,132 @@
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
+ """Utilities for working with GRIB parameters.
9
+
10
+ See https://codes.ecmwf.int/grib/param-db/ for more information.
11
+
12
+ """
13
+
14
+ import logging
15
+ import re
16
+
17
+ import requests
18
+
19
+ from .caching import cached
20
+
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):
34
+ name = re.escape(name)
35
+ r = requests.get(f"https://codes.ecmwf.int/parameter-database/api/v1/param/?search=^{name}$&regex=true")
36
+ r.raise_for_status()
37
+ results = r.json()
38
+ if len(results) == 0:
39
+ raise KeyError(name)
40
+
41
+ if len(results) > 1:
42
+ names = [f'{r.get("id")} ({r.get("name")})' for r in results]
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']}")
49
+
50
+ return results[0]
51
+
52
+
53
+ def shortname_to_paramid(shortname: str) -> int:
54
+ """Return the GRIB parameter id given its shortname.
55
+
56
+ Parameters
57
+ ----------
58
+ shortname : str
59
+ Parameter shortname.
60
+
61
+ Returns
62
+ -------
63
+ int
64
+ Parameter id.
65
+
66
+ >>> shortname_to_paramid("2t")
67
+ 167
68
+
69
+ """
70
+ return _search_param(shortname)["id"]
71
+
72
+
73
+ def paramid_to_shortname(paramid: int) -> str:
74
+ """Return the shortname of a GRIB parameter given its id.
75
+
76
+ Parameters
77
+ ----------
78
+ paramid : int
79
+ Parameter id.
80
+
81
+ Returns
82
+ -------
83
+ str
84
+ Parameter shortname.
85
+
86
+ >>> paramid_to_shortname(167)
87
+ '2t'
88
+
89
+ """
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"]
@@ -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",
@@ -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.6
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
@@ -22,6 +22,7 @@ docs/modules/provenance.rst
22
22
  docs/modules/text.rst
23
23
  src/anemoi/utils/__init__.py
24
24
  src/anemoi/utils/_version.py
25
+ src/anemoi/utils/caching.py
25
26
  src/anemoi/utils/checkpoints.py
26
27
  src/anemoi/utils/config.py
27
28
  src/anemoi/utils/dates.py
@@ -7,6 +7,8 @@
7
7
 
8
8
 
9
9
  from anemoi.utils.config import DotDict
10
+ from anemoi.utils.grib import paramid_to_shortname
11
+ from anemoi.utils.grib import shortname_to_paramid
10
12
 
11
13
 
12
14
  def test_dotdict():
@@ -26,5 +28,10 @@ def test_dotdict():
26
28
  assert d.d.x == 6
27
29
 
28
30
 
31
+ def test_grib():
32
+ assert shortname_to_paramid("2t") == 167
33
+ assert paramid_to_shortname(167) == "2t"
34
+
35
+
29
36
  if __name__ == "__main__":
30
- test_dotdict()
37
+ test_grib()
@@ -1,73 +0,0 @@
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
- """Utilities for working with GRIB parameters.
9
-
10
- See https://codes.ecmwf.int/grib/param-db/ for more information.
11
-
12
- """
13
-
14
- import re
15
-
16
- import requests
17
-
18
-
19
- def _search(name):
20
- name = re.escape(name)
21
- r = requests.get(f"https://codes.ecmwf.int/parameter-database/api/v1/param/?search=^{name}$&regex=true")
22
- r.raise_for_status()
23
- results = r.json()
24
- if len(results) == 0:
25
- raise KeyError(name)
26
-
27
- if len(results) > 1:
28
- names = [f'{r.get("id")} ({r.get("name")})' for r in results]
29
- raise ValueError(f"{name} is ambiguous: {', '.join(names)}")
30
-
31
- return results[0]
32
-
33
-
34
- def shortname_to_paramid(shortname: str) -> int:
35
- """Return the GRIB parameter id given its shortname.
36
-
37
- Parameters
38
- ----------
39
- shortname : str
40
- Parameter shortname.
41
-
42
- Returns
43
- -------
44
- int
45
- Parameter id.
46
-
47
-
48
- >>> shortname_to_paramid("2t")
49
- 167
50
-
51
- """
52
- return _search(shortname)["id"]
53
-
54
-
55
- def paramid_to_shortname(paramid: int) -> str:
56
- """Return the shortname of a GRIB parameter given its id.
57
-
58
- Parameters
59
- ----------
60
- paramid : int
61
- Parameter id.
62
-
63
- Returns
64
- -------
65
- str
66
- Parameter shortname.
67
-
68
-
69
- >>> paramid_to_shortname(167)
70
- '2t'
71
-
72
- """
73
- return _search(str(paramid))["shortname"]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes