anemoi-utils 0.4.12__py3-none-any.whl → 0.4.14__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/__init__.py +1 -0
- anemoi/utils/__main__.py +12 -2
- anemoi/utils/_version.py +9 -4
- anemoi/utils/caching.py +138 -13
- anemoi/utils/checkpoints.py +81 -13
- anemoi/utils/cli.py +83 -7
- anemoi/utils/commands/__init__.py +4 -0
- anemoi/utils/commands/config.py +19 -2
- anemoi/utils/commands/requests.py +18 -2
- anemoi/utils/compatibility.py +6 -5
- anemoi/utils/config.py +254 -23
- anemoi/utils/dates.py +204 -50
- anemoi/utils/devtools.py +68 -7
- anemoi/utils/grib.py +30 -9
- anemoi/utils/grids.py +85 -8
- anemoi/utils/hindcasts.py +25 -8
- anemoi/utils/humanize.py +357 -52
- anemoi/utils/logs.py +31 -3
- anemoi/utils/mars/__init__.py +46 -12
- anemoi/utils/mars/requests.py +15 -1
- anemoi/utils/provenance.py +189 -32
- anemoi/utils/registry.py +234 -44
- anemoi/utils/remote/__init__.py +386 -38
- anemoi/utils/remote/s3.py +252 -29
- anemoi/utils/remote/ssh.py +140 -8
- anemoi/utils/s3.py +77 -4
- anemoi/utils/sanitise.py +52 -7
- anemoi/utils/testing.py +182 -0
- anemoi/utils/text.py +218 -54
- anemoi/utils/timer.py +91 -15
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/METADATA +8 -4
- anemoi_utils-0.4.14.dist-info/RECORD +38 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/WHEEL +1 -1
- anemoi_utils-0.4.12.dist-info/RECORD +0 -37
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/entry_points.txt +0 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info/licenses}/LICENSE +0 -0
- {anemoi_utils-0.4.12.dist-info → anemoi_utils-0.4.14.dist-info}/top_level.txt +0 -0
anemoi/utils/grids.py
CHANGED
|
@@ -8,9 +8,7 @@
|
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
"""Utilities for working with grids.
|
|
12
|
-
|
|
13
|
-
"""
|
|
11
|
+
"""Utilities for working with grids."""
|
|
14
12
|
|
|
15
13
|
import logging
|
|
16
14
|
import os
|
|
@@ -27,14 +25,46 @@ LOG = logging.getLogger(__name__)
|
|
|
27
25
|
GRIDS_URL_PATTERN = "https://get.ecmwf.int/repository/anemoi/grids/grid-{name}.npz"
|
|
28
26
|
|
|
29
27
|
|
|
30
|
-
def xyz_to_latlon(x, y, z):
|
|
28
|
+
def xyz_to_latlon(x: np.ndarray, y: np.ndarray, z: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
|
29
|
+
"""Convert Cartesian coordinates to latitude and longitude.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
x : np.ndarray
|
|
34
|
+
The x coordinates
|
|
35
|
+
y : np.ndarray
|
|
36
|
+
The y coordinates
|
|
37
|
+
z : np.ndarray
|
|
38
|
+
The z coordinates
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
tuple[np.ndarray, np.ndarray]
|
|
43
|
+
The latitude and longitude
|
|
44
|
+
"""
|
|
31
45
|
return (
|
|
32
46
|
np.rad2deg(np.arcsin(np.minimum(1.0, np.maximum(-1.0, z)))),
|
|
33
47
|
np.rad2deg(np.arctan2(y, x)),
|
|
34
48
|
)
|
|
35
49
|
|
|
36
50
|
|
|
37
|
-
def latlon_to_xyz(lat, lon, radius=1.0):
|
|
51
|
+
def latlon_to_xyz(lat: np.ndarray, lon: np.ndarray, radius: float = 1.0) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
52
|
+
"""Convert latitude and longitude to Cartesian coordinates.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
lat : np.ndarray
|
|
57
|
+
The latitudes
|
|
58
|
+
lon : np.ndarray
|
|
59
|
+
The longitudes
|
|
60
|
+
radius : float, optional
|
|
61
|
+
The radius of the sphere, by default 1.0
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
tuple[np.ndarray, np.ndarray, np.ndarray]
|
|
66
|
+
The x, y, and z coordinates
|
|
67
|
+
"""
|
|
38
68
|
# https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates
|
|
39
69
|
# We assume that the Earth is a sphere of radius 1 so N(phi) = 1
|
|
40
70
|
# We assume h = 0
|
|
@@ -54,7 +84,30 @@ def latlon_to_xyz(lat, lon, radius=1.0):
|
|
|
54
84
|
return x, y, z
|
|
55
85
|
|
|
56
86
|
|
|
57
|
-
def nearest_grid_points(
|
|
87
|
+
def nearest_grid_points(
|
|
88
|
+
source_latitudes: np.ndarray,
|
|
89
|
+
source_longitudes: np.ndarray,
|
|
90
|
+
target_latitudes: np.ndarray,
|
|
91
|
+
target_longitudes: np.ndarray,
|
|
92
|
+
) -> np.ndarray:
|
|
93
|
+
"""Find the nearest grid points.
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
source_latitudes : np.ndarray
|
|
98
|
+
The source latitudes
|
|
99
|
+
source_longitudes : np.ndarray
|
|
100
|
+
The source longitudes
|
|
101
|
+
target_latitudes : np.ndarray
|
|
102
|
+
The target latitudes
|
|
103
|
+
target_longitudes : np.ndarray
|
|
104
|
+
The target longitudes
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
np.ndarray
|
|
109
|
+
The indices of the nearest grid points
|
|
110
|
+
"""
|
|
58
111
|
from scipy.spatial import cKDTree
|
|
59
112
|
|
|
60
113
|
source_xyz = latlon_to_xyz(source_latitudes, source_longitudes)
|
|
@@ -68,7 +121,19 @@ def nearest_grid_points(source_latitudes, source_longitudes, target_latitudes, t
|
|
|
68
121
|
|
|
69
122
|
|
|
70
123
|
@cached(collection="grids", encoding="npz")
|
|
71
|
-
def _grids(name):
|
|
124
|
+
def _grids(name: str) -> bytes:
|
|
125
|
+
"""Get grid data by name.
|
|
126
|
+
|
|
127
|
+
Parameters
|
|
128
|
+
----------
|
|
129
|
+
name : str
|
|
130
|
+
The name of the grid
|
|
131
|
+
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
134
|
+
bytes
|
|
135
|
+
The grid data
|
|
136
|
+
"""
|
|
72
137
|
from anemoi.utils.config import load_config
|
|
73
138
|
|
|
74
139
|
user_path = load_config().get("utils", {}).get("grids_path")
|
|
@@ -88,7 +153,19 @@ def _grids(name):
|
|
|
88
153
|
return response.content
|
|
89
154
|
|
|
90
155
|
|
|
91
|
-
def grids(name):
|
|
156
|
+
def grids(name: str) -> dict:
|
|
157
|
+
"""Load grid data by name.
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
name : str
|
|
162
|
+
The name of the grid
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
dict
|
|
167
|
+
The grid data
|
|
168
|
+
"""
|
|
92
169
|
if name.endswith(".npz"):
|
|
93
170
|
return dict(np.load(name))
|
|
94
171
|
|
anemoi/utils/hindcasts.py
CHANGED
|
@@ -9,29 +9,46 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import datetime
|
|
12
|
+
from typing import Iterator
|
|
13
|
+
from typing import List
|
|
14
|
+
from typing import Tuple
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class HindcastDatesTimes:
|
|
15
|
-
"""The HindcastDatesTimes class is an iterator that generates datetime objects within a given range.
|
|
18
|
+
"""The HindcastDatesTimes class is an iterator that generates datetime objects within a given range.
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
reference_dates : List[datetime.datetime]
|
|
23
|
+
List of reference dates.
|
|
24
|
+
years : int
|
|
25
|
+
Number of years to go back from each reference date.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, reference_dates: List[datetime.datetime], years: int = 20):
|
|
29
|
+
"""Initialize the HindcastDatesTimes iterator.
|
|
19
30
|
|
|
20
31
|
Parameters
|
|
21
32
|
----------
|
|
22
|
-
reference_dates :
|
|
23
|
-
|
|
33
|
+
reference_dates : List[datetime.datetime]
|
|
34
|
+
List of reference dates.
|
|
24
35
|
years : int, optional
|
|
25
|
-
|
|
36
|
+
Number of years to go back from each reference date, by default 20.
|
|
26
37
|
"""
|
|
27
|
-
|
|
28
38
|
self.reference_dates = reference_dates
|
|
29
39
|
|
|
30
40
|
assert isinstance(years, int), f"years must be an integer, got {years}"
|
|
31
41
|
assert years > 0, f"years must be greater than 0, got {years}"
|
|
32
42
|
self.years = years
|
|
33
43
|
|
|
34
|
-
def __iter__(self):
|
|
44
|
+
def __iter__(self) -> Iterator[Tuple[datetime.datetime, datetime.datetime]]:
|
|
45
|
+
"""Generate tuples of past dates and their corresponding reference dates.
|
|
46
|
+
|
|
47
|
+
Yields
|
|
48
|
+
------
|
|
49
|
+
Iterator[Tuple[datetime.datetime, datetime.datetime]]
|
|
50
|
+
Tuples containing a past date and its corresponding reference date.
|
|
51
|
+
"""
|
|
35
52
|
for reference_date in self.reference_dates:
|
|
36
53
|
year, month, day = reference_date.year, reference_date.month, reference_date.day
|
|
37
54
|
if (month, day) == (2, 29):
|