anemoi-datasets 0.5.27__py3-none-any.whl → 0.5.28__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.
Files changed (61) hide show
  1. anemoi/datasets/_version.py +2 -2
  2. anemoi/datasets/commands/recipe/__init__.py +93 -0
  3. anemoi/datasets/commands/recipe/format.py +55 -0
  4. anemoi/datasets/commands/recipe/migrate.py +555 -0
  5. anemoi/datasets/create/__init__.py +42 -1
  6. anemoi/datasets/create/config.py +2 -0
  7. anemoi/datasets/create/input/__init__.py +43 -63
  8. anemoi/datasets/create/input/action.py +296 -236
  9. anemoi/datasets/create/input/context/__init__.py +71 -0
  10. anemoi/datasets/create/input/context/field.py +54 -0
  11. anemoi/datasets/create/input/data_sources.py +2 -1
  12. anemoi/datasets/create/input/misc.py +0 -71
  13. anemoi/datasets/create/input/repeated_dates.py +0 -114
  14. anemoi/datasets/create/input/result/__init__.py +17 -0
  15. anemoi/datasets/create/input/{result.py → result/field.py} +9 -89
  16. anemoi/datasets/create/sources/accumulations.py +74 -94
  17. anemoi/datasets/create/sources/accumulations2.py +16 -45
  18. anemoi/datasets/create/sources/anemoi_dataset.py +46 -42
  19. anemoi/datasets/create/sources/constants.py +39 -38
  20. anemoi/datasets/create/sources/empty.py +26 -22
  21. anemoi/datasets/create/sources/forcings.py +29 -28
  22. anemoi/datasets/create/sources/grib.py +92 -72
  23. anemoi/datasets/create/sources/grib_index.py +46 -42
  24. anemoi/datasets/create/sources/hindcasts.py +56 -55
  25. anemoi/datasets/create/sources/legacy.py +10 -62
  26. anemoi/datasets/create/sources/mars.py +107 -131
  27. anemoi/datasets/create/sources/netcdf.py +28 -24
  28. anemoi/datasets/create/sources/opendap.py +28 -24
  29. anemoi/datasets/create/sources/recentre.py +42 -41
  30. anemoi/datasets/create/sources/repeated_dates.py +44 -0
  31. anemoi/datasets/create/sources/source.py +26 -48
  32. anemoi/datasets/create/sources/tendencies.py +67 -94
  33. anemoi/datasets/create/sources/xarray_support/__init__.py +29 -24
  34. anemoi/datasets/create/sources/xarray_support/field.py +4 -4
  35. anemoi/datasets/create/sources/xarray_zarr.py +28 -24
  36. anemoi/datasets/create/sources/zenodo.py +43 -39
  37. anemoi/datasets/create/utils.py +0 -42
  38. anemoi/datasets/data/dataset.py +6 -0
  39. anemoi/datasets/data/grids.py +0 -152
  40. anemoi/datasets/data/rolling_average.py +141 -0
  41. anemoi/datasets/data/stores.py +7 -9
  42. anemoi/datasets/dates/__init__.py +2 -0
  43. anemoi/datasets/dumper.py +76 -0
  44. anemoi/datasets/grids.py +1 -178
  45. anemoi/datasets/schemas/recipe.json +131 -0
  46. {anemoi_datasets-0.5.27.dist-info → anemoi_datasets-0.5.28.dist-info}/METADATA +5 -2
  47. {anemoi_datasets-0.5.27.dist-info → anemoi_datasets-0.5.28.dist-info}/RECORD +51 -51
  48. anemoi/datasets/create/filter.py +0 -47
  49. anemoi/datasets/create/input/concat.py +0 -161
  50. anemoi/datasets/create/input/context.py +0 -86
  51. anemoi/datasets/create/input/empty.py +0 -53
  52. anemoi/datasets/create/input/filter.py +0 -117
  53. anemoi/datasets/create/input/function.py +0 -232
  54. anemoi/datasets/create/input/join.py +0 -129
  55. anemoi/datasets/create/input/pipe.py +0 -66
  56. anemoi/datasets/create/input/step.py +0 -173
  57. anemoi/datasets/create/input/template.py +0 -161
  58. {anemoi_datasets-0.5.27.dist-info → anemoi_datasets-0.5.28.dist-info}/WHEEL +0 -0
  59. {anemoi_datasets-0.5.27.dist-info → anemoi_datasets-0.5.28.dist-info}/entry_points.txt +0 -0
  60. {anemoi_datasets-0.5.27.dist-info → anemoi_datasets-0.5.28.dist-info}/licenses/LICENSE +0 -0
  61. {anemoi_datasets-0.5.27.dist-info → anemoi_datasets-0.5.28.dist-info}/top_level.txt +0 -0
@@ -1,53 +0,0 @@
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
- import logging
11
- from functools import cached_property
12
-
13
- from earthkit.data import FieldList
14
-
15
- from .misc import assert_fieldlist
16
- from .result import Result
17
- from .trace import trace_datasource
18
-
19
- LOG = logging.getLogger(__name__)
20
-
21
-
22
- class EmptyResult(Result):
23
- """Class to represent an empty result in the dataset creation process."""
24
-
25
- empty = True
26
-
27
- def __init__(self, context: object, action_path: list, dates: object) -> None:
28
- """Initializes an EmptyResult instance.
29
-
30
- Parameters
31
- ----------
32
- context : object
33
- The context object.
34
- action_path : list
35
- The action path.
36
- dates : object
37
- The dates object.
38
- """
39
- super().__init__(context, action_path + ["empty"], dates)
40
-
41
- @cached_property
42
- @assert_fieldlist
43
- @trace_datasource
44
- def datasource(self) -> FieldList:
45
- """Returns an empty datasource."""
46
- from earthkit.data import from_source
47
-
48
- return from_source("empty")
49
-
50
- @property
51
- def variables(self) -> list[str]:
52
- """Returns an empty list of variables."""
53
- return []
@@ -1,117 +0,0 @@
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
- import logging
11
- from functools import cached_property
12
- from typing import Any
13
-
14
- from earthkit.data import FieldList
15
-
16
- from .function import FunctionContext
17
- from .misc import _tidy
18
- from .misc import assert_fieldlist
19
- from .step import StepAction
20
- from .step import StepResult
21
- from .template import notify_result
22
- from .trace import trace_datasource
23
-
24
- LOG = logging.getLogger(__name__)
25
-
26
-
27
- class FilterStepResult(StepResult):
28
- @property
29
- @notify_result
30
- @assert_fieldlist
31
- @trace_datasource
32
- def datasource(self) -> FieldList:
33
- """Returns the filtered datasource."""
34
- ds: FieldList = self.upstream_result.datasource
35
- ds = ds.sel(**self.action.kwargs)
36
- return _tidy(ds)
37
-
38
-
39
- class FilterStepAction(StepAction):
40
- """Represents an action to filter a step result."""
41
-
42
- result_class: type[FilterStepResult] = FilterStepResult
43
-
44
-
45
- class StepFunctionResult(StepResult):
46
- @cached_property
47
- @assert_fieldlist
48
- @notify_result
49
- @trace_datasource
50
- def datasource(self) -> FieldList:
51
- """Returns the datasource after applying the function."""
52
-
53
- self.action.filter.context = FunctionContext(self)
54
- try:
55
- return _tidy(
56
- self.action.filter.execute(
57
- self.upstream_result.datasource,
58
- *self.action.args[1:],
59
- **self.action.kwargs,
60
- )
61
- )
62
-
63
- except Exception:
64
- LOG.error(f"Error in {self.action.name}", exc_info=True)
65
- raise
66
-
67
- def _trace_datasource(self, *args: Any, **kwargs: Any) -> str:
68
- """Traces the datasource for the given arguments.
69
-
70
- Parameters
71
- ----------
72
- *args : Any
73
- The arguments.
74
- **kwargs : Any
75
- The keyword arguments.
76
-
77
- Returns
78
- -------
79
- str
80
- A string representation of the traced datasource.
81
- """
82
- return f"{self.action.name}({self.group_of_dates})"
83
-
84
-
85
- class FunctionStepAction(StepAction):
86
- """Represents an action to apply a function to a step result."""
87
-
88
- result_class: type[StepFunctionResult] = StepFunctionResult
89
-
90
- def __init__(
91
- self,
92
- context: object,
93
- action_path: list,
94
- previous_step: StepAction,
95
- name: str,
96
- filter: Any,
97
- *args: Any,
98
- **kwargs: Any,
99
- ) -> None:
100
- """Initializes a FunctionStepAction instance.
101
-
102
- Parameters
103
- ----------
104
- context : object
105
- The context object.
106
- action_path : list
107
- The action path.
108
- previous_step : StepAction
109
- The previous step action.
110
- *args : Any
111
- Additional arguments.
112
- **kwargs : Any
113
- Additional keyword arguments.
114
- """
115
- super().__init__(context, action_path, previous_step, *args, **kwargs)
116
- self.name = name
117
- self.filter = filter
@@ -1,232 +0,0 @@
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
- import logging
11
- from functools import cached_property
12
- from typing import Any
13
-
14
- from earthkit.data import FieldList
15
-
16
- from ...dates.groups import GroupOfDates
17
- from .action import Action
18
- from .misc import _tidy
19
- from .misc import assert_fieldlist
20
- from .result import Result
21
- from .template import notify_result
22
- from .template import substitute
23
- from .trace import trace
24
- from .trace import trace_datasource
25
- from .trace import trace_select
26
-
27
- LOG = logging.getLogger(__name__)
28
-
29
-
30
- class FunctionContext:
31
- """A FunctionContext is passed to all functions, it will be used to pass information
32
- to the functions from the other actions and filters and results.
33
- """
34
-
35
- def __init__(self, owner: Result) -> None:
36
- """Initializes a FunctionContext instance.
37
-
38
- Parameters
39
- ----------
40
- owner : object
41
- The owner object.
42
- """
43
- self.owner = owner
44
- self.use_grib_paramid: bool = owner.context.use_grib_paramid
45
-
46
- def trace(self, emoji: str, *args: Any) -> None:
47
- """Traces the given arguments with an emoji.
48
-
49
- Parameters
50
- ----------
51
- emoji : str
52
- The emoji to use.
53
- *args : Any
54
- The arguments to trace.
55
- """
56
- trace(emoji, *args)
57
-
58
- def info(self, *args: Any, **kwargs: Any) -> None:
59
- """Logs an info message.
60
-
61
- Parameters
62
- ----------
63
- *args : Any
64
- The arguments for the log message.
65
- **kwargs : Any
66
- The keyword arguments for the log message.
67
- """
68
- LOG.info(*args, **kwargs)
69
-
70
- @property
71
- def dates_provider(self) -> object:
72
- """Returns the dates provider."""
73
- return self.owner.group_of_dates.provider
74
-
75
- @property
76
- def partial_ok(self) -> bool:
77
- """Returns whether partial results are acceptable."""
78
- return self.owner.group_of_dates.partial_ok
79
-
80
- def get_result(self, *args, **kwargs) -> Any:
81
- return self.owner.context.get_result(*args, **kwargs)
82
-
83
-
84
- class FunctionAction(Action):
85
- """Represents an action that executes a function.
86
-
87
- Attributes
88
- ----------
89
- name : str
90
- The name of the function.
91
- """
92
-
93
- def __init__(self, context: object, action_path: list, _name: str, source, **kwargs: dict[str, Any]) -> None:
94
- """Initializes a FunctionAction instance.
95
-
96
- Parameters
97
- ----------
98
- context : object
99
- The context object.
100
- action_path : list
101
- The action path.
102
- _name : str
103
- The name of the function.
104
- **kwargs : Dict[str, Any]
105
- Additional keyword arguments.
106
- """
107
- super().__init__(context, action_path, **kwargs)
108
- self.name: str = _name
109
- self.source = source
110
-
111
- @trace_select
112
- def select(self, group_of_dates: GroupOfDates) -> "FunctionResult":
113
- """Selects the function result for the given group of dates.
114
-
115
- Parameters
116
- ----------
117
- group_of_dates : GroupOfDates
118
- The group of dates.
119
-
120
- Returns
121
- -------
122
- FunctionResult
123
- The function result instance.
124
- """
125
- return FunctionResult(self.context, self.action_path, group_of_dates, action=self)
126
-
127
- def __repr__(self) -> str:
128
- """Returns a string representation of the FunctionAction instance."""
129
- content: str = ""
130
- content += ",".join([self._short_str(a) for a in self.args])
131
- content += " ".join([self._short_str(f"{k}={v}") for k, v in self.kwargs.items()])
132
- content = self._short_str(content)
133
- return self._repr(_inline_=content, _indent_=" ")
134
-
135
- def _trace_select(self, group_of_dates: GroupOfDates) -> str:
136
- """Traces the selection of the function for the given group of dates.
137
-
138
- Parameters
139
- ----------
140
- group_of_dates : GroupOfDates
141
- The group of dates.
142
-
143
- Returns
144
- -------
145
- str
146
- The trace string.
147
- """
148
- return f"{self.name}({group_of_dates})"
149
-
150
-
151
- class FunctionResult(Result):
152
- """Represents the result of executing a function.
153
-
154
- Attributes
155
- ----------
156
- action : Action
157
- The action instance.
158
- args : tuple
159
- The positional arguments for the function.
160
- kwargs : dict
161
- The keyword arguments for the function.
162
- """
163
-
164
- def __init__(self, context: object, action_path: list, group_of_dates: GroupOfDates, action: Action) -> None:
165
- """Initializes a FunctionResult instance.
166
-
167
- Parameters
168
- ----------
169
- context : object
170
- The context object.
171
- action_path : list
172
- The action path.
173
- group_of_dates : GroupOfDates
174
- The group of dates.
175
- action : Action
176
- The action instance.
177
- """
178
- super().__init__(context, action_path, group_of_dates)
179
- assert isinstance(action, Action), type(action)
180
- self.action: Action = action
181
-
182
- self.args, self.kwargs = substitute(context, (self.action.args, self.action.kwargs))
183
-
184
- def _trace_datasource(self, *args: Any, **kwargs: Any) -> str:
185
- """Traces the datasource for the given arguments.
186
-
187
- Parameters
188
- ----------
189
- *args : Any
190
- The arguments.
191
- **kwargs : Any
192
- The keyword arguments.
193
-
194
- Returns
195
- -------
196
- str
197
- The trace string.
198
- """
199
- return f"{self.action.name}({self.group_of_dates})"
200
-
201
- @cached_property
202
- @assert_fieldlist
203
- @notify_result
204
- @trace_datasource
205
- def datasource(self) -> FieldList:
206
- """Returns the datasource for the function result."""
207
- # args, kwargs = resolve(self.context, (self.args, self.kwargs))
208
- self.action.source.context = FunctionContext(self)
209
-
210
- return _tidy(
211
- self.action.source.execute(
212
- list(self.group_of_dates), # Will provide a list of datetime objects
213
- )
214
- )
215
-
216
- def __repr__(self) -> str:
217
- """Returns a string representation of the FunctionResult instance."""
218
- try:
219
- return f"{self.action.name}({self.group_of_dates})"
220
- except Exception:
221
- return f"{self.__class__.__name__}(unitialised)"
222
-
223
- @property
224
- def function(self) -> None:
225
- """Raises NotImplementedError as this property is not implemented.
226
-
227
- Raises
228
- ------
229
- NotImplementedError
230
- Always raised.
231
- """
232
- raise NotImplementedError(f"Not implemented in {self.__class__.__name__}")
@@ -1,129 +0,0 @@
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
- import logging
11
- from functools import cached_property
12
- from typing import Any
13
-
14
- from earthkit.data import FieldList
15
-
16
- from ...dates.groups import GroupOfDates
17
- from .action import Action
18
- from .action import action_factory
19
- from .empty import EmptyResult
20
- from .misc import _tidy
21
- from .misc import assert_fieldlist
22
- from .result import Result
23
- from .template import notify_result
24
- from .trace import trace_datasource
25
- from .trace import trace_select
26
-
27
- LOG = logging.getLogger(__name__)
28
-
29
-
30
- class JoinResult(Result):
31
- """Represents a result that combines multiple results.
32
-
33
- Attributes
34
- ----------
35
- context : object
36
- The context object.
37
- action_path : list
38
- The action path.
39
- group_of_dates : GroupOfDates
40
- The group of dates.
41
- results : List[Result]
42
- The list of results.
43
- """
44
-
45
- def __init__(
46
- self, context: object, action_path: list, group_of_dates: GroupOfDates, results: list[Result], **kwargs: Any
47
- ) -> None:
48
- """Initializes a JoinResult instance.
49
-
50
- Parameters
51
- ----------
52
- context : object
53
- The context object.
54
- action_path : list
55
- The action path.
56
- group_of_dates : GroupOfDates
57
- The group of dates.
58
- results : List[Result]
59
- The list of results.
60
- """
61
- super().__init__(context, action_path, group_of_dates)
62
- self.results: list[Result] = [r for r in results if not r.empty]
63
-
64
- @cached_property
65
- @assert_fieldlist
66
- @notify_result
67
- @trace_datasource
68
- def datasource(self) -> FieldList:
69
- """Returns the combined datasource from all results."""
70
- ds: FieldList = EmptyResult(self.context, self.action_path, self.group_of_dates).datasource
71
- for i in self.results:
72
- ds += i.datasource
73
- return _tidy(ds)
74
-
75
- def __repr__(self) -> str:
76
- """Returns a string representation of the JoinResult instance."""
77
- content: str = "\n".join([str(i) for i in self.results])
78
- return self._repr(content)
79
-
80
-
81
- class JoinAction(Action):
82
- """Represents an action that combines multiple actions.
83
-
84
- Attributes
85
- ----------
86
- context : object
87
- The context object.
88
- action_path : list
89
- The action path.
90
- actions : List[Action]
91
- The list of actions.
92
- """
93
-
94
- def __init__(self, context: object, action_path: list, *configs: dict) -> None:
95
- """Initializes a JoinAction instance.
96
-
97
- Parameters
98
- ----------
99
- context : object
100
- The context object.
101
- action_path : list
102
- The action path.
103
- *configs : dict
104
- The configuration dictionaries.
105
- """
106
- super().__init__(context, action_path, *configs)
107
- self.actions: list[Action] = [action_factory(c, context, action_path + [str(i)]) for i, c in enumerate(configs)]
108
-
109
- def __repr__(self) -> str:
110
- """Returns a string representation of the JoinAction instance."""
111
- content: str = "\n".join([str(i) for i in self.actions])
112
- return self._repr(content)
113
-
114
- @trace_select
115
- def select(self, group_of_dates: GroupOfDates) -> JoinResult:
116
- """Selects the results for the given group of dates.
117
-
118
- Parameters
119
- ----------
120
- group_of_dates : GroupOfDates
121
- The group of dates.
122
-
123
- Returns
124
- -------
125
- JoinResult
126
- The combined result for the given group of dates.
127
- """
128
- results: list[Result] = [a.select(group_of_dates) for a in self.actions]
129
- return JoinResult(self.context, self.action_path, group_of_dates, results)
@@ -1,66 +0,0 @@
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
- import json
11
- import logging
12
- from typing import Any
13
-
14
- from .action import Action
15
- from .action import action_factory
16
- from .step import step_factory
17
- from .trace import trace_select
18
-
19
- LOG = logging.getLogger(__name__)
20
-
21
-
22
- class PipeAction(Action):
23
- """A class to represent a pipeline of actions."""
24
-
25
- def __init__(self, context: Any, action_path: list, *configs: dict) -> None:
26
- """Initialize the PipeAction.
27
-
28
- Parameters
29
- ----------
30
- context : Any
31
- The context for the action.
32
- action_path : list
33
- The path of the action.
34
- configs : dict
35
- The configurations for the actions.
36
- """
37
- super().__init__(context, action_path, *configs)
38
- if len(configs) <= 1:
39
- raise ValueError(
40
- f"PipeAction requires at least two actions, got {len(configs)}\n{json.dumps(configs, indent=2)}"
41
- )
42
-
43
- current: Any = action_factory(configs[0], context, action_path + ["0"])
44
- for i, c in enumerate(configs[1:]):
45
- current = step_factory(c, context, action_path + [str(i + 1)], previous_step=current)
46
- self.last_step: Any = current
47
-
48
- @trace_select
49
- def select(self, group_of_dates: Any) -> Any:
50
- """Select data based on the group of dates.
51
-
52
- Parameters
53
- ----------
54
- group_of_dates : Any
55
- The group of dates to select data for.
56
-
57
- Returns
58
- -------
59
- Any
60
- The selected data.
61
- """
62
- return self.last_step.select(group_of_dates)
63
-
64
- def __repr__(self) -> str:
65
- """Return a string representation of the PipeAction."""
66
- return f"PipeAction({self.last_step})"