anemoi-datasets 0.5.16__py3-none-any.whl → 0.5.17__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/__init__.py +4 -1
- anemoi/datasets/__main__.py +12 -2
- anemoi/datasets/_version.py +9 -4
- anemoi/datasets/commands/cleanup.py +17 -2
- anemoi/datasets/commands/compare.py +18 -2
- anemoi/datasets/commands/copy.py +196 -14
- anemoi/datasets/commands/create.py +50 -7
- anemoi/datasets/commands/finalise-additions.py +17 -2
- anemoi/datasets/commands/finalise.py +17 -2
- anemoi/datasets/commands/init-additions.py +17 -2
- anemoi/datasets/commands/init.py +16 -2
- anemoi/datasets/commands/inspect.py +283 -62
- anemoi/datasets/commands/load-additions.py +16 -2
- anemoi/datasets/commands/load.py +16 -2
- anemoi/datasets/commands/patch.py +17 -2
- anemoi/datasets/commands/publish.py +17 -2
- anemoi/datasets/commands/scan.py +31 -3
- anemoi/datasets/compute/recentre.py +47 -11
- anemoi/datasets/create/__init__.py +612 -85
- anemoi/datasets/create/check.py +142 -20
- anemoi/datasets/create/chunks.py +64 -4
- anemoi/datasets/create/config.py +185 -21
- anemoi/datasets/create/filter.py +50 -0
- anemoi/datasets/create/filters/__init__.py +33 -0
- anemoi/datasets/create/filters/empty.py +37 -0
- anemoi/datasets/create/filters/legacy.py +93 -0
- anemoi/datasets/create/filters/noop.py +37 -0
- anemoi/datasets/create/filters/orog_to_z.py +58 -0
- anemoi/datasets/create/{functions/filters → filters}/pressure_level_relative_humidity_to_specific_humidity.py +33 -10
- anemoi/datasets/create/{functions/filters → filters}/pressure_level_specific_humidity_to_relative_humidity.py +32 -8
- anemoi/datasets/create/filters/rename.py +205 -0
- anemoi/datasets/create/{functions/filters → filters}/rotate_winds.py +43 -28
- anemoi/datasets/create/{functions/filters → filters}/single_level_dewpoint_to_relative_humidity.py +32 -9
- anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_dewpoint.py +33 -9
- anemoi/datasets/create/{functions/filters → filters}/single_level_relative_humidity_to_specific_humidity.py +55 -7
- anemoi/datasets/create/{functions/filters → filters}/single_level_specific_humidity_to_relative_humidity.py +98 -37
- anemoi/datasets/create/filters/speeddir_to_uv.py +95 -0
- anemoi/datasets/create/{functions/filters → filters}/sum.py +24 -27
- anemoi/datasets/create/filters/transform.py +53 -0
- anemoi/datasets/create/{functions/filters → filters}/unrotate_winds.py +27 -18
- anemoi/datasets/create/filters/uv_to_speeddir.py +94 -0
- anemoi/datasets/create/{functions/filters → filters}/wz_to_w.py +51 -33
- anemoi/datasets/create/input/__init__.py +76 -5
- anemoi/datasets/create/input/action.py +149 -13
- anemoi/datasets/create/input/concat.py +81 -10
- anemoi/datasets/create/input/context.py +39 -4
- anemoi/datasets/create/input/data_sources.py +72 -6
- anemoi/datasets/create/input/empty.py +21 -3
- anemoi/datasets/create/input/filter.py +60 -12
- anemoi/datasets/create/input/function.py +154 -37
- anemoi/datasets/create/input/join.py +86 -14
- anemoi/datasets/create/input/misc.py +67 -17
- anemoi/datasets/create/input/pipe.py +33 -6
- anemoi/datasets/create/input/repeated_dates.py +189 -41
- anemoi/datasets/create/input/result.py +202 -87
- anemoi/datasets/create/input/step.py +119 -22
- anemoi/datasets/create/input/template.py +100 -13
- anemoi/datasets/create/input/trace.py +62 -7
- anemoi/datasets/create/patch.py +52 -4
- anemoi/datasets/create/persistent.py +134 -17
- anemoi/datasets/create/size.py +15 -1
- anemoi/datasets/create/source.py +51 -0
- anemoi/datasets/create/sources/__init__.py +36 -0
- anemoi/datasets/create/{functions/sources → sources}/accumulations.py +296 -30
- anemoi/datasets/create/{functions/sources → sources}/constants.py +27 -2
- anemoi/datasets/create/{functions/sources → sources}/eccc_fstd.py +7 -3
- anemoi/datasets/create/sources/empty.py +37 -0
- anemoi/datasets/create/{functions/sources → sources}/forcings.py +25 -1
- anemoi/datasets/create/sources/grib.py +297 -0
- anemoi/datasets/create/{functions/sources → sources}/hindcasts.py +38 -4
- anemoi/datasets/create/sources/legacy.py +93 -0
- anemoi/datasets/create/{functions/sources → sources}/mars.py +168 -20
- anemoi/datasets/create/sources/netcdf.py +42 -0
- anemoi/datasets/create/sources/opendap.py +43 -0
- anemoi/datasets/create/{functions/sources/__init__.py → sources/patterns.py} +35 -4
- anemoi/datasets/create/sources/recentre.py +150 -0
- anemoi/datasets/create/{functions/sources → sources}/source.py +27 -5
- anemoi/datasets/create/{functions/sources → sources}/tendencies.py +64 -7
- anemoi/datasets/create/sources/xarray.py +92 -0
- anemoi/datasets/create/sources/xarray_kerchunk.py +36 -0
- anemoi/datasets/create/sources/xarray_support/README.md +1 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/__init__.py +109 -8
- anemoi/datasets/create/sources/xarray_support/coordinates.py +442 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/field.py +94 -16
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/fieldlist.py +90 -25
- anemoi/datasets/create/sources/xarray_support/flavour.py +1036 -0
- anemoi/datasets/create/{functions/sources/xarray → sources/xarray_support}/grid.py +92 -31
- anemoi/datasets/create/sources/xarray_support/metadata.py +395 -0
- anemoi/datasets/create/sources/xarray_support/patch.py +91 -0
- anemoi/datasets/create/sources/xarray_support/time.py +391 -0
- anemoi/datasets/create/sources/xarray_support/variable.py +331 -0
- anemoi/datasets/create/sources/xarray_zarr.py +41 -0
- anemoi/datasets/create/{functions/sources → sources}/zenodo.py +34 -5
- anemoi/datasets/create/statistics/__init__.py +233 -44
- anemoi/datasets/create/statistics/summary.py +52 -6
- anemoi/datasets/create/testing.py +76 -0
- anemoi/datasets/create/{functions/filters/noop.py → typing.py} +6 -3
- anemoi/datasets/create/utils.py +97 -6
- anemoi/datasets/create/writer.py +26 -4
- anemoi/datasets/create/zarr.py +170 -23
- anemoi/datasets/data/__init__.py +51 -4
- anemoi/datasets/data/complement.py +191 -40
- anemoi/datasets/data/concat.py +141 -16
- anemoi/datasets/data/dataset.py +552 -61
- anemoi/datasets/data/debug.py +197 -26
- anemoi/datasets/data/ensemble.py +93 -8
- anemoi/datasets/data/fill_missing.py +165 -18
- anemoi/datasets/data/forwards.py +428 -56
- anemoi/datasets/data/grids.py +323 -97
- anemoi/datasets/data/indexing.py +112 -19
- anemoi/datasets/data/interpolate.py +92 -12
- anemoi/datasets/data/join.py +158 -19
- anemoi/datasets/data/masked.py +129 -15
- anemoi/datasets/data/merge.py +137 -23
- anemoi/datasets/data/misc.py +172 -16
- anemoi/datasets/data/missing.py +233 -29
- anemoi/datasets/data/rescale.py +111 -10
- anemoi/datasets/data/select.py +168 -26
- anemoi/datasets/data/statistics.py +67 -6
- anemoi/datasets/data/stores.py +149 -64
- anemoi/datasets/data/subset.py +159 -25
- anemoi/datasets/data/unchecked.py +168 -57
- anemoi/datasets/data/xy.py +168 -25
- anemoi/datasets/dates/__init__.py +191 -16
- anemoi/datasets/dates/groups.py +189 -47
- anemoi/datasets/grids.py +270 -31
- anemoi/datasets/testing.py +28 -1
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.17.dist-info}/METADATA +9 -6
- anemoi_datasets-0.5.17.dist-info/RECORD +137 -0
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.17.dist-info}/WHEEL +1 -1
- anemoi/datasets/create/functions/__init__.py +0 -66
- anemoi/datasets/create/functions/filters/__init__.py +0 -9
- anemoi/datasets/create/functions/filters/empty.py +0 -17
- anemoi/datasets/create/functions/filters/orog_to_z.py +0 -58
- anemoi/datasets/create/functions/filters/rename.py +0 -79
- anemoi/datasets/create/functions/filters/speeddir_to_uv.py +0 -78
- anemoi/datasets/create/functions/filters/uv_to_speeddir.py +0 -56
- anemoi/datasets/create/functions/sources/empty.py +0 -15
- anemoi/datasets/create/functions/sources/grib.py +0 -150
- anemoi/datasets/create/functions/sources/netcdf.py +0 -15
- anemoi/datasets/create/functions/sources/opendap.py +0 -15
- anemoi/datasets/create/functions/sources/recentre.py +0 -60
- anemoi/datasets/create/functions/sources/xarray/coordinates.py +0 -255
- anemoi/datasets/create/functions/sources/xarray/flavour.py +0 -472
- anemoi/datasets/create/functions/sources/xarray/metadata.py +0 -148
- anemoi/datasets/create/functions/sources/xarray/patch.py +0 -44
- anemoi/datasets/create/functions/sources/xarray/time.py +0 -177
- anemoi/datasets/create/functions/sources/xarray/variable.py +0 -188
- anemoi/datasets/create/functions/sources/xarray_kerchunk.py +0 -42
- anemoi/datasets/create/functions/sources/xarray_zarr.py +0 -15
- anemoi/datasets/utils/fields.py +0 -47
- anemoi_datasets-0.5.16.dist-info/RECORD +0 -129
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.17.dist-info}/entry_points.txt +0 -0
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.17.dist-info/licenses}/LICENSE +0 -0
- {anemoi_datasets-0.5.16.dist-info → anemoi_datasets-0.5.17.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# (C) Copyright 2025 Anemoi contributors.
|
|
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
|
+
#
|
|
6
|
+
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
7
|
+
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
|
+
# nor does it submit to any jurisdiction.
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
from typing import Dict
|
|
12
|
+
|
|
13
|
+
import earthkit.data as ekd
|
|
14
|
+
|
|
15
|
+
from ..filter import Filter
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TransformFilter(Filter):
|
|
19
|
+
"""Calls filters from anemoi.transform.filters
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
context : Any
|
|
24
|
+
The context in which the filter is created.
|
|
25
|
+
name : str
|
|
26
|
+
The name of the filter.
|
|
27
|
+
config : Dict[str, Any]
|
|
28
|
+
The configuration for the filter.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, context: Any, name: str, config: Dict[str, Any]) -> None:
|
|
32
|
+
|
|
33
|
+
from anemoi.transform.filters import create_filter
|
|
34
|
+
|
|
35
|
+
self.name = name
|
|
36
|
+
self.transform_filter = create_filter(self, config)
|
|
37
|
+
|
|
38
|
+
def execute(self, context: Any, input: ekd.FieldList) -> ekd.FieldList:
|
|
39
|
+
"""Execute the transformation filter.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
context : Any
|
|
44
|
+
The context in which the execution occurs.
|
|
45
|
+
input : ekd.FieldList
|
|
46
|
+
The input data to be transformed.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
ekd.FieldList
|
|
51
|
+
The transformed data.
|
|
52
|
+
"""
|
|
53
|
+
return self.transform_filter.forward(input)
|
|
@@ -7,29 +7,38 @@
|
|
|
7
7
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
from collections import defaultdict
|
|
11
|
+
from typing import Any
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
from
|
|
13
|
+
import earthkit.data as ekd
|
|
14
|
+
from anemoi.transform.fields import new_field_from_numpy
|
|
15
|
+
from anemoi.transform.fields import new_fieldlist_from_list
|
|
15
16
|
from earthkit.geo.rotate import unrotate_vector
|
|
16
17
|
|
|
18
|
+
from .legacy import legacy_filter
|
|
17
19
|
|
|
18
|
-
class NewDataField:
|
|
19
|
-
def __init__(self, field, data):
|
|
20
|
-
self.field = field
|
|
21
|
-
self.data = data
|
|
22
|
-
|
|
23
|
-
def to_numpy(self, *args, **kwargs):
|
|
24
|
-
return self.data
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
@legacy_filter(__file__)
|
|
22
|
+
def execute(context: Any, input: ekd.FieldList, u: str, v: str) -> ekd.FieldList:
|
|
23
|
+
"""Unrotate the wind components of a GRIB file.
|
|
28
24
|
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
context : Any
|
|
28
|
+
The execution context.
|
|
29
|
+
input : List[Any]
|
|
30
|
+
The list of input fields.
|
|
31
|
+
u : str
|
|
32
|
+
The parameter name for the u-component of the wind.
|
|
33
|
+
v : str
|
|
34
|
+
The parameter name for the v-component of the wind.
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
ekd.FieldList
|
|
39
|
+
The resulting field array with unrotated wind components.
|
|
40
|
+
"""
|
|
41
|
+
result = []
|
|
33
42
|
|
|
34
43
|
wind_params = (u, v)
|
|
35
44
|
wind_pairs = defaultdict(dict)
|
|
@@ -72,10 +81,10 @@ def execute(context, input, u, v):
|
|
|
72
81
|
lon_unrotated=raw_longs,
|
|
73
82
|
)
|
|
74
83
|
|
|
75
|
-
result.append(
|
|
76
|
-
result.append(
|
|
84
|
+
result.append(new_field_from_numpy(x, u_new))
|
|
85
|
+
result.append(new_field_from_numpy(y, v_new))
|
|
77
86
|
|
|
78
|
-
return result
|
|
87
|
+
return new_fieldlist_from_list(result)
|
|
79
88
|
|
|
80
89
|
|
|
81
90
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# (C) Copyright 2024 Anemoi contributors.
|
|
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
|
+
#
|
|
6
|
+
# In applying this licence, ECMWF does not waive the privileges and immunities
|
|
7
|
+
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
|
+
# nor does it submit to any jurisdiction.
|
|
9
|
+
|
|
10
|
+
"""This module provides a function to convert u and v wind components to wind speed and direction."""
|
|
11
|
+
|
|
12
|
+
from collections import defaultdict
|
|
13
|
+
from typing import Any
|
|
14
|
+
from typing import List
|
|
15
|
+
|
|
16
|
+
import earthkit.data as ekd
|
|
17
|
+
import numpy as np
|
|
18
|
+
from anemoi.transform.fields import new_field_from_numpy
|
|
19
|
+
from anemoi.transform.fields import new_fieldlist_from_list
|
|
20
|
+
from earthkit.meteo.wind.array import xy_to_polar
|
|
21
|
+
|
|
22
|
+
from .legacy import legacy_filter
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@legacy_filter(__file__)
|
|
26
|
+
def execute(
|
|
27
|
+
context: Any,
|
|
28
|
+
input: List[Any],
|
|
29
|
+
u_component: str,
|
|
30
|
+
v_component: str,
|
|
31
|
+
wind_speed: str,
|
|
32
|
+
wind_dir: str,
|
|
33
|
+
in_radians: bool = False,
|
|
34
|
+
) -> ekd.FieldList:
|
|
35
|
+
"""Converts u and v wind components to wind speed and direction.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
context : Any
|
|
40
|
+
The context in which the function is executed.
|
|
41
|
+
input : List[Any]
|
|
42
|
+
List of input fields containing wind components.
|
|
43
|
+
u_component : str
|
|
44
|
+
The name of the u component field.
|
|
45
|
+
v_component : str
|
|
46
|
+
The name of the v component field.
|
|
47
|
+
wind_speed : str
|
|
48
|
+
The name of the wind speed field to be created.
|
|
49
|
+
wind_dir : str
|
|
50
|
+
The name of the wind direction field to be created.
|
|
51
|
+
in_radians : bool, optional
|
|
52
|
+
If True, the wind direction is returned in radians. Default is False.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
ekd.FieldList
|
|
57
|
+
A FieldArray containing the wind speed and direction fields.
|
|
58
|
+
"""
|
|
59
|
+
result = []
|
|
60
|
+
|
|
61
|
+
wind_params = (u_component, v_component)
|
|
62
|
+
wind_pairs = defaultdict(dict)
|
|
63
|
+
|
|
64
|
+
for f in input:
|
|
65
|
+
key = f.metadata(namespace="mars")
|
|
66
|
+
param = key.pop("param")
|
|
67
|
+
|
|
68
|
+
if param not in wind_params:
|
|
69
|
+
result.append(f)
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
key = tuple(key.items())
|
|
73
|
+
|
|
74
|
+
if param in wind_pairs[key]:
|
|
75
|
+
raise ValueError(f"Duplicate wind component {param} for {key}")
|
|
76
|
+
|
|
77
|
+
wind_pairs[key][param] = f
|
|
78
|
+
|
|
79
|
+
for _, pairs in wind_pairs.items():
|
|
80
|
+
if len(pairs) != 2:
|
|
81
|
+
raise ValueError("Missing wind component")
|
|
82
|
+
|
|
83
|
+
u = pairs[u_component]
|
|
84
|
+
v = pairs[v_component]
|
|
85
|
+
|
|
86
|
+
# assert speed.grid_mapping == dir.grid_mapping
|
|
87
|
+
magnitude, direction = xy_to_polar(u.to_numpy(flatten=True), v.to_numpy(flatten=True))
|
|
88
|
+
if in_radians:
|
|
89
|
+
direction = np.deg2rad(direction)
|
|
90
|
+
|
|
91
|
+
result.append(new_field_from_numpy(u, magnitude, params=wind_speed))
|
|
92
|
+
result.append(new_field_from_numpy(v, direction, params=wind_dir))
|
|
93
|
+
|
|
94
|
+
return new_fieldlist_from_list(result)
|
|
@@ -7,37 +7,39 @@
|
|
|
7
7
|
# granted to it by virtue of its status as an intergovernmental organisation
|
|
8
8
|
# nor does it submit to any jurisdiction.
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
from collections import defaultdict
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
import earthkit.data as ekd
|
|
14
|
+
from anemoi.transform.fields import new_field_from_numpy
|
|
15
|
+
from anemoi.transform.fields import new_fieldlist_from_list
|
|
16
|
+
|
|
17
|
+
from .legacy import legacy_filter
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@legacy_filter(__file__)
|
|
21
|
+
def execute(context: Any, input: ekd.FieldList, wz: str, t: str, w: str = "w") -> ekd.FieldList:
|
|
22
|
+
"""Convert geometric vertical velocity (m/s) to vertical velocity (Pa / s).
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
context : Any
|
|
27
|
+
The context for the execution.
|
|
28
|
+
input : List[Any]
|
|
29
|
+
The list of input fields.
|
|
30
|
+
wz : str
|
|
31
|
+
The parameter name for geometric vertical velocity.
|
|
32
|
+
t : str
|
|
33
|
+
The parameter name for temperature.
|
|
34
|
+
w : str, optional
|
|
35
|
+
The parameter name for vertical velocity. Defaults to "w".
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
ekd.FieldList
|
|
40
|
+
The resulting FieldArray with converted vertical velocity fields.
|
|
41
|
+
"""
|
|
42
|
+
result = []
|
|
41
43
|
|
|
42
44
|
params = (wz, t)
|
|
43
45
|
pairs = defaultdict(dict)
|
|
@@ -67,12 +69,28 @@ def execute(context, input, wz, t, w="w"):
|
|
|
67
69
|
pressure = keys[4][1] * 100 # TODO: REMOVE HARDCODED INDICES
|
|
68
70
|
|
|
69
71
|
w_pl = wz_to_w(wz_pl, t_pl, pressure)
|
|
70
|
-
result.append(
|
|
72
|
+
result.append(new_field_from_numpy(values[wz], w_pl, param=w))
|
|
73
|
+
|
|
74
|
+
return new_fieldlist_from_list(result)
|
|
75
|
+
|
|
71
76
|
|
|
72
|
-
|
|
77
|
+
def wz_to_w(wz: Any, t: Any, pressure: float) -> Any:
|
|
78
|
+
"""Convert geometric vertical velocity (m/s) to vertical velocity (Pa / s).
|
|
73
79
|
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
wz : Any
|
|
83
|
+
The geometric vertical velocity data.
|
|
84
|
+
t : Any
|
|
85
|
+
The temperature data.
|
|
86
|
+
pressure : float
|
|
87
|
+
The pressure value.
|
|
74
88
|
|
|
75
|
-
|
|
89
|
+
Returns
|
|
90
|
+
-------
|
|
91
|
+
Any
|
|
92
|
+
The vertical velocity data in Pa / s.
|
|
93
|
+
"""
|
|
76
94
|
g = 9.81
|
|
77
95
|
Rd = 287.058
|
|
78
96
|
|
|
@@ -9,14 +9,37 @@
|
|
|
9
9
|
|
|
10
10
|
import logging
|
|
11
11
|
from copy import deepcopy
|
|
12
|
+
from typing import Any
|
|
13
|
+
from typing import Union
|
|
14
|
+
|
|
15
|
+
from anemoi.datasets.dates.groups import GroupOfDates
|
|
12
16
|
|
|
13
17
|
from .trace import trace_select
|
|
14
18
|
|
|
15
19
|
LOG = logging.getLogger(__name__)
|
|
16
20
|
|
|
17
21
|
|
|
22
|
+
class Context:
|
|
23
|
+
"""Context for building input data."""
|
|
24
|
+
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
18
28
|
class InputBuilder:
|
|
19
|
-
|
|
29
|
+
"""Builder class for creating input data from configuration and data sources."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, config: dict, data_sources: Union[dict, list], **kwargs: Any) -> None:
|
|
32
|
+
"""Initialize the InputBuilder.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
config : dict
|
|
37
|
+
Configuration dictionary.
|
|
38
|
+
data_sources : Union[dict, list]
|
|
39
|
+
Data sources.
|
|
40
|
+
**kwargs : Any
|
|
41
|
+
Additional keyword arguments.
|
|
42
|
+
"""
|
|
20
43
|
self.kwargs = kwargs
|
|
21
44
|
|
|
22
45
|
config = deepcopy(config)
|
|
@@ -31,7 +54,19 @@ class InputBuilder:
|
|
|
31
54
|
self.action_path = ["input"]
|
|
32
55
|
|
|
33
56
|
@trace_select
|
|
34
|
-
def select(self, group_of_dates):
|
|
57
|
+
def select(self, group_of_dates: GroupOfDates) -> Any:
|
|
58
|
+
"""Select data based on the group of dates.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
group_of_dates : GroupOfDates
|
|
63
|
+
Group of dates to select data for.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
Any
|
|
68
|
+
Selected data.
|
|
69
|
+
"""
|
|
35
70
|
from .action import ActionContext
|
|
36
71
|
from .action import action_factory
|
|
37
72
|
|
|
@@ -40,7 +75,14 @@ class InputBuilder:
|
|
|
40
75
|
action = action_factory(self.config, context, self.action_path)
|
|
41
76
|
return action.select(group_of_dates)
|
|
42
77
|
|
|
43
|
-
def __repr__(self):
|
|
78
|
+
def __repr__(self) -> str:
|
|
79
|
+
"""Return a string representation of the InputBuilder.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
str
|
|
84
|
+
String representation.
|
|
85
|
+
"""
|
|
44
86
|
from .action import ActionContext
|
|
45
87
|
from .action import action_factory
|
|
46
88
|
|
|
@@ -48,8 +90,37 @@ class InputBuilder:
|
|
|
48
90
|
a = action_factory(self.config, context, self.action_path)
|
|
49
91
|
return repr(a)
|
|
50
92
|
|
|
51
|
-
def _trace_select(self, group_of_dates):
|
|
93
|
+
def _trace_select(self, group_of_dates: GroupOfDates) -> str:
|
|
94
|
+
"""Trace the select operation.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
group_of_dates : GroupOfDates
|
|
99
|
+
Group of dates to select data for.
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
str
|
|
104
|
+
Trace string.
|
|
105
|
+
"""
|
|
52
106
|
return f"InputBuilder({group_of_dates})"
|
|
53
107
|
|
|
54
108
|
|
|
55
|
-
build_input
|
|
109
|
+
def build_input(config: dict, data_sources: Union[dict, list], **kwargs: Any) -> InputBuilder:
|
|
110
|
+
"""Build an InputBuilder instance.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
config : dict
|
|
115
|
+
Configuration dictionary.
|
|
116
|
+
data_sources : Union[dict, list]
|
|
117
|
+
Data sources.
|
|
118
|
+
**kwargs : Any
|
|
119
|
+
Additional keyword arguments.
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
InputBuilder
|
|
124
|
+
An instance of InputBuilder.
|
|
125
|
+
"""
|
|
126
|
+
return InputBuilder(config, data_sources, **kwargs)
|
|
@@ -9,17 +9,49 @@
|
|
|
9
9
|
|
|
10
10
|
import logging
|
|
11
11
|
from copy import deepcopy
|
|
12
|
+
from typing import Any
|
|
13
|
+
from typing import Dict
|
|
14
|
+
from typing import List
|
|
12
15
|
|
|
13
16
|
from earthkit.data.core.order import build_remapping
|
|
14
17
|
|
|
18
|
+
from ...dates.groups import GroupOfDates
|
|
15
19
|
from .context import Context
|
|
16
|
-
from .misc import is_function
|
|
17
20
|
|
|
18
21
|
LOG = logging.getLogger(__name__)
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
class Action:
|
|
22
|
-
|
|
25
|
+
"""Represents an action to be performed within a given context.
|
|
26
|
+
|
|
27
|
+
Attributes
|
|
28
|
+
----------
|
|
29
|
+
context : ActionContext
|
|
30
|
+
The context in which the action exists.
|
|
31
|
+
kwargs : Dict[str, Any]
|
|
32
|
+
Additional keyword arguments.
|
|
33
|
+
args : Any
|
|
34
|
+
Additional positional arguments.
|
|
35
|
+
action_path : List[str]
|
|
36
|
+
The action path.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(
|
|
40
|
+
self, context: "ActionContext", action_path: List[str], /, *args: Any, **kwargs: Dict[str, Any]
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Initialize an Action instance.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
context : ActionContext
|
|
47
|
+
The context in which the action exists.
|
|
48
|
+
action_path : List[str]
|
|
49
|
+
The action path.
|
|
50
|
+
args : Any
|
|
51
|
+
Additional positional arguments.
|
|
52
|
+
kwargs : Dict[str, Any]
|
|
53
|
+
Additional keyword arguments.
|
|
54
|
+
"""
|
|
23
55
|
if "args" in kwargs and "kwargs" in kwargs:
|
|
24
56
|
"""We have:
|
|
25
57
|
args = []
|
|
@@ -38,13 +70,43 @@ class Action:
|
|
|
38
70
|
self.action_path = action_path
|
|
39
71
|
|
|
40
72
|
@classmethod
|
|
41
|
-
def _short_str(cls, x):
|
|
73
|
+
def _short_str(cls, x: str) -> str:
|
|
74
|
+
"""Shorten the string representation if it exceeds 1000 characters.
|
|
75
|
+
|
|
76
|
+
Parameters
|
|
77
|
+
----------
|
|
78
|
+
x : str
|
|
79
|
+
The string to shorten.
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
str
|
|
84
|
+
The shortened string.
|
|
85
|
+
"""
|
|
42
86
|
x = str(x)
|
|
43
87
|
if len(x) < 1000:
|
|
44
88
|
return x
|
|
45
89
|
return x[:1000] + "..."
|
|
46
90
|
|
|
47
|
-
def
|
|
91
|
+
def _repr(self, *args: Any, _indent_: str = "\n", _inline_: str = "", **kwargs: Any) -> str:
|
|
92
|
+
"""Generate a string representation of the Action instance.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
args : Any
|
|
97
|
+
Additional positional arguments.
|
|
98
|
+
_indent_ : str, optional
|
|
99
|
+
The indentation string, by default "\n".
|
|
100
|
+
_inline_ : str, optional
|
|
101
|
+
The inline string, by default "".
|
|
102
|
+
kwargs : Any
|
|
103
|
+
Additional keyword arguments.
|
|
104
|
+
|
|
105
|
+
Returns
|
|
106
|
+
-------
|
|
107
|
+
str
|
|
108
|
+
The string representation.
|
|
109
|
+
"""
|
|
48
110
|
more = ",".join([str(a)[:5000] for a in args])
|
|
49
111
|
more += ",".join([f"{k}={v}"[:5000] for k, v in kwargs.items()])
|
|
50
112
|
|
|
@@ -54,18 +116,77 @@ class Action:
|
|
|
54
116
|
txt = txt.replace("\n", "\n ")
|
|
55
117
|
return txt
|
|
56
118
|
|
|
57
|
-
def
|
|
119
|
+
def __repr__(self) -> str:
|
|
120
|
+
"""Return the string representation of the Action instance.
|
|
121
|
+
|
|
122
|
+
Returns
|
|
123
|
+
-------
|
|
124
|
+
str
|
|
125
|
+
The string representation.
|
|
126
|
+
"""
|
|
127
|
+
return self._repr()
|
|
128
|
+
|
|
129
|
+
def select(self, dates: object, **kwargs: Any) -> None:
|
|
130
|
+
"""Select dates for the action.
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
dates : object
|
|
135
|
+
The dates to select.
|
|
136
|
+
kwargs : Any
|
|
137
|
+
Additional keyword arguments.
|
|
138
|
+
"""
|
|
58
139
|
self._raise_not_implemented()
|
|
59
140
|
|
|
60
|
-
def _raise_not_implemented(self):
|
|
141
|
+
def _raise_not_implemented(self) -> None:
|
|
142
|
+
"""Raise a NotImplementedError indicating the method is not implemented."""
|
|
61
143
|
raise NotImplementedError(f"Not implemented in {self.__class__.__name__}")
|
|
62
144
|
|
|
63
|
-
def _trace_select(self, group_of_dates):
|
|
145
|
+
def _trace_select(self, group_of_dates: GroupOfDates) -> str:
|
|
146
|
+
"""Trace the selection of a group of dates.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
group_of_dates : GroupOfDates
|
|
151
|
+
The group of dates to trace.
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
str
|
|
156
|
+
The trace string.
|
|
157
|
+
"""
|
|
64
158
|
return f"{self.__class__.__name__}({group_of_dates})"
|
|
65
159
|
|
|
66
160
|
|
|
67
161
|
class ActionContext(Context):
|
|
68
|
-
|
|
162
|
+
"""Represents the context in which an action is performed.
|
|
163
|
+
|
|
164
|
+
Attributes
|
|
165
|
+
----------
|
|
166
|
+
order_by : str
|
|
167
|
+
The order by criteria.
|
|
168
|
+
flatten_grid : bool
|
|
169
|
+
Whether to flatten the grid.
|
|
170
|
+
remapping : Dict[str, Any]
|
|
171
|
+
The remapping configuration.
|
|
172
|
+
use_grib_paramid : bool
|
|
173
|
+
Whether to use GRIB parameter ID.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
def __init__(self, /, order_by: str, flatten_grid: bool, remapping: Dict[str, Any], use_grib_paramid: bool) -> None:
|
|
177
|
+
"""Initialize an ActionContext instance.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
order_by : str
|
|
182
|
+
The order by criteria.
|
|
183
|
+
flatten_grid : bool
|
|
184
|
+
Whether to flatten the grid.
|
|
185
|
+
remapping : Dict[str, Any]
|
|
186
|
+
The remapping configuration.
|
|
187
|
+
use_grib_paramid : bool
|
|
188
|
+
Whether to use GRIB parameter ID.
|
|
189
|
+
"""
|
|
69
190
|
super().__init__()
|
|
70
191
|
self.order_by = order_by
|
|
71
192
|
self.flatten_grid = flatten_grid
|
|
@@ -73,8 +194,23 @@ class ActionContext(Context):
|
|
|
73
194
|
self.use_grib_paramid = use_grib_paramid
|
|
74
195
|
|
|
75
196
|
|
|
76
|
-
def action_factory(config, context, action_path):
|
|
197
|
+
def action_factory(config: Dict[str, Any], context: ActionContext, action_path: List[str]) -> Action:
|
|
198
|
+
"""Factory function to create an Action instance based on the configuration.
|
|
77
199
|
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
config : Dict[str, Any]
|
|
203
|
+
The action configuration.
|
|
204
|
+
context : ActionContext
|
|
205
|
+
The context in which the action exists.
|
|
206
|
+
action_path : List[str]
|
|
207
|
+
The action path.
|
|
208
|
+
|
|
209
|
+
Returns
|
|
210
|
+
-------
|
|
211
|
+
Action
|
|
212
|
+
The created Action instance.
|
|
213
|
+
"""
|
|
78
214
|
from .concat import ConcatAction
|
|
79
215
|
from .data_sources import DataSourcesAction
|
|
80
216
|
from .function import FunctionAction
|
|
@@ -110,9 +246,9 @@ def action_factory(config, context, action_path):
|
|
|
110
246
|
}.get(key)
|
|
111
247
|
|
|
112
248
|
if cls is None:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
249
|
+
from ..sources import create_source
|
|
250
|
+
|
|
251
|
+
source = create_source(None, config)
|
|
252
|
+
return FunctionAction(context, action_path + [key], key, source)
|
|
117
253
|
|
|
118
254
|
return cls(context, action_path + [key], *args, **kwargs)
|