"""
Time series visualization functions (statsmodels-style API).
This module provides simple function-based API for common visualizations,
following the statsmodels pattern where ax=None creates a new figure.
Examples
--------
>>> from temporalcv.viz import plot_cv_folds, plot_prediction_intervals
>>>
>>> # Simple one-liner
>>> plot_cv_folds(cv, X)
>>> plt.show()
>>>
>>> # With custom axes
>>> fig, (ax1, ax2) = plt.subplots(1, 2)
>>> plot_cv_folds(cv, X, ax=ax1)
>>> plot_prediction_intervals(intervals, actuals, ax=ax2)
>>> plt.show()
"""
from __future__ import annotations
from typing import Any
import numpy as np
from matplotlib.axes import Axes
from .comparison import MetricComparisonDisplay
from .cv import CVFoldsDisplay
from .intervals import PredictionIntervalDisplay
__all__ = [
"plot_cv_folds",
"plot_prediction_intervals",
"plot_interval_width",
"plot_metric_comparison",
]
[docs]
def plot_cv_folds(
cv: Any,
X: np.ndarray,
y: np.ndarray | None = None,
*,
groups: np.ndarray | None = None,
ax: Axes | None = None,
tufte: bool = True,
title: str | None = None,
) -> Axes:
"""
Plot cross-validation fold structure.
Convenience function wrapping CVFoldsDisplay.
Parameters
----------
cv : cross-validator
A scikit-learn compatible cross-validator.
X : array-like
Training data.
y : array-like, optional
Target values.
groups : array-like, optional
Group labels.
ax : matplotlib.axes.Axes, optional
Axes to plot on. If None, creates new figure.
tufte : bool
If True, apply Tufte styling (default).
title : str, optional
Plot title.
Returns
-------
matplotlib.axes.Axes
The axes with the plot.
Examples
--------
>>> from temporalcv import WalkForwardCV
>>> from temporalcv.viz import plot_cv_folds
>>>
>>> cv = WalkForwardCV(n_splits=5, test_size=20)
>>> plot_cv_folds(cv, X, title="Walk-Forward CV")
>>> plt.show()
See Also
--------
CVFoldsDisplay : Class-based API for more customization.
"""
display = CVFoldsDisplay.from_cv(cv, X, y, groups=groups)
display.plot(ax=ax, tufte=tufte, title=title)
return display.ax_
[docs]
def plot_prediction_intervals(
intervals: Any,
actuals: np.ndarray | None = None,
*,
x: np.ndarray | None = None,
ax: Axes | None = None,
tufte: bool = True,
show_coverage: bool = True,
title: str | None = None,
) -> Axes:
"""
Plot prediction intervals with actuals.
Convenience function wrapping PredictionIntervalDisplay.
Parameters
----------
intervals : PredictionInterval
Prediction interval object from conformal predictor.
actuals : array-like, optional
Actual values for coverage visualization.
x : array-like, optional
X-axis values (e.g., time indices).
ax : matplotlib.axes.Axes, optional
Axes to plot on.
tufte : bool
If True, apply Tufte styling.
show_coverage : bool
If True, highlight covered/uncovered points.
title : str, optional
Plot title.
Returns
-------
matplotlib.axes.Axes
The axes with the plot.
Examples
--------
>>> from temporalcv.conformal import SplitConformalPredictor
>>> from temporalcv.viz import plot_prediction_intervals
>>>
>>> conformal = SplitConformalPredictor(alpha=0.10)
>>> conformal.calibrate(cal_preds, cal_actuals)
>>> intervals = conformal.predict_interval(test_preds)
>>>
>>> plot_prediction_intervals(intervals, test_actuals)
>>> plt.show()
See Also
--------
PredictionIntervalDisplay : Class-based API.
"""
display = PredictionIntervalDisplay.from_conformal(intervals, actuals, x=x)
display.plot(ax=ax, tufte=tufte, show_coverage=show_coverage, title=title)
return display.ax_
[docs]
def plot_interval_width(
intervals: Any,
*,
x: np.ndarray | None = None,
ax: Axes | None = None,
tufte: bool = True,
title: str | None = None,
) -> Axes:
"""
Plot prediction interval widths over time.
Useful for adaptive conformal where width varies.
Parameters
----------
intervals : PredictionInterval
Prediction interval object.
x : array-like, optional
X-axis values.
ax : matplotlib.axes.Axes, optional
Axes to plot on.
tufte : bool
If True, apply Tufte styling.
title : str, optional
Plot title.
Returns
-------
matplotlib.axes.Axes
The axes with the plot.
Examples
--------
>>> from temporalcv.conformal import AdaptiveConformalPredictor
>>> from temporalcv.viz import plot_interval_width
>>>
>>> adaptive = AdaptiveConformalPredictor(alpha=0.10, gamma=0.01)
>>> # ... fit and predict ...
>>> plot_interval_width(intervals)
>>> plt.show()
See Also
--------
PredictionIntervalDisplay.plot_width : Class-based method.
"""
display = PredictionIntervalDisplay.from_conformal(intervals, x=x)
display.plot_width(ax=ax, tufte=tufte, title=title)
return display.ax_
[docs]
def plot_metric_comparison(
results: dict[str, dict[str, float]],
*,
ax: Axes | None = None,
tufte: bool = True,
baseline: str | None = None,
show_values: bool = True,
title: str | None = None,
) -> Axes:
"""
Plot metric comparison across models.
Parameters
----------
results : dict
Nested dict of {model_name: {metric_name: value}}.
ax : matplotlib.axes.Axes, optional
Axes to plot on.
tufte : bool
If True, apply Tufte styling.
baseline : str, optional
Name of baseline model for highlighting.
show_values : bool
If True, show values on bars.
title : str, optional
Plot title.
Returns
-------
matplotlib.axes.Axes
The axes with the plot.
Examples
--------
>>> from temporalcv.viz import plot_metric_comparison
>>>
>>> results = {
... "Model A": {"MAE": 0.15, "RMSE": 0.22},
... "Model B": {"MAE": 0.12, "RMSE": 0.19},
... }
>>> plot_metric_comparison(results, baseline="Model A")
>>> plt.show()
See Also
--------
MetricComparisonDisplay : Class-based API.
"""
display = MetricComparisonDisplay.from_dict(results, baseline=baseline)
display.plot(ax=ax, tufte=tufte, show_values=show_values, title=title)
return display.ax_