openstef-models 4.0.0.dev1__tar.gz → 4.1.0__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.
Files changed (176) hide show
  1. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/.gitignore +26 -6
  2. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/PKG-INFO +11 -7
  3. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/README.md +2 -2
  4. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/pyproject.toml +22 -14
  5. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/__init__.py +1 -1
  6. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/explainability/__init__.py +5 -3
  7. openstef_models-4.1.0/src/openstef_models/explainability/mixins.py +126 -0
  8. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/explainability/plotters/__init__.py +3 -1
  9. openstef_models-4.1.0/src/openstef_models/explainability/plotters/contributions_plotter.py +228 -0
  10. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/explainability/plotters/feature_importance_plotter.py +1 -1
  11. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/integrations/__init__.py +3 -1
  12. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/integrations/joblib/__init__.py +1 -1
  13. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/integrations/joblib/joblib_model_serializer.py +4 -4
  14. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/integrations/mlflow/__init__.py +8 -3
  15. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/integrations/mlflow/mlflow_storage.py +118 -14
  16. openstef_models-4.1.0/src/openstef_models/integrations/mlflow/mlflow_storage_callback.py +383 -0
  17. openstef_models-4.1.0/src/openstef_models/integrations/optuna/__init__.py +23 -0
  18. openstef_models-4.1.0/src/openstef_models/integrations/optuna/tuner.py +355 -0
  19. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/mixins/__init__.py +1 -1
  20. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/mixins/callbacks.py +1 -1
  21. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/mixins/model_serializer.py +1 -1
  22. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/__init__.py +3 -2
  23. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting/__init__.py +1 -1
  24. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting/component_splitter.py +2 -1
  25. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting/constant_component_splitter.py +5 -4
  26. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting/linear_component_splitter.py +8 -14
  27. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting/linear_component_splitter_model/linear_component_splitter_model.z.license +1 -1
  28. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting_model.py +2 -2
  29. openstef_models-4.1.0/src/openstef_models/models/forecasting/__init__.py +9 -0
  30. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/forecasting/base_case_forecaster.py +47 -69
  31. openstef_models-4.0.0.dev1/src/openstef_models/models/forecasting/constant_median_forecaster.py → openstef_models-4.1.0/src/openstef_models/models/forecasting/constant_quantile_forecaster.py +47 -63
  32. openstef_models-4.1.0/src/openstef_models/models/forecasting/flatliner_forecaster.py +111 -0
  33. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/forecasting/forecaster.py +40 -104
  34. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/forecasting/gblinear_forecaster.py +112 -101
  35. openstef_models-4.1.0/src/openstef_models/models/forecasting/lgbm_forecaster.py +344 -0
  36. openstef_models-4.1.0/src/openstef_models/models/forecasting/lgbmlinear_forecaster.py +345 -0
  37. openstef_models-4.1.0/src/openstef_models/models/forecasting/median_forecaster.py +320 -0
  38. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/forecasting/xgboost_forecaster.py +132 -139
  39. openstef_models-4.1.0/src/openstef_models/models/forecasting_model.py +678 -0
  40. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/presets/__init__.py +6 -2
  41. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/presets/forecasting_workflow.py +283 -77
  42. openstef_models-4.1.0/src/openstef_models/testing.py +98 -0
  43. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/__init__.py +1 -1
  44. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/energy_domain/__init__.py +1 -1
  45. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/energy_domain/wind_power_feature_adder.py +15 -15
  46. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/__init__.py +12 -4
  47. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/dimensionality_reducer.py +4 -3
  48. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/empty_feature_remover.py +3 -3
  49. openstef_models-4.1.0/src/openstef_models/transforms/general/flagger.py +97 -0
  50. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/imputer.py +62 -60
  51. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/nan_dropper.py +3 -3
  52. openstef_models-4.1.0/src/openstef_models/transforms/general/outlier_handler.py +178 -0
  53. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/sample_weighter.py +134 -33
  54. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/general/scaler.py +3 -2
  55. openstef_models-4.1.0/src/openstef_models/transforms/general/selector.py +83 -0
  56. openstef_models-4.1.0/src/openstef_models/transforms/general/shifter.py +130 -0
  57. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/postprocessing/__init__.py +3 -2
  58. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/postprocessing/confidence_interval_applicator.py +35 -21
  59. openstef_models-4.1.0/src/openstef_models/transforms/postprocessing/isotonic_quantile_calibrator.py +229 -0
  60. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/postprocessing/quantile_sorter.py +2 -2
  61. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/time_domain/__init__.py +5 -1
  62. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/time_domain/cyclic_features_adder.py +3 -2
  63. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/time_domain/datetime_features_adder.py +17 -10
  64. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/time_domain/holiday_features_adder.py +35 -12
  65. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/time_domain/lags_adder.py +109 -39
  66. openstef_models-4.1.0/src/openstef_models/transforms/time_domain/rolling_aggregates_adder.py +166 -0
  67. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/time_domain/versioned_lags_adder.py +12 -6
  68. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/validation/__init__.py +1 -1
  69. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/validation/completeness_checker.py +19 -19
  70. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/validation/flatline_checker.py +28 -25
  71. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/validation/input_consistency_checker.py +1 -1
  72. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/weather_domain/__init__.py +1 -1
  73. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/weather_domain/atmosphere_derived_features_adder.py +2 -2
  74. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/weather_domain/daylight_feature_adder.py +2 -2
  75. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/transforms/weather_domain/radiation_derived_features_adder.py +17 -16
  76. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/utils/__init__.py +1 -1
  77. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/utils/data_split.py +12 -6
  78. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/utils/evaluation_functions.py +3 -3
  79. openstef_models-4.1.0/src/openstef_models/utils/feature_selection.py +214 -0
  80. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/utils/loss_functions.py +16 -14
  81. openstef_models-4.1.0/src/openstef_models/utils/multi_quantile_regressor.py +157 -0
  82. openstef_models-4.1.0/src/openstef_models/utils/xgboost.py +45 -0
  83. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/workflows/__init__.py +1 -1
  84. openstef_models-4.1.0/src/openstef_models/workflows/callbacks/__init__.py +13 -0
  85. openstef_models-4.1.0/src/openstef_models/workflows/callbacks/data_save.py +108 -0
  86. openstef_models-4.1.0/src/openstef_models/workflows/callbacks/model_performance_callback.py +92 -0
  87. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/workflows/custom_component_split_workflow.py +4 -4
  88. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/workflows/custom_forecasting_workflow.py +88 -17
  89. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/__init__.py +1 -1
  90. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/integration/test_integration.py +1 -1
  91. openstef_models-4.1.0/tests/unit/explainability/plotters/test_contributions_plotter.py +219 -0
  92. {openstef_models-4.0.0.dev1/tests/unit/integrations/joblib → openstef_models-4.1.0/tests/unit/integrations}/__init__.py +1 -1
  93. {openstef_models-4.0.0.dev1/tests/unit/integrations → openstef_models-4.1.0/tests/unit/integrations/joblib}/__init__.py +1 -1
  94. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/integrations/joblib/test_joblib_model_serializer.py +1 -1
  95. {openstef_models-4.0.0.dev1/tests/unit/models/component_splitting → openstef_models-4.1.0/tests/unit/integrations/mlflow}/__init__.py +1 -1
  96. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/integrations/mlflow/test_mlflow_storage.py +76 -11
  97. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/integrations/mlflow/test_mlflow_storage_callback.py +53 -19
  98. openstef_models-4.1.0/tests/unit/integrations/optuna/test_tuner.py +306 -0
  99. {openstef_models-4.0.0.dev1/tests/unit/utils → openstef_models-4.1.0/tests/unit/models/component_splitting}/__init__.py +1 -1
  100. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/models/component_splitting/test_constant_component_splitter.py +1 -1
  101. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/models/component_splitting/test_linear_component_splitter.py +7 -7
  102. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/models/forecasting/conftest.py +1 -1
  103. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/models/forecasting/test_base_case_forecaster.py +41 -29
  104. openstef_models-4.1.0/tests/unit/models/forecasting/test_constant_quantile_forecaster.py +135 -0
  105. openstef_models-4.1.0/tests/unit/models/forecasting/test_flatliner_forecaster.py +66 -0
  106. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/models/forecasting/test_gblinear_forecaster.py +39 -14
  107. openstef_models-4.1.0/tests/unit/models/forecasting/test_lgbm_forecaster.py +173 -0
  108. openstef_models-4.1.0/tests/unit/models/forecasting/test_lgbmlinear_forecaster.py +147 -0
  109. openstef_models-4.1.0/tests/unit/models/forecasting/test_median_forecaster.py +460 -0
  110. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/models/forecasting/test_xgboost_forecaster.py +41 -16
  111. openstef_models-4.1.0/tests/unit/models/test_forecasting_model.py +460 -0
  112. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/test_example.py +1 -1
  113. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/energy_domain/test_wind_power_feature_adder.py +1 -1
  114. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/general/test_dimensionality_reducer.py +1 -1
  115. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/general/test_empty_feature_remover.py +1 -1
  116. openstef_models-4.1.0/tests/unit/transforms/general/test_flagger.py +61 -0
  117. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/general/test_imputer.py +2 -2
  118. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/general/test_nan_dropper.py +1 -1
  119. openstef_models-4.1.0/tests/unit/transforms/general/test_outlier_handler.py +235 -0
  120. openstef_models-4.1.0/tests/unit/transforms/general/test_sample_weighter.py +280 -0
  121. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/general/test_scaler.py +2 -2
  122. openstef_models-4.1.0/tests/unit/transforms/general/test_selector.py +82 -0
  123. openstef_models-4.1.0/tests/unit/transforms/general/test_shifter.py +174 -0
  124. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/postprocessing/__init__.py +1 -1
  125. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/postprocessing/test_confidence_interval_applicator.py +43 -1
  126. openstef_models-4.1.0/tests/unit/transforms/postprocessing/test_isotonic_quantile_calibrator.py +200 -0
  127. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/postprocessing/test_quantile_sorter.py +1 -1
  128. openstef_models-4.1.0/tests/unit/transforms/time_domain/__init__.py +0 -0
  129. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/time_domain/test_cyclic_features_adder.py +1 -1
  130. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/time_domain/test_datetime_features_adder.py +30 -1
  131. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/time_domain/test_holiday_features_adder.py +36 -1
  132. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/time_domain/test_lags_adder.py +186 -15
  133. openstef_models-4.1.0/tests/unit/transforms/time_domain/test_rolling_aggregates_adder.py +284 -0
  134. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/time_domain/test_versioned_lags_adder.py +54 -44
  135. openstef_models-4.1.0/tests/unit/transforms/validation/__init__.py +0 -0
  136. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/validation/test_completeness_checker.py +1 -1
  137. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/validation/test_flatline_checker.py +20 -1
  138. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/validation/test_input_consistency_checker.py +1 -1
  139. openstef_models-4.1.0/tests/unit/transforms/weather_domain/__init__.py +0 -0
  140. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/weather_domain/test_atmosphere_derived_features_adder.py +1 -1
  141. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/weather_domain/test_daylight_feature_adder.py +1 -1
  142. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/transforms/weather_domain/test_radiation_derived_featuers_adder.py +8 -31
  143. {openstef_models-4.0.0.dev1/tests/unit/integrations/mlflow → openstef_models-4.1.0/tests/unit/utils}/__init__.py +1 -1
  144. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/utils/test_data_split.py +2 -2
  145. openstef_models-4.1.0/tests/unit/utils/test_feature_selection.py +125 -0
  146. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/utils/test_loss_functions.py +69 -6
  147. openstef_models-4.1.0/tests/unit/utils/test_multi_quantile_regressor.py +118 -0
  148. openstef_models-4.1.0/tests/unit/workflows/__init__.py +0 -0
  149. openstef_models-4.1.0/tests/unit/workflows/callbacks/__init__.py +0 -0
  150. openstef_models-4.1.0/tests/unit/workflows/callbacks/test_model_performance_callback.py +89 -0
  151. openstef_models-4.1.0/tests/unit/workflows/test_custom_forecasting_workflow.py +134 -0
  152. openstef_models-4.0.0.dev1/src/openstef_models/explainability/mixins.py +0 -58
  153. openstef_models-4.0.0.dev1/src/openstef_models/integrations/mlflow/mlflow_storage_callback.py +0 -239
  154. openstef_models-4.0.0.dev1/src/openstef_models/models/forecasting/__init__.py +0 -26
  155. openstef_models-4.0.0.dev1/src/openstef_models/models/forecasting/flatliner_forecaster.py +0 -104
  156. openstef_models-4.0.0.dev1/src/openstef_models/models/forecasting_model.py +0 -389
  157. openstef_models-4.0.0.dev1/src/openstef_models/transforms/general/clipper.py +0 -121
  158. openstef_models-4.0.0.dev1/src/openstef_models/transforms/time_domain/rolling_aggregates_adder.py +0 -126
  159. openstef_models-4.0.0.dev1/src/openstef_models/utils/feature_selection.py +0 -100
  160. openstef_models-4.0.0.dev1/tests/unit/models/forecasting/test_constant_median_forecaster.py +0 -92
  161. openstef_models-4.0.0.dev1/tests/unit/models/forecasting/test_flatliner_forecaster.py +0 -32
  162. openstef_models-4.0.0.dev1/tests/unit/models/test_forecasting_model.py +0 -241
  163. openstef_models-4.0.0.dev1/tests/unit/transforms/general/test_clipper.py +0 -116
  164. openstef_models-4.0.0.dev1/tests/unit/transforms/general/test_sample_weighter.py +0 -97
  165. openstef_models-4.0.0.dev1/tests/unit/transforms/time_domain/test_rolling_aggregates_adder.py +0 -126
  166. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/src/openstef_models/models/component_splitting/linear_component_splitter_model/linear_component_splitter_model.z +0 -0
  167. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/integration/__init__.py +0 -0
  168. {openstef_models-4.0.0.dev1 → openstef_models-4.1.0}/tests/unit/__init__.py +0 -0
  169. {openstef_models-4.0.0.dev1/tests/unit/models → openstef_models-4.1.0/tests/unit/explainability}/__init__.py +0 -0
  170. {openstef_models-4.0.0.dev1/tests/unit/models/forecasting → openstef_models-4.1.0/tests/unit/explainability/plotters}/__init__.py +0 -0
  171. {openstef_models-4.0.0.dev1/tests/unit/transforms → openstef_models-4.1.0/tests/unit/integrations/optuna}/__init__.py +0 -0
  172. {openstef_models-4.0.0.dev1/tests/unit/transforms/energy_domain → openstef_models-4.1.0/tests/unit/models}/__init__.py +0 -0
  173. {openstef_models-4.0.0.dev1/tests/unit/transforms/general → openstef_models-4.1.0/tests/unit/models/forecasting}/__init__.py +0 -0
  174. {openstef_models-4.0.0.dev1/tests/unit/transforms/time_domain → openstef_models-4.1.0/tests/unit/transforms}/__init__.py +0 -0
  175. {openstef_models-4.0.0.dev1/tests/unit/transforms/validation → openstef_models-4.1.0/tests/unit/transforms/energy_domain}/__init__.py +0 -0
  176. {openstef_models-4.0.0.dev1/tests/unit/transforms/weather_domain → openstef_models-4.1.0/tests/unit/transforms/general}/__init__.py +0 -0
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2017-2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com> # noqa E501>
1
+ # SPDX-FileCopyrightText: 2017-2025 Contributors to the OpenSTEF project <openstef@lfenergy.org> # noqa E501>
2
2
  # SPDX-License-Identifier: MPL-2.0
3
3
 
4
4
  # Core
@@ -35,10 +35,6 @@ MANIFEST
35
35
  # Ruff
36
36
  .ruff_cache/
37
37
 
38
- # Pyright
39
- .pyright/
40
- # pyright-report/
41
-
42
38
  # Test, coverage, tox
43
39
  .pytest_cache/
44
40
  .coverage
@@ -67,6 +63,14 @@ dmypy.json
67
63
  # Sphinx
68
64
  docs/_build/
69
65
  docs/source/api/generated/
66
+ docs/source/tutorials/
67
+ docs/source/benchmarks/
68
+ # Community health files materialized from OpenSTEF/.github at build time
69
+ docs/source/contribute/_community/
70
+ docs/source/user_guide/**/quick_start_tutorial.py
71
+ docs/source/user_guide/**/feature_engineering_tutorial.py
72
+ docs/source/user_guide/**/datasets_tutorial.py
73
+ docs/source/user_guide/**/backtesting_tutorial.py
70
74
 
71
75
  # docs/_doctrees/
72
76
  # docs/_static_gen/
@@ -124,4 +128,20 @@ certificates/
124
128
  *.pkl
125
129
 
126
130
  # Benchmark outputs
127
- benchmark_results*/
131
+ benchmark_results*/
132
+
133
+ # Local dataset files
134
+ liander_dataset/
135
+
136
+ # Deployment example run artifacts (MLflow store, forecasts, dataset, Celery/Airflow state)
137
+ openstef_deployment_runs/
138
+
139
+ # Mlflow
140
+ /mlflow
141
+ /mlflow_artifacts_local
142
+
143
+ .github/instructions
144
+
145
+ # Jupyter notebook cache (myst-nb execution outputs)
146
+ .jupyter_cache/
147
+ docs/build.zip
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openstef-models
3
- Version: 4.0.0.dev1
3
+ Version: 4.1.0
4
4
  Summary: Core models for OpenSTEF
5
5
  Project-URL: Documentation, https://openstef.github.io/openstef/index.html
6
6
  Project-URL: Homepage, https://lfenergy.org/projects/openstef/
7
7
  Project-URL: Issues, https://github.com/OpenSTEF/openstef/issues
8
8
  Project-URL: Repository, https://github.com/OpenSTEF/openstef
9
- Author-email: "Alliander N.V" <short.term.energy.forecasts@alliander.com>
9
+ Author-email: "Alliander N.V" <openstef@lfenergy.org>
10
10
  License-Expression: MPL-2.0
11
11
  Keywords: energy,forecasting,machinelearning
12
12
  Classifier: Development Status :: 5 - Production/Stable
@@ -18,12 +18,16 @@ Classifier: Programming Language :: Python :: 3.14
18
18
  Requires-Python: <4.0,>=3.12
19
19
  Requires-Dist: holidays>=0.79
20
20
  Requires-Dist: mlflow-skinny<4,>=3
21
- Requires-Dist: openstef-beam<5,>=4.0.0.dev0
22
- Requires-Dist: openstef-core<5,>=4.0.0.dev0
21
+ Requires-Dist: openstef-beam<5,>=4
22
+ Requires-Dist: openstef-core<5,>=4
23
23
  Requires-Dist: pvlib>=0.13
24
24
  Requires-Dist: pycountry>=24.6.1
25
- Requires-Dist: scikit-learn<2,>=1.7.1
25
+ Requires-Dist: scikit-learn<1.8,>=1.7.1
26
26
  Requires-Dist: scipy<2,>=1.16.3
27
+ Provides-Extra: lgbm
28
+ Requires-Dist: lightgbm>=4.6; extra == 'lgbm'
29
+ Provides-Extra: tuning
30
+ Requires-Dist: optuna>=4.7; extra == 'tuning'
27
31
  Provides-Extra: xgb-cpu
28
32
  Requires-Dist: xgboost-cpu<4,>=3; (sys_platform == 'linux' or sys_platform == 'win32') and extra == 'xgb-cpu'
29
33
  Requires-Dist: xgboost<4,>=3; (sys_platform == 'darwin') and extra == 'xgb-cpu'
@@ -32,9 +36,9 @@ Requires-Dist: xgboost<4,>=3; extra == 'xgb-gpu'
32
36
  Description-Content-Type: text/markdown
33
37
 
34
38
  <!--
35
- SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
39
+ SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
36
40
 
37
41
  SPDX-License-Identifier: MPL-2.0
38
42
  -->
39
43
 
40
- # openstef-model
44
+ # openstef-model
@@ -1,7 +1,7 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
2
+ SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
3
3
 
4
4
  SPDX-License-Identifier: MPL-2.0
5
5
  -->
6
6
 
7
- # openstef-model
7
+ # openstef-model
@@ -1,21 +1,19 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
-
5
4
  [build-system]
6
5
  build-backend = "hatchling.build"
7
-
8
6
  requires = [ "hatchling" ]
9
7
 
10
8
  [project]
11
9
  name = "openstef-models"
12
- version = "4.0.0.dev1"
10
+ version = "4.1.0"
13
11
  description = "Core models for OpenSTEF"
14
12
  readme = "README.md"
15
13
  keywords = [ "energy", "forecasting", "machinelearning" ]
16
14
  license = "MPL-2.0"
17
15
  authors = [
18
- { name = "Alliander N.V", email = "short.term.energy.forecasts@alliander.com" },
16
+ { name = "Alliander N.V", email = "openstef@lfenergy.org" },
19
17
  ]
20
18
  requires-python = ">=3.12,<4.0"
21
19
  classifiers = [
@@ -26,29 +24,39 @@ classifiers = [
26
24
  "Programming Language :: Python :: 3.13",
27
25
  "Programming Language :: Python :: 3.14",
28
26
  ]
29
-
30
27
  dependencies = [
31
28
  "holidays>=0.79",
32
29
  "mlflow-skinny>=3,<4",
33
- "openstef-beam>=4.0.0.dev0,<5",
34
- "openstef-core>=4.0.0.dev0,<5",
30
+ "openstef-beam>=4,<5",
31
+ "openstef-core>=4,<5",
35
32
  "pvlib>=0.13",
36
33
  "pycountry>=24.6.1",
37
- "scikit-learn>=1.7.1,<2",
34
+ "scikit-learn>=1.7.1,<1.8",
38
35
  "scipy>=1.16.3,<2",
39
36
  ]
40
-
37
+ optional-dependencies.lgbm = [
38
+ "lightgbm>=4.6",
39
+ ]
40
+ optional-dependencies.tuning = [ "optuna>=4.7" ]
41
41
  optional-dependencies.xgb-cpu = [
42
42
  "xgboost>=3,<4; sys_platform=='darwin'",
43
43
  "xgboost-cpu>=3,<4; sys_platform=='linux' or sys_platform=='win32'",
44
44
  ]
45
-
46
45
  optional-dependencies.xgb-gpu = [ "xgboost>=3,<4" ]
47
-
48
46
  urls.Documentation = "https://openstef.github.io/openstef/index.html"
49
47
  urls.Homepage = "https://lfenergy.org/projects/openstef/"
50
48
  urls.Issues = "https://github.com/OpenSTEF/openstef/issues"
51
49
  urls.Repository = "https://github.com/OpenSTEF/openstef"
52
50
 
53
- [tool.hatch.build.targets.wheel]
54
- packages = [ "src/openstef_models" ]
51
+ [tool.hatch]
52
+ build.targets.wheel.packages = [ "src/openstef_models" ]
53
+
54
+ [tool.uv]
55
+ # xgb-cpu installs xgboost-cpu (Linux/Windows) and xgb-gpu installs the full
56
+ # xgboost; both provide the same import, so exactly one may be installed.
57
+ conflicts = [
58
+ [
59
+ { extra = "xgb-cpu" },
60
+ { extra = "xgb-gpu" },
61
+ ],
62
+ ]
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2017-2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2017-2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
  """Core models for OpenSTEF."""
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
 
@@ -7,10 +7,12 @@
7
7
  Tools for feature importance, attribution and model interpretation.
8
8
  """
9
9
 
10
- from .mixins import ExplainableForecaster
11
- from .plotters import FeatureImportancePlotter
10
+ from .mixins import ContributionsMixin, ExplainableForecaster
11
+ from .plotters import ContributionsPlotter, FeatureImportancePlotter
12
12
 
13
13
  __all__ = [
14
+ "ContributionsMixin",
15
+ "ContributionsPlotter",
14
16
  "ExplainableForecaster",
15
17
  "FeatureImportancePlotter",
16
18
  ]
@@ -0,0 +1,126 @@
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+
5
+ """Mixins for adding explainability features to forecasting models.
6
+
7
+ Provides base classes that enable models to expose feature importance scores
8
+ and generate visualization plots.
9
+ """
10
+
11
+ from abc import ABC, abstractmethod
12
+ from typing import Any, Literal
13
+
14
+ import pandas as pd
15
+ import plotly.graph_objects as go
16
+
17
+ from openstef_core.datasets import ForecastInputDataset, TimeSeriesDataset
18
+ from openstef_core.types import Q, Quantile
19
+ from openstef_models.explainability.plotters.contributions_plotter import ContributionsPlotter
20
+ from openstef_models.explainability.plotters.feature_importance_plotter import FeatureImportancePlotter
21
+
22
+
23
+ class ExplainableForecaster(ABC):
24
+ """Mixin for forecasters that can explain feature importance.
25
+
26
+ Provides a standardized interface for accessing and visualizing feature
27
+ importance scores across different forecasting models.
28
+ """
29
+
30
+ @property
31
+ @abstractmethod
32
+ def feature_importances(self) -> pd.DataFrame:
33
+ """Get feature importance scores for this model.
34
+
35
+ Returns DataFrame with feature names as index and quantiles as columns.
36
+ Each quantile represents the importance distribution across multiple
37
+ model training runs or folds.
38
+
39
+ Returns:
40
+ DataFrame with feature names as index and quantile columns.
41
+ Values represent normalized importance scores summing to 1.0.
42
+
43
+ Note:
44
+ The returned DataFrame must have feature names as index and quantile
45
+ columns in format 'quantile_PXX' (e.g., 'quantile_P50', 'quantile_P95').
46
+ All quantile values must be between 0 and 1.
47
+ """
48
+ raise NotImplementedError
49
+
50
+ def plot_feature_importances(self, quantile: Quantile = Q(0.5)) -> go.Figure:
51
+ """Create interactive treemap visualization of feature importances.
52
+
53
+ Args:
54
+ quantile: Which quantile of importance scores to display.
55
+ Defaults to median (0.5).
56
+
57
+ Returns:
58
+ Plotly Figure containing treemap with feature importance scores.
59
+ Color intensity indicates relative importance of each feature.
60
+ """
61
+ return FeatureImportancePlotter().plot(scores=self.feature_importances, quantile=quantile)
62
+
63
+
64
+ class ContributionsMixin(ABC):
65
+ """Mixin for forecasters that can explain per-sample feature contributions.
66
+
67
+ Unlike ``ExplainableForecaster`` which provides aggregate feature importance,
68
+ this mixin provides per-sample decomposition of predictions — i.e., how
69
+ much each feature contributed to the prediction for each individual sample.
70
+
71
+ For tree-based models (XGBoost), this corresponds to SHAP TreeExplainer values.
72
+ For linear models (GBLinear), this is the coefficient x feature value decomposition.
73
+ For ensembles, this shows each base model's contribution weight.
74
+ """
75
+
76
+ @abstractmethod
77
+ def predict_contributions(self, data: ForecastInputDataset) -> TimeSeriesDataset:
78
+ """Compute per-sample feature contributions for the given input data.
79
+
80
+ Returns a TimeSeriesDataset where columns are feature names (or model
81
+ names for ensemble contributions) and rows correspond to the same time
82
+ index as the input. Values represent the additive contribution of each
83
+ feature to the prediction at that timestep.
84
+
85
+ Args:
86
+ data: Preprocessed input data (same format as ``predict()`` takes).
87
+
88
+ Returns:
89
+ TimeSeriesDataset with feature contributions. Columns are features,
90
+ rows are timesteps. A ``bias`` column may be included for the
91
+ model intercept/base value.
92
+ """
93
+
94
+ def plot_contributions(
95
+ self,
96
+ data: ForecastInputDataset,
97
+ kind: Literal["heatmap", "waterfall", "bar"] = "heatmap",
98
+ **kwargs: Any,
99
+ ) -> go.Figure:
100
+ """Plot per-sample feature contributions.
101
+
102
+ Calls ``predict_contributions()`` and visualizes the result using the
103
+ requested chart type.
104
+
105
+ Args:
106
+ data: Preprocessed input data.
107
+ kind: Chart type — ``"heatmap"``, ``"waterfall"``, or ``"bar"``.
108
+ **kwargs: Forwarded to the corresponding plotter method
109
+ (e.g. ``top_n``, ``timestep``).
110
+
111
+ Returns:
112
+ Plotly Figure.
113
+
114
+ Raises:
115
+ ValueError: If *kind* is not one of the supported chart types.
116
+ """
117
+ contributions = self.predict_contributions(data)
118
+ plotters = {
119
+ "heatmap": ContributionsPlotter.plot_heatmap,
120
+ "waterfall": ContributionsPlotter.plot_waterfall,
121
+ "bar": ContributionsPlotter.plot_bar,
122
+ }
123
+ if kind not in plotters:
124
+ msg = f"Unknown plot kind {kind!r}. Choose from {list(plotters)}"
125
+ raise ValueError(msg)
126
+ return plotters[kind](contributions=contributions, **kwargs)
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
 
@@ -8,8 +8,10 @@ Provides plotters for creating interactive visualizations of feature importance
8
8
  scores and other model explanation outputs.
9
9
  """
10
10
 
11
+ from .contributions_plotter import ContributionsPlotter
11
12
  from .feature_importance_plotter import FeatureImportancePlotter
12
13
 
13
14
  __all__ = [
15
+ "ContributionsPlotter",
14
16
  "FeatureImportancePlotter",
15
17
  ]
@@ -0,0 +1,228 @@
1
+ # SPDX-FileCopyrightText: 2026 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
+ #
3
+ # SPDX-License-Identifier: MPL-2.0
4
+
5
+ """Visualizations for per-sample feature contributions (SHAP values)."""
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import TYPE_CHECKING
10
+
11
+ import plotly.graph_objects as go
12
+ from plotly.subplots import make_subplots
13
+
14
+ from openstef_core.datasets import TimeSeriesDataset # noqa: TC001
15
+
16
+ if TYPE_CHECKING:
17
+ import pandas as pd
18
+
19
+
20
+ class ContributionsPlotter:
21
+ """Visualizations for per-timestep feature contributions."""
22
+
23
+ @staticmethod
24
+ def plot_heatmap(
25
+ contributions: TimeSeriesDataset,
26
+ top_n: int = 10,
27
+ target_column: str = "load",
28
+ bias_column: str = "bias",
29
+ *,
30
+ show_prediction: bool = True,
31
+ ) -> go.Figure:
32
+ """Create an interactive heatmap of feature contributions over time.
33
+
34
+ X-axis is the prediction datetime, Y-axis shows feature names ranked by mean absolute contribution
35
+ (most important at top). Color ranges from blue (negative) through white (zero) to red (positive).
36
+ When ``show_prediction`` is True a line plot of the model prediction (sum of contributions + bias)
37
+ is shown above the heatmap.
38
+
39
+ Args:
40
+ contributions: Output of ``predict_contributions()``.
41
+ top_n: Number of top features to show (ranked by mean absolute contribution).
42
+ target_column: Name of the target column to exclude. Default "load".
43
+ bias_column: Name of the bias column. Default "bias".
44
+ show_prediction: If True, add a prediction line subplot above the heatmap. Default True.
45
+
46
+ Returns:
47
+ Plotly Figure with a diverging heatmap centered at zero (and optional prediction line).
48
+ """
49
+ bias = contributions.data[bias_column] if bias_column in contributions.data.columns else None
50
+ cols_to_drop = [c for c in [target_column, bias_column] if c in contributions.data.columns]
51
+ df = contributions.data.drop(columns=cols_to_drop)
52
+ ranked: list[str] = df.abs().mean().sort_values(ascending=False).head(top_n).index.tolist()
53
+
54
+ # Most-important feature at top of Y-axis
55
+ y_labels = list(reversed(ranked))
56
+
57
+ heatmap = go.Heatmap(
58
+ z=df[y_labels].T.values,
59
+ x=df.index,
60
+ y=y_labels,
61
+ colorscale="RdBu_r",
62
+ zmid=0,
63
+ colorbar={"title": "Contribution"},
64
+ showlegend=False,
65
+ )
66
+
67
+ if show_prediction:
68
+ prediction = df.sum(axis=1)
69
+ if bias is not None:
70
+ prediction += bias
71
+
72
+ fig = make_subplots(
73
+ rows=2,
74
+ cols=1,
75
+ shared_xaxes=True,
76
+ row_heights=[0.2, 0.8],
77
+ vertical_spacing=0.03,
78
+ )
79
+
80
+ fig.add_trace(
81
+ go.Scatter(
82
+ x=df.index,
83
+ y=prediction,
84
+ mode="lines",
85
+ name="Prediction",
86
+ line={"color": "black", "width": 1.5},
87
+ showlegend=False,
88
+ ),
89
+ row=1,
90
+ col=1,
91
+ )
92
+ fig.add_trace(heatmap, row=2, col=1)
93
+
94
+ fig.update_layout(
95
+ yaxis_title="Prediction",
96
+ yaxis2_title="Feature",
97
+ xaxis2_title="Time",
98
+ margin={"t": 30, "r": 10, "b": 40, "l": 120},
99
+ )
100
+ else:
101
+ fig = go.Figure(
102
+ data=heatmap,
103
+ layout={
104
+ "xaxis_title": "Time",
105
+ "yaxis_title": "Feature",
106
+ "margin": {"t": 30, "r": 10, "b": 40, "l": 120},
107
+ },
108
+ )
109
+
110
+ return fig
111
+
112
+ @staticmethod
113
+ def plot_waterfall(
114
+ contributions: TimeSeriesDataset,
115
+ timestep: int = 0,
116
+ top_n: int = 10,
117
+ target_column: str = "load",
118
+ bias_column: str = "bias",
119
+ ) -> go.Figure:
120
+ """Create a waterfall chart decomposing a single timestep's prediction.
121
+
122
+ Shows how the bias (base value) is pushed up or down by each feature's
123
+ contribution to arrive at the final prediction.
124
+
125
+ Args:
126
+ contributions: Output of ``predict_contributions()``.
127
+ timestep: Row index (0-based) of the timestep to explain.
128
+ top_n: Number of top features to show. Remaining features are
129
+ aggregated into an "other" bar.
130
+ target_column: Name of the target column to exclude. Default "load".
131
+ bias_column: Name of the bias column used as base value. Default "bias".
132
+
133
+ Returns:
134
+ Plotly Figure with waterfall chart.
135
+ """
136
+ bias = contributions.data[bias_column] if bias_column in contributions.data.columns else None
137
+ cols_to_drop = [c for c in [target_column, bias_column] if c in contributions.data.columns]
138
+ df = contributions.data.drop(columns=cols_to_drop)
139
+ row = df.iloc[timestep]
140
+ base_value = float(bias.iloc[timestep]) if bias is not None else 0.0
141
+
142
+ # Rank by |contribution| for this specific timestep
143
+ abs_sorted = row.abs().sort_values(ascending=False)
144
+ top = abs_sorted.head(top_n).index.tolist()
145
+ remaining = [c for c in abs_sorted.index if c not in top]
146
+
147
+ names: list[str] = [bias_column]
148
+ values: list[float] = [base_value]
149
+ measures: list[str] = ["absolute"]
150
+
151
+ for feat in top:
152
+ names.append(feat)
153
+ values.append(float(row[feat]))
154
+ measures.append("relative")
155
+
156
+ if len(remaining) > 0:
157
+ other_sum = float(row[remaining].sum())
158
+ names.append(f"other ({len(remaining)})")
159
+ values.append(other_sum)
160
+ measures.append("relative")
161
+
162
+ names.append("Prediction")
163
+ values.append(base_value + float(row.sum()))
164
+ measures.append("total")
165
+
166
+ timestamp = contributions.data.index[timestep]
167
+ return go.Figure(
168
+ go.Waterfall(
169
+ x=names,
170
+ y=values,
171
+ measure=measures,
172
+ connector={"line": {"color": "grey", "width": 0.5}},
173
+ increasing={"marker": {"color": "#ff4136"}},
174
+ decreasing={"marker": {"color": "#0074d9"}},
175
+ totals={"marker": {"color": "#2ecc40"}},
176
+ textposition="outside",
177
+ text=[f"{v:+.4f}" if m == "relative" else f"{v:.4f}" for v, m in zip(values, measures, strict=True)],
178
+ ),
179
+ layout={
180
+ "title": f"Contributions at {timestamp}",
181
+ "yaxis_title": "Contribution",
182
+ "margin": {"t": 50, "r": 10, "b": 40, "l": 60},
183
+ "showlegend": False,
184
+ },
185
+ )
186
+
187
+ @staticmethod
188
+ def plot_bar(
189
+ contributions: TimeSeriesDataset,
190
+ top_n: int = 10,
191
+ target_column: str = "load",
192
+ bias_column: str = "bias",
193
+ ) -> go.Figure:
194
+ """Create a horizontal bar chart of mean absolute contributions per feature.
195
+
196
+ Features are ranked from most to least important (top to bottom).
197
+
198
+ Args:
199
+ contributions: Output of ``predict_contributions()``.
200
+ top_n: Number of top features to show.
201
+ target_column: Name of the target column to exclude. Default "load".
202
+ bias_column: Name of the bias column to exclude. Default "bias".
203
+
204
+ Returns:
205
+ Plotly Figure with horizontal bar chart.
206
+ """
207
+ cols_to_drop = [c for c in [target_column, bias_column] if c in contributions.data.columns]
208
+ df = contributions.data.drop(columns=cols_to_drop)
209
+ mean_abs: pd.Series = df.abs().mean().sort_values(ascending=False).head(top_n)
210
+
211
+ # Reverse for plotly (bottom-to-top rendering)
212
+ mean_abs = mean_abs.iloc[::-1]
213
+
214
+ return go.Figure(
215
+ go.Bar(
216
+ x=mean_abs.values,
217
+ y=mean_abs.index.tolist(),
218
+ orientation="h",
219
+ marker_color="#1f77b4",
220
+ hovertemplate="<b>%{y}</b><br>mean |SHAP|: %{x:.4f}<extra></extra>",
221
+ ),
222
+ layout={
223
+ "xaxis_title": "mean |SHAP value|",
224
+ "yaxis_title": "Feature",
225
+ "margin": {"t": 30, "r": 10, "b": 40, "l": 120},
226
+ "showlegend": False,
227
+ },
228
+ )
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
 
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
 
@@ -8,3 +8,5 @@ Contains implementations for callbacks and storage systems that hook into and
8
8
  extend OpenSTEF functionality by integrating with external systems such as
9
9
  monitoring tools, databases, cloud storage, and custom processing pipelines.
10
10
  """
11
+
12
+ __all__ = ["joblib", "mlflow", "optuna"]
@@ -6,7 +6,7 @@ the local filesystem, making it suitable for development, testing, and
6
6
  single-machine deployments.
7
7
  """
8
8
 
9
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
9
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
10
10
  #
11
11
  # SPDX-License-Identifier: MPL-2.0
12
12
 
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
  """Local model storage implementation using joblib serialization.
@@ -45,7 +45,7 @@ class JoblibModelSerializer(ModelSerializer):
45
45
  - Load operations fail with ModelNotFoundError if model file doesn't exist
46
46
 
47
47
  Example:
48
- Basic usage with model persistence:
48
+ Basic usage with model persistence
49
49
 
50
50
  >>> from pathlib import Path
51
51
  >>> from openstef_models.models.forecasting_model import ForecastingModel
@@ -58,11 +58,11 @@ class JoblibModelSerializer(ModelSerializer):
58
58
 
59
59
  @override
60
60
  def serialize(self, model: object, file: BinaryIO) -> None:
61
- joblib.dump(model, file) # type: ignore[reportUnknownMemberType]
61
+ joblib.dump(model, file)
62
62
 
63
63
  @override
64
64
  def deserialize(self, file: BinaryIO) -> object:
65
- return joblib.load(file) # type: ignore[reportUnknownMemberType]
65
+ return joblib.load(file)
66
66
 
67
67
 
68
68
  __all__ = ["JoblibModelSerializer"]
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <short.term.energy.forecasts@alliander.com>
1
+ # SPDX-FileCopyrightText: 2025 Contributors to the OpenSTEF project <openstef@lfenergy.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MPL-2.0
4
4
 
@@ -16,6 +16,11 @@ Note:
16
16
  """
17
17
 
18
18
  from .mlflow_storage import MLFlowStorage
19
- from .mlflow_storage_callback import MLFlowStorageCallback
19
+ from .mlflow_storage_callback import (
20
+ MLFlowStorageCallback,
21
+ )
20
22
 
21
- __all__ = ["MLFlowStorage", "MLFlowStorageCallback"]
23
+ __all__ = [
24
+ "MLFlowStorage",
25
+ "MLFlowStorageCallback",
26
+ ]