Skip to content

docs(tutorials): add inline API links and contextual cross-references#891

Open
egordm wants to merge 21 commits into
release/v4.0.0from
docs/886-tutorial-notebooks
Open

docs(tutorials): add inline API links and contextual cross-references#891
egordm wants to merge 21 commits into
release/v4.0.0from
docs/886-tutorial-notebooks

Conversation

@egordm
Copy link
Copy Markdown
Collaborator

@egordm egordm commented May 18, 2026

Summary

Add clickable API documentation links and contextual cross-references across all 7 tutorial notebooks.

Changes

Inline API links — Key classes and functions mentioned in tutorial prose now link directly to their API documentation pages:

  • `ForecastingWorkflowConfig`, `create_forecasting_workflow`, `ForecastDataset`, `LeadTime`, `Q`
  • `BacktestPipeline`, `BacktestConfig`, `EvaluationPipeline`, `RMAEProvider`, `RCRPSProvider`
  • `HyperparameterTuner`, `FloatRange`, `IntRange`
  • `EnsembleForecastingWorkflowConfig`, `create_ensemble_forecasting_workflow`
  • `ForecastingModel`, `TransformPipeline`, `GBLinearForecaster`
  • `ExplainableForecaster`, `ContributionsPlotter`, `FeatureImportancePlotter`
  • `IsotonicQuantileCalibrator`
  • `ForecastTimeSeriesPlotter`

Contextual cross-references — Replaced bloated "Next steps" bullet lists (4-5 items per tutorial) with:

  1. Inline `{doc}` links where the prose naturally segues into another tutorial
  2. A trimmed "Next steps" section with only 1-2 logical continuations

Tutorials updated

  • `forecasting_quickstart`
  • `backtesting_quickstart`
  • `ensemble_forecasting`
  • `custom_pipeline`
  • `hyperparameter_tuning_with_optuna`
  • `model_explainability`
  • `quantile_calibration`

Closes #886

egordm added 14 commits May 18, 2026 13:55
- New jupytext .py (percent format) + paired .ipynb
- Train GBLinear on Liander 45-day slice, predict 7 days with quantiles
- Hidden setup cell (warnings/logger suppression, display config)
- Hidden assert cells for regression detection during CI execution
- Enable nb_execution_mode='cache' in Sphinx conf
- Exclude optuna notebook from execution (too slow for CI)
- Add to docs/source/examples.rst toctree

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Feature importance treemap via ExplainableForecaster
- Per-timestep SHAP contributions: heatmap, bar chart, waterfall
- Hidden assert cells for regression detection
- Exclude forecasting_with_workflow_presets from execution (stale)

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Before/after isotonic calibration comparison
- Expected vs observed coverage visualization
- Demonstrates IsotonicQuantileCalibrator as postprocessing step
- Hidden assert cells for regression detection

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Build ForecastingModel from individual transforms
- Shows preprocessing, forecaster, and postprocessing assembly
- Demonstrates TransformPipeline with LagsAdder, Scaler, Imputer, etc.
- Hidden assert cells for regression detection

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Explains built-in search spaces (Annotated metadata pattern)
- Shows how to activate/deactivate/customize tunable parameters
- Demonstrates changing tuning metric to rCRPS (RCRPSProvider)
- Trains untuned baseline for visual comparison
- 5 trials for CI compatibility (<120s)
- Removed from nb_execution_excludepatterns

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Explains ensemble architecture (base models + combiner)
- Configures learned_weights ensemble with lgbm + gblinear
- Trains and predicts with ensemble workflow
- Compares ensemble vs individual base models on same chart

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- XGBoost model with 48h horizon, 90-day training window
- Evaluation with day-ahead (D-1T0600) lead-time filtering
- Visualization using ForecastTimeSeriesPlotter with evaluation subset
- 'The easy way' section introducing the benchmark framework
- Runs in ~4 seconds, produces continuous gap-free predictions

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
The 3 standalone scripts in examples/examples/ are superseded by
interactive tutorials in examples/tutorials/:
- configuring_model_pipeline_example.py → custom_pipeline tutorial
- forecasting_preset_example.py → forecasting_with_workflow_presets tutorial
- isotonic_calibration_example.py → quantile_calibration tutorial

The deployment/ folder was an empty placeholder (.gitkeep only).

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Superseded by:
- backtesting_quickstart (low-level API, runs in 4s)
- examples/benchmarks/ (full benchmark scripts, to be converted to jupytext)

The BEAM tutorial took ~1 hour to run and duplicated benchmark functionality.

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
…docs integration

- Move 3 Liander 2024 scripts to examples/benchmarks/liander2024/
- Move 6 custom benchmark scripts to examples/benchmarks/custom/
- Rename files for clarity (e.g. example_baseline -> custom_forecaster)
- Convert all scripts to jupytext format with markdown cells
- Hide boilerplate (SPDX, os.environ) with tags=[remove-cell]
- Add explanatory markdown sections between code cells
- Create README.md for each folder (overview, liander2024, custom)
- Integrate into docs build (myst-nb, excluded from execution)
- Add hierarchical sidebar nav (Benchmarking > Liander 2024 / Build Your Own)
- Group tutorials into sections (Getting Started, Model Training, Evaluation)
- Extend CI tasks (notebooks, notebooks-check, notebooks-clear)
- Update tools/check_notebook_outputs.py for new paths
- Add per-file-ignores for benchmark lint rules

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
…ickstart + explainability)

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Add 'Key API references' section to each tutorial intro
- Expand 'Next steps' with links to all related tutorials
- Add links to benchmark notebooks where relevant
- Standardize {doc} directive formatting

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Link class/function mentions to their API reference pages
- ForecastingWorkflowConfig, create_forecasting_workflow, ForecastDataset,
  ForecastTimeSeriesPlotter, BacktestPipeline, EvaluationPipeline,
  EnsembleForecastingWorkflowConfig, ForecastingModel,
  CustomForecastingWorkflow, IsotonicQuantileCalibrator,
  ConfidenceIntervalApplicator, QuantileSorter, ContributionsPlotter,
  FeatureImportancePlotter, VersionedTimeSeriesDataset, etc.
- Links point to openstef.github.io/openstef/v4/api/generated/ pages

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Add clickable links to API documentation for key classes/functions
  mentioned in tutorial prose (ForecastingWorkflowConfig, BacktestPipeline,
  HyperparameterTuner, ExplainableForecaster, IsotonicQuantileCalibrator, etc.)
- Replace bloated 'Next steps' bullet lists (4-5 items each) with 1-2
  contextual recommendations per tutorial
- Add inline {doc} cross-references where tutorials naturally segue into
  related topics (e.g. after quantile results → quantile_calibration)

Closes #886

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
@egordm egordm requested a review from a team May 18, 2026 13:28
@github-actions github-actions Bot added the chore Improvements or additions to documentation label May 18, 2026
egordm added 7 commits May 18, 2026 15:35
Jupyter .ipynb files and example .py scripts (tutorials, benchmarks) are
interactive notebook code, not library code.  SonarQube flags patterns
like user-toggles (USE_MLFLOW_STORAGE) as constant expressions — these
are false positives for configurable notebook cells.

- sonar.exclusions: **/*.ipynb, examples/tutorials/*.py, examples/benchmarks/**/*.py
- sonar.cpd.exclusions: **/tests/**/*.py (test fixture duplication is expected)

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Replace unicode EN DASH with hyphen in forecasting_quickstart.py (RUF003)
- Add per-file-ignores for tutorial notebooks: ANN, B905, D103, PLR2004,
  PT018, RUF003, SLF001 — these are interactive notebook patterns, not
  library code
- Auto-formatted pyproject.toml via pyproject-fmt
- Added .license files for benchmark notebooks (reuse --fix)

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Replace hardcoded constants with environment variable lookups to avoid
SonarQube 'always constant' false positives and make benchmarks
configurable without code changes:

- OPENSTEF_N_PROCESSES: defaults to cpu_count() (or 1 in ensemble)
- OPENSTEF_MLFLOW_STORAGE: defaults to 'false' (xgboost) / 'true' (ensemble)

Also extend sonar.exclusions to cover docs/source/tutorials/** and
docs/source/benchmarks/** (synced copies).

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
- Add strict=True to zip() calls in quantile_calibration (B905)
- Remove B905 and RUF003 from per-file-ignores (issues are fixed, not ignored)
- Add sonar.python.version=3.12 for precise SonarQube analysis
- Remove .playwright-mcp from .gitignore (moved to .git/info/exclude)

Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
Signed-off-by: Egor Dmitriev <egor.dmitriev@alliander.com>
@egordm egordm force-pushed the docs/886-tutorial-notebooks branch from ffb11b0 to 767cc93 Compare May 18, 2026 14:09
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Collaborator

@lschilders lschilders left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comments:

  • There are quite some warnings from executions, such as [WARNING] No aggregation functions specified. Returning original data. and Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads. (These are logged twice as well). Would be nice to solve this and incorporate a check for warnings maybe?
  • Just an idea: Wouldn't it be nice to have some cells collapsed by default? For example cells that only generate figures are not very interesting to have the code displayed by default.

result_single = single_transform.transform(train_dataset)

added = sorted(set(result_single.data.columns) - set(train_dataset.data.columns))
print(f"CyclicFeaturesAdder added {len(added)} columns: {added}")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transforms have a features_added property

default_hp = XGBoostHyperParams()
default_space = default_hp.get_search_space()
print(f"Default tunable parameters: {len(default_space)}")
print("(None — all parameters use their fixed defaults until you opt in)")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the None say here?

Comment on lines +128 to +129
# For a perfectly calibrated forecast at quantile $p$, the fraction of
# observations falling below the predicted value should equal $p$. We compute
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $ p $ are not rendered here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants