openstef 3.4.56__py3-none-any.whl → 4.0.0a3__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 (104) hide show
  1. openstef-4.0.0a3.dist-info/METADATA +177 -0
  2. openstef-4.0.0a3.dist-info/RECORD +4 -0
  3. {openstef-3.4.56.dist-info → openstef-4.0.0a3.dist-info}/WHEEL +1 -2
  4. openstef/__init__.py +0 -14
  5. openstef/__main__.py +0 -3
  6. openstef/app_settings.py +0 -19
  7. openstef/data/NL_terrestrial_radiation.csv +0 -25585
  8. openstef/data/NL_terrestrial_radiation.csv.license +0 -3
  9. openstef/data/dazls_model_3.4.24/dazls_stored_3.4.24_baseline_model.z +0 -0
  10. openstef/data/dazls_model_3.4.24/dazls_stored_3.4.24_baseline_model.z.license +0 -3
  11. openstef/data/dazls_model_3.4.24/dazls_stored_3.4.24_model_card.md +0 -18
  12. openstef/data/dazls_model_3.4.24/dazls_stored_3.4.24_model_card.md.license +0 -3
  13. openstef/data/dutch_holidays.csv +0 -1759
  14. openstef/data/dutch_holidays.csv.license +0 -3
  15. openstef/data/pv_single_coefs.csv +0 -601
  16. openstef/data/pv_single_coefs.csv.license +0 -3
  17. openstef/data_classes/__init__.py +0 -3
  18. openstef/data_classes/data_prep.py +0 -99
  19. openstef/data_classes/model_specifications.py +0 -30
  20. openstef/data_classes/prediction_job.py +0 -135
  21. openstef/data_classes/split_function.py +0 -97
  22. openstef/enums.py +0 -140
  23. openstef/exceptions.py +0 -74
  24. openstef/feature_engineering/__init__.py +0 -3
  25. openstef/feature_engineering/apply_features.py +0 -138
  26. openstef/feature_engineering/bidding_zone_to_country_mapping.py +0 -106
  27. openstef/feature_engineering/cyclic_features.py +0 -161
  28. openstef/feature_engineering/data_preparation.py +0 -152
  29. openstef/feature_engineering/feature_adder.py +0 -206
  30. openstef/feature_engineering/feature_applicator.py +0 -202
  31. openstef/feature_engineering/general.py +0 -141
  32. openstef/feature_engineering/holiday_features.py +0 -231
  33. openstef/feature_engineering/lag_features.py +0 -165
  34. openstef/feature_engineering/missing_values_transformer.py +0 -141
  35. openstef/feature_engineering/rolling_features.py +0 -58
  36. openstef/feature_engineering/weather_features.py +0 -492
  37. openstef/metrics/__init__.py +0 -3
  38. openstef/metrics/figure.py +0 -303
  39. openstef/metrics/metrics.py +0 -486
  40. openstef/metrics/reporter.py +0 -222
  41. openstef/model/__init__.py +0 -3
  42. openstef/model/basecase.py +0 -82
  43. openstef/model/confidence_interval_applicator.py +0 -242
  44. openstef/model/fallback.py +0 -77
  45. openstef/model/metamodels/__init__.py +0 -3
  46. openstef/model/metamodels/feature_clipper.py +0 -90
  47. openstef/model/metamodels/grouped_regressor.py +0 -222
  48. openstef/model/metamodels/missing_values_handler.py +0 -138
  49. openstef/model/model_creator.py +0 -214
  50. openstef/model/objective.py +0 -426
  51. openstef/model/objective_creator.py +0 -65
  52. openstef/model/regressors/__init__.py +0 -3
  53. openstef/model/regressors/arima.py +0 -197
  54. openstef/model/regressors/custom_regressor.py +0 -64
  55. openstef/model/regressors/dazls.py +0 -116
  56. openstef/model/regressors/flatliner.py +0 -95
  57. openstef/model/regressors/gblinear_quantile.py +0 -334
  58. openstef/model/regressors/lgbm.py +0 -29
  59. openstef/model/regressors/linear.py +0 -90
  60. openstef/model/regressors/linear_quantile.py +0 -305
  61. openstef/model/regressors/regressor.py +0 -114
  62. openstef/model/regressors/xgb.py +0 -52
  63. openstef/model/regressors/xgb_multioutput_quantile.py +0 -261
  64. openstef/model/regressors/xgb_quantile.py +0 -228
  65. openstef/model/serializer.py +0 -431
  66. openstef/model/standard_deviation_generator.py +0 -81
  67. openstef/model_selection/__init__.py +0 -3
  68. openstef/model_selection/model_selection.py +0 -311
  69. openstef/monitoring/__init__.py +0 -3
  70. openstef/monitoring/performance_meter.py +0 -92
  71. openstef/monitoring/teams.py +0 -203
  72. openstef/pipeline/__init__.py +0 -3
  73. openstef/pipeline/create_basecase_forecast.py +0 -133
  74. openstef/pipeline/create_component_forecast.py +0 -168
  75. openstef/pipeline/create_forecast.py +0 -171
  76. openstef/pipeline/optimize_hyperparameters.py +0 -317
  77. openstef/pipeline/train_create_forecast_backtest.py +0 -163
  78. openstef/pipeline/train_model.py +0 -561
  79. openstef/pipeline/utils.py +0 -52
  80. openstef/postprocessing/__init__.py +0 -3
  81. openstef/postprocessing/postprocessing.py +0 -275
  82. openstef/preprocessing/__init__.py +0 -3
  83. openstef/preprocessing/preprocessing.py +0 -42
  84. openstef/settings.py +0 -15
  85. openstef/tasks/__init__.py +0 -3
  86. openstef/tasks/calculate_kpi.py +0 -324
  87. openstef/tasks/create_basecase_forecast.py +0 -118
  88. openstef/tasks/create_components_forecast.py +0 -162
  89. openstef/tasks/create_forecast.py +0 -145
  90. openstef/tasks/create_solar_forecast.py +0 -420
  91. openstef/tasks/create_wind_forecast.py +0 -80
  92. openstef/tasks/optimize_hyperparameters.py +0 -135
  93. openstef/tasks/split_forecast.py +0 -273
  94. openstef/tasks/train_model.py +0 -224
  95. openstef/tasks/utils/__init__.py +0 -3
  96. openstef/tasks/utils/dependencies.py +0 -107
  97. openstef/tasks/utils/predictionjobloop.py +0 -243
  98. openstef/tasks/utils/taskcontext.py +0 -160
  99. openstef/validation/__init__.py +0 -3
  100. openstef/validation/validation.py +0 -322
  101. openstef-3.4.56.dist-info/METADATA +0 -154
  102. openstef-3.4.56.dist-info/RECORD +0 -102
  103. openstef-3.4.56.dist-info/top_level.txt +0 -1
  104. /openstef-3.4.56.dist-info/LICENSE → /openstef-4.0.0a3.dist-info/licenses/LICENSE.md +0 -0
@@ -1,243 +0,0 @@
1
- # SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com> # noqa E501>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
-
5
- import random
6
- import sys
7
- from collections import defaultdict
8
- from itertools import chain
9
- from typing import Callable
10
-
11
- from openstef.data_classes.prediction_job import PredictionJobDataClass
12
- from openstef.exceptions import PredictionJobException
13
- from openstef.tasks.utils.dependencies import find_groups, has_dependencies
14
- from openstef.tasks.utils.taskcontext import TaskContext
15
-
16
-
17
- class PredictionJobLoop:
18
- """Convenience objects that maps a function over prediction jobs.
19
-
20
- Default behaviour is to automatically get prediction jobs from the
21
- database. Any keyword argument passed will be directed to the getting
22
- function. If another set of prediction jobs is desired, manually pass
23
- them using the prediction_jobs argument.
24
-
25
- Tip: For debugging a specific PID, use debug_pid=specific_pid
26
-
27
- Args:
28
- context: The context to run this loop in.
29
- stop_on_exception: Whether to break out of the
30
- loop when an exception is raised. Defaults to False.
31
- random_order: Whether to randomize the order of the
32
- prediction jobs. Defaults to True. Does not apply to manually
33
- passed prediction jobs.
34
- on_exception_callback: Callback, will be called
35
- everytime an exception is raised. Callable gets the pj and
36
- exception raised as arguments
37
- on_successful_callback: Callback, will be called
38
- everytime an iteration is successful (no exception is raised).
39
- Callable gets the pj as argument.
40
- on_end_callback: Callback, will be called everytime an
41
- iteration is completed. Callable gets the pj and and bool
42
- indicating success as argument.
43
- prediction_jobs: Manually pass a list of
44
- prediction jobs that will be looped over. If set to None, will fetch
45
- prediction jobs from database based on pj_kwargs
46
- debug_pid: enter a specific pid for debugging.
47
- If not None, the prediction job loop will only look at this pid
48
- **pj_kwargs: Any other kwargs willed will be directed to the
49
- prediction job getting function.
50
-
51
- """
52
-
53
- def __init__(
54
- self,
55
- context: TaskContext,
56
- stop_on_exception: bool = False,
57
- random_order: bool = True,
58
- on_exception_callback: Callable = None,
59
- on_successful_callback: Callable = None,
60
- on_end_callback: Callable = None,
61
- prediction_jobs: list[PredictionJobDataClass] = None,
62
- debug_pid: int = None,
63
- **pj_kwargs
64
- ):
65
- """Initialzie prediction job loop."""
66
- self.context = context
67
- self.stop_on_exception = stop_on_exception
68
- self.random_order = random_order
69
- self.on_exception_callback = on_exception_callback
70
- self.on_successful_callback = on_successful_callback
71
- self.on_end_callback = on_end_callback
72
- self.pj_kwargs = pj_kwargs
73
- self.debug_pid = debug_pid
74
-
75
- if prediction_jobs is None:
76
- self.prediction_jobs = self._get_prediction_jobs()
77
- else:
78
- self.prediction_jobs = prediction_jobs
79
-
80
- if has_dependencies(self.prediction_jobs):
81
- # Groups so that prediction jobs in each group
82
- # depend only on the pj in the previous groups
83
- _, pj_groups = find_groups(self.prediction_jobs, self.random_order)
84
- # Concatenate groups
85
- self.prediction_jobs = list(chain(*pj_groups))
86
- else:
87
- if self.random_order:
88
- random.shuffle(self.prediction_jobs)
89
-
90
- def _get_prediction_jobs(self):
91
- """Fetches prediction jobs from database."""
92
- self.context.logger.info(
93
- "Querying prediction jobs from database", **self.pj_kwargs
94
- )
95
- if self.debug_pid is None:
96
- prediction_jobs = self.context.database.get_prediction_jobs(
97
- **self.pj_kwargs
98
- )
99
- else:
100
- # retrieve prediction_job for single pid - useful for debugging
101
- prediction_jobs = [
102
- self.context.database.get_prediction_job(
103
- pid=self.debug_pid, **self.pj_kwargs
104
- )
105
- ]
106
-
107
- return prediction_jobs
108
-
109
- def map(self, function: Callable, *args, **kwargs):
110
- """Maps the passed function over all prediction jobs.
111
-
112
- Args:
113
- function: The function that will be applied to each prediction
114
- job separately.
115
- *args: Any other arguments or passed to the function.
116
- **kwargs: All keyword arguments are passed to the function. This method is
117
- highly prefered over using args, since kwargs will be automatically
118
- logged.
119
-
120
- Raises:
121
- PredictionJobException: This exception will be raised if one or more
122
- prediction jobs raised an exception during the loop.
123
-
124
- """
125
- pids_successful = []
126
- pids_unsuccessful = []
127
- pids_unsuccessful_dict = defaultdict(list)
128
- last_job_exception = None
129
-
130
- num_jobs = len(self.prediction_jobs)
131
- self.context.perf_meter.checkpoint("pre-loop")
132
-
133
- # loop over prediction jobs
134
- for i, prediction_job in enumerate(self.prediction_jobs):
135
- successful = False
136
-
137
- self.context.logger = self.context.logger.bind(
138
- prediction_id=prediction_job["id"],
139
- prediction_name=prediction_job["name"],
140
- )
141
-
142
- self.context.perf_meter.start_level(
143
- "iteration", i, num_jobs=num_jobs, pid=prediction_job["id"], **kwargs
144
- )
145
-
146
- try:
147
- function(prediction_job, *args, **kwargs)
148
-
149
- pids_successful.append(prediction_job["id"])
150
- successful = True
151
-
152
- self._handle_successful_iteration(prediction_job)
153
-
154
- except Exception as exception:
155
- pids_unsuccessful.append(prediction_job["id"])
156
- pids_unsuccessful_dict[str(exception)].append(prediction_job["id"])
157
- last_job_exception = exception
158
-
159
- self._handle_exception_during_iteration(prediction_job, exception)
160
-
161
- if self.stop_on_exception:
162
- break
163
- finally:
164
- self._handle_finished_last_iteration(prediction_job, successful)
165
-
166
- self.context.logger = self.context.logger.unbind("prediction_id")
167
-
168
- jobs_successful = len(pids_successful)
169
- jobs_unsuccessful = len(pids_unsuccessful)
170
- jobs_started = jobs_successful + jobs_unsuccessful
171
-
172
- # This log is for human readable logging
173
- self.context.perf_meter.checkpoint(
174
- "loop",
175
- num_jobs=num_jobs,
176
- jobs_started=jobs_started,
177
- jobs_successful=jobs_successful,
178
- jobs_unsuccessful=jobs_unsuccessful,
179
- successful=int(jobs_unsuccessful > 0),
180
- )
181
-
182
- if jobs_unsuccessful > 0:
183
- metrics = {
184
- "num_jobs": num_jobs,
185
- "pids_successful": pids_successful,
186
- "pids_unsuccessful": pids_unsuccessful,
187
- "exceptions": pids_unsuccessful_dict,
188
- "jobs_successful": jobs_successful,
189
- "jobs_unsuccessful": jobs_unsuccessful,
190
- "jobs_started": jobs_started,
191
- }
192
-
193
- raise PredictionJobException(metrics) from last_job_exception
194
-
195
- def _handle_successful_iteration(self, prediction_job):
196
- if self.on_successful_callback is not None:
197
- try:
198
- self.on_successful_callback(prediction_job)
199
- except Exception:
200
- _, exc_info, stack_info = sys.exc_info()
201
- self.context.logger.error(
202
- "An exception occured when executing the on_successful_callback "
203
- " callback function for this iteration",
204
- exc_info=exc_info,
205
- stack_info=stack_info,
206
- )
207
-
208
- def _handle_exception_during_iteration(self, prediction_job, e):
209
- _, exc_info, stack_info = sys.exc_info()
210
- self.context.logger.error(
211
- "An exception occured during this iteration",
212
- exc_info=exc_info,
213
- stack_info=stack_info,
214
- )
215
-
216
- if self.on_exception_callback is None:
217
- return
218
-
219
- try:
220
- self.on_exception_callback(prediction_job, e)
221
- except Exception:
222
- _, exc_info, stack_info = sys.exc_info()
223
- self.context.logger.error(
224
- "An exception occured when executing the on_exception_callback "
225
- "callback function for this iteration",
226
- exc_info=exc_info,
227
- stack_info=stack_info,
228
- )
229
-
230
- def _handle_finished_last_iteration(self, prediction_job, successful):
231
- self.context.perf_meter.complete_level(successful)
232
-
233
- if self.on_end_callback is not None:
234
- try:
235
- self.on_end_callback(prediction_job, successful)
236
- except Exception:
237
- _, exc_info, stack_info = sys.exc_info()
238
- self.context.logger.error(
239
- "An exception occured when executing the on_end_callback callback "
240
- " function for this iteration",
241
- exc_info=exc_info,
242
- stack_info=stack_info,
243
- )
@@ -1,160 +0,0 @@
1
- # SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com> # noqa E501>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0
4
- import logging
5
- import traceback
6
- from typing import Callable
7
-
8
- import structlog
9
-
10
- from openstef.exceptions import PredictionJobException
11
- from openstef.monitoring.performance_meter import PerformanceMeter
12
- from openstef.monitoring.teams import post_teams
13
- from openstef.settings import Settings
14
-
15
-
16
- class TaskContext:
17
- """A context manager that can be used to run tasks with.
18
-
19
- Should be used as:
20
-
21
- .. code-block:: py
22
-
23
- with TaskContext("my_task_name") as context:
24
- pass
25
-
26
- Args:
27
- name: Name of the task
28
- config: Configuration object, can be found in openSTEF-dbc
29
- database: Database object, can be found in openSTEF-dbc
30
- suppress_exceptions: If set to False the context
31
- manager will pass any raised exception on. Defaults to False.
32
- post_teams_on_exception: If set to True the context
33
- manager will automatically post a message to teams when an
34
- exception is encountered. Defaults to True.
35
- on_exception : Callback, will be called
36
- when an exception is raised. Callable gets exc_type, exc_info,
37
- stack_info as arguments.
38
- on_successful: Callback, will be called
39
- everytime if the task is successful (no exception is raised).
40
- on_end: Callback, will be called if the task is
41
- completed. Callable gets a bool indicating success as argument.
42
-
43
- """
44
-
45
- def __init__(
46
- self,
47
- name: str,
48
- config: object,
49
- database: object,
50
- suppress_exceptions: bool = False,
51
- post_teams_on_exception: bool = True,
52
- on_exception: Callable = None,
53
- on_successful: Callable = None,
54
- on_end: Callable = None,
55
- ):
56
- """Initialize context manager."""
57
- self.name = name
58
- self.suppress_exceptions = suppress_exceptions
59
- self.post_teams_on_exception = post_teams_on_exception
60
- self.on_exception = on_exception
61
- self.on_successful = on_successful
62
- self.on_end = on_end
63
- self.config = config
64
- self.database = database
65
-
66
- def __enter__(self):
67
- structlog.configure(
68
- wrapper_class=structlog.make_filtering_bound_logger(
69
- logging.getLevelName(Settings.log_level)
70
- )
71
- )
72
- self.logger = structlog.get_logger(__name__).bind(task=self.name)
73
-
74
- self.perf_meter = PerformanceMeter(self.logger)
75
-
76
- self.perf_meter.start_level("task", self.name)
77
-
78
- return self
79
-
80
- def __exit__(self, exc_type: type, exc_info: str, stack_info: str) -> bool:
81
- self.successful = exc_type is None
82
-
83
- if self.successful:
84
- if self.on_successful is not None:
85
- self.on_successful()
86
- else:
87
- self.logger.error(
88
- "An error has occured",
89
- exc_info=exc_info,
90
- stack_info=stack_info,
91
- )
92
- if self.on_exception is not None:
93
- self.on_exception(exc_type, exc_info, stack_info)
94
-
95
- if self.post_teams_on_exception:
96
- self._send_teams_message(exc_type, exc_info, stack_info)
97
-
98
- if self.on_end is not None:
99
- self.on_end(self.successful)
100
-
101
- self.perf_meter.complete_level(self.successful)
102
-
103
- # Returning true stops the propagation of the exception
104
- return self.suppress_exceptions
105
-
106
- def _send_teams_message(
107
- self, exc_type: type, exc_info: str, stack_info: str
108
- ) -> None:
109
- stack_text = "".join(traceback.format_exception(exc_type, exc_info, stack_info))
110
- # The teams webhook behaves weird. Using the correct order \r\n does NOT work
111
- # The 4 spaces forces teams to format a monospaced message for some reason
112
- stack_text = stack_text.replace("\n", "\n\r ")
113
- msg = {
114
- "title": f"Task '{self.name}' raised an exception",
115
- "color": "#a54f4f",
116
- "sections": [],
117
- }
118
- if exc_type is PredictionJobException:
119
- metrics = exc_info.metrics
120
- msg["sections"].append(
121
- {
122
- "facts": [
123
- ("Number of pjs in this task", metrics["num_jobs"]),
124
- ("Number of pjs started", metrics["jobs_started"]),
125
- ("Number of pjs successful", metrics["jobs_successful"]),
126
- ("Number of pjs unsuccessful", metrics["jobs_unsuccessful"]),
127
- ],
128
- }
129
- )
130
- string_pids_unsuccessful = ", ".join(
131
- [f"{pid:d}" for pid in metrics["pids_unsuccessful"]]
132
- )
133
- msg["sections"].append(
134
- {
135
- "facts": [
136
- ("Unsuccessful pid(s)", string_pids_unsuccessful),
137
- ]
138
- }
139
- )
140
- # Add details of exceptions and pids
141
- string_pids_exceptions = "\n".join(
142
- [f"{key}:{value}\n" for key, value in metrics["exceptions"].items()]
143
- )
144
- msg["sections"].append(
145
- {
146
- "facts": [
147
- ("Exceptions: pid(s)", string_pids_exceptions),
148
- ]
149
- }
150
- )
151
-
152
- msg["sections"].append(
153
- {
154
- "text": f" {stack_text}",
155
- }
156
- )
157
-
158
- post_teams(
159
- msg, url=self.config.teams_monitoring_url, proxies=self.config.proxies
160
- )
@@ -1,3 +0,0 @@
1
- # SPDX-FileCopyrightText: 2017-2023 Contributors to the OpenSTEF project <korte.termijn.prognoses@alliander.com> # noqa E501>
2
- #
3
- # SPDX-License-Identifier: MPL-2.0