Documentation Guide#
OpenSTEF welcomes improvements to documentation! Whether you’re fixing typos, clarifying explanations, or adding tutorials, your contributions help make forecasting more accessible to everyone.
Getting started#
Documentation structure#
OpenSTEF documentation is organized following the Diátaxis framework:
Tutorials (
examples/tutorials/): Learning-oriented guides for beginnersHow-to guides (
user_guide/): Problem-oriented practical guidesReference (
api/): Information-oriented technical referenceExplanation (
user_guide/intro/): Understanding-oriented background material
The documentation lives in several places:
docs/source/ # Main documentation source
├── api/ # API reference (auto-generated)
├── user_guide/ # User guides and tutorials
├── project/ # Project information
├── contribute/ # Contributing guides
└── examples/ # Example gallery
examples/ # Example scripts and tutorials
├── examples/ # Gallery examples
└── tutorials/ # Tutorials
packages/*/src/ # Inline code documentation (docstrings)
Building the documentation#
To build the documentation locally:
# Build the documentation
poe docs
# Build and serve with live reload (recommended for editing)
poe docs --serve
# Clean previous builds
poe docs-clean
The built documentation will be available at docs/build/html/index.html.
Note
Building documentation requires additional dependencies that are included in the
development environment. Make sure you’ve run uv sync --group dev first.
Writing docstrings#
OpenSTEF uses Google-style docstrings for all code documentation. This style is clear, readable, and well-supported by Sphinx.
Basic docstring structure#
def forecast_energy(data: pd.DataFrame, horizon: int = 24) -> pd.DataFrame:
"""Generate energy forecasts for the specified horizon.
This function creates forecasts using the configured model and feature
engineering pipeline. It handles missing data and provides uncertainty
estimates for each prediction.
Args:
data: Historical energy consumption data with datetime index.
Must include columns: ['load', 'temperature', 'wind_speed'].
horizon: Number of hours to forecast ahead. Must be positive.
Returns:
DataFrame with forecasted values and uncertainty bounds:
- 'forecast': Point predictions
- 'forecast_lower': Lower confidence bound (5th percentile)
- 'forecast_upper': Upper confidence bound (95th percentile)
Raises:
ValueError: If data is empty or missing required columns.
TypeError: If horizon is not a positive integer.
Example:
Basic usage with sample data:
>>> import pandas as pd
>>> data = pd.DataFrame({
... 'load': [100, 120, 110],
... 'temperature': [20, 22, 21],
... 'wind_speed': [5, 7, 6]
... }, index=pd.date_range('2025-01-01', periods=3, freq='h'))
>>> forecast = forecast_energy(data, horizon=6)
>>> forecast.shape
(6, 3)
Note:
The model automatically handles daylight saving time transitions and
public holidays for improved accuracy.
See Also:
evaluate_forecast: Evaluate forecast accuracy against ground truth.
prepare_features: Prepare input data for forecasting.
"""
Docstring sections#
Use these sections in your docstrings (order matters):
Summary line: One-line description of what the function does
Extended description: More detailed explanation (optional)
Args: Function parameters and their types/descriptions
Returns: Description of return value(s)
Raises: Exceptions that may be raised
Example: Code examples showing how to use the function
Note: Additional important information
Invariants: Contract guarantees and requirements (for classes and interfaces)
See Also: References to related functions/classes
Type hints and docstrings#
Always use type hints in function signatures. The docstring should complement, not repeat, the type information:
# Good: Type hints in signature, description in docstring
def train_model(data: TimeSeriesDataset, config: ModelConfig) -> ForecastModel:
"""Train a forecasting model on the provided dataset.
Args:
data: Training dataset with features and targets.
config: Model configuration including hyperparameters.
Returns:
Trained model ready for forecasting.
"""
# Avoid: Repeating type information in docstring
def train_model(data: TimeSeriesDataset, config: ModelConfig) -> ForecastModel:
"""Train a forecasting model on the provided dataset.
Args:
data (TimeSeriesDataset): Training dataset with features and targets.
config (ModelConfig): Model configuration including hyperparameters.
Returns:
ForecastModel: Trained model ready for forecasting.
"""
Invariants section#
For classes and interfaces, use an Invariants section to document the contract
guarantees and requirements that implementers and users must follow:
class ForecastModel(ABC):
"""Base class for all forecasting models.
Provides a standardized interface for training and prediction across
different forecasting algorithms and approaches.
Invariants:
- fit() must be called before predict() for stateful models
- predict() should handle all horizons specified in configuration
- Output format must be consistent with ForecastDataset structure
- Model state must remain unchanged during prediction calls
Example:
Basic model implementation:
>>> class SimpleModel(ForecastModel):
... def fit(self, data):
... self._fitted = True
... def predict(self, data):
... return generate_forecasts(data)
"""
The Invariants section should document:
Pre-conditions: What must be true before calling methods
Post-conditions: What the implementation guarantees after execution
State requirements: How object state should be managed
Interface contracts: Consistent behavior expectations across implementations
This helps both implementers understand what they must provide and users understand what they can rely on.
Note
The Invariants section is an OpenSTEF-specific extension to Google-style
docstrings. Use it for classes and interfaces where contract guarantees are
important for correct implementation and usage.
Examples in docstrings#
Include practical examples in your docstrings using the Example section.
These examples are automatically tested with poe doctests.
Writing good examples#
def calculate_mae(y_true: np.ndarray, y_pred: np.ndarray) -> float:
"""Calculate Mean Absolute Error between predictions and ground truth.
Example:
Basic usage:
>>> import numpy as np
>>> y_true = np.array([1, 2, 3, 4, 5])
>>> y_pred = np.array([1.1, 2.2, 2.9, 3.8, 5.2])
>>> mae = calculate_mae(y_true, y_pred)
>>> round(mae, 2)
0.16
With perfect predictions:
>>> perfect_pred = np.array([1, 2, 3, 4, 5])
>>> calculate_mae(y_true, perfect_pred)
0.0
"""
Example guidelines#
Keep examples simple but realistic
Use ``>>>`` prompts for interactive examples
Show expected output when it’s not obvious
Test edge cases (empty inputs, perfect predictions, etc.)
Use ``round()`` for floating-point outputs to avoid precision issues
Import required modules within the example if needed
Writing narrative documentation#
For user guides, tutorials, and explanatory content, use reStructuredText (.rst) files.
reStructuredText basics#
Section headers
===============
Subsection headers
------------------
*Italic text* and **bold text**
``Code snippets`` and :func:`function references`
.. code-block:: python
# Code blocks with syntax highlighting
import openstef
model = openstef.create_model()
.. note::
Informational notes for readers.
.. warning::
Important warnings about potential issues.
Cross-references#
Link to other parts of the documentation:
# Link to other documents
See the :doc:`user_guide/installation` guide.
# Link to specific functions/classes
Use :func:`openstef.models.forecast` for predictions.
# Link to sections within documents
Refer to :ref:`development_setup` for setup instructions.
Contributing to examples and tutorials#
Examples and tutorials are crucial for user onboarding. When adding new examples:
Choose the right location:
examples/examples/- Short, focused examplesexamples/tutorials/- Multi-step tutorials
Follow naming conventions:
Use descriptive filenames:
basic_forecasting.py,advanced_transforms.pyStart with a docstring explaining the example’s purpose
Structure your example:
""" Basic Energy Forecasting ======================== This example demonstrates how to create simple energy forecasts using OpenSTEF. We'll load sample data, train a model, and generate predictions. """ import pandas as pd import openstef # Load sample data data = openstef.load_sample_data() # ... rest of example
Include explanations: Use comments and markdown cells to explain each step
Test your examples: Run
poe docteststo ensure all examples work
Documentation style guide#
Writing style#
Be clear and concise - Avoid jargon, explain technical terms
Use active voice - “The model predicts” rather than “Predictions are made”
Write for your audience - Tutorials for beginners, reference for experts
Include context - Explain why something is useful, not just how to do it
Code style in documentation#
Use realistic examples - Avoid
foo,bar; use domain-relevant namesShow complete examples - Include imports and setup code
Highlight important parts - Use comments to draw attention to key concepts
Test all code - Ensure examples actually work
All code examples in documentation should follow our Style Guide.
Building and testing documentation#
Before submitting documentation changes:
# Check that documentation builds without errors
poe docs
# Test all code examples in docstrings
poe doctests
# Run full quality checks (includes documentation)
poe all --check
Common issues#
Import errors: Make sure all imports in examples are available
Outdated examples: Keep examples current with API changes
Broken links: Verify that all cross-references work
Missing docstrings: All public functions need documentation
Getting help#
If you need assistance:
💬 Slack: Join the LF Energy Slack workspace (#openstef channel)
🐛 Issues: Check GitHub Issues or create a new one
📧 Email: Contact us at
openstef@lfenergy.org🤝 Community meetings: Join our four-weekly co-coding sessions
For more information, see our Support page.
Additional documentation resources#
If you need help with documentation specifically:
Check the Sphinx documentation
Look at existing documentation for examples
Reference the Diátaxis framework for guidance on documentation types