visualization
Visualization module for change-point detection.
This module provides a backend-agnostic visualization system for rendering
time series data, online detection traces, algorithm state evolution, and
benchmark performance metrics. All visualizers and components support both
Matplotlib (static) and Plotly (interactive) backends through the
DrawBackend enum.
The architecture follows two complementary patterns: the Strategy pattern for visualizers that own complete subplots, and the Component pattern for composable drawing elements that layer annotations onto existing axes.
Public API
Abstract interfaces (see abstracts subpackage for details):
IVisualizer: Base interface for all visualizers managing complete subplots. Declaresaxes,backend, and backend-specificdrawmethods.ITimeseriesVisualizer: Interface for time series visualizers. Generic overDataProvider.ITraceVisualizer: Interface for detection trace visualizers. Generic overDetectionTrace.IMetricVisualizer: Base class for benchmark metric visualizers.IVisualComponent: Interface for composable drawing components that render annotation elements onto a single subplot.
Time series visualizers (see timeseries subpackage for details):
UnivariateTimeseriesVisualizer: Renders a single time series with change point annotations and period fills.PlainMultivariateTimeseriesVisualizer: Dimension-oriented visualizer creating one subplot per data dimension.MultivariateTimeseriesVisualizer: Compatibility alias forPlainMultivariateTimeseriesVisualizer.RichMultivariateTimeseriesVisualizer: Pandas-first visualizer organizing data by logical plot names with optional twin y-axis.
Online detection visualizers (see online subpackage for details):
OnlineTraceVisualizer: Renders detection function values, threshold lines, and processing time evolution. Accepts a composable state visualizer for algorithm-specific panels.IOnlineStateVisualizer: Abstract interface for algorithm state evolution visualizers. Generic overOnlineAlgorithmState.DummyStateVisualizer: Placeholder state visualizer for testing or when state visualization is not needed.
Benchmarking visualizers (see benchmarking subpackage for details):
BenchmarkPlotter: Coordinates multiple metric visualizers into composite benchmark figures.ThresholdBasedMetricVisualizer: Plots metrics as functions of detection threshold.PrAucVisualizer: Draws precision-recall curves with PR-AUC annotation.ARLBasedMetricVisualizer: Plots metrics as functions of average run length, producing lower-envelope curves.
Coordinator and components:
OnlineCpdPlotter: High-level coordinator that bundles a timeseries visualizer, an online trace visualizer, and annotation components into a single draw call. Supports named layout strategies.VerticalLineVisualComponent: Draws vertical lines at specified x-coordinates.VerticalFillComponent: Draws filled vertical regions between pairs of x-coordinates.
Style specifications and types:
PlotSpec: TypedDict for subplot-level options (title, axis labels, grid).LineSpec: TypedDict for line-style options (color, linewidth, linestyle, etc.).FilledLineSpec: TypedDict extendingLineSpecwith fill options.FillSpec: TypedDict for filled element styling.DrawBackend: Enum withMATPLOTLIBandPLOTLYvalues.
Utilities:
get_plotly_subplot_annotation_index: Calculates the annotation index for a subplot in a Plotly figure.
Subpackages
- abstracts
Abstract base classes defining contracts for visualizers and composable drawing components. See the
abstractssubpackage docstring for architecture and backend abstraction details.- timeseries
Univariate and multivariate time series visualizers. See the
timeseriessubpackage docstring for usage examples.- online
Online detection trace visualizers, state visualizers, and the
OnlineCpdPlottercoordinator. See theonlinesubpackage docstring for composition patterns and layout strategies.- benchmarking
Benchmark metric visualizers and the
BenchmarkPlottercoordinator. See thebenchmarkingsubpackage docstring for registration and drawing workflow details.- components
Reusable annotation components (vertical lines and fills). See the
componentssubpackage docstring for composable usage patterns.
Examples
Visualize a univariate time series with Matplotlib:
>>> import matplotlib.pyplot as plt
>>> from pysatl_cpd.analysis.visualization import (
... DrawBackend,
... UnivariateTimeseriesVisualizer,
... )
>>> from pysatl_cpd.data.generator import (
... GenericSeriesGenerator,
... NormalSpec,
... ScenarioSpec,
... SegmentPlan,
... SegmentSpec,
... build_plain_univariate_labeled_data,
... )
>>> from pysatl_cpd.data.typedefs import StateDescriptor, frozendict
>>> scenario = ScenarioSpec(
... name="demo",
... segments=(
... SegmentSpec(plan_name="a", length=50),
... SegmentSpec(plan_name="b", length=50),
... ),
... plans=frozendict(
... a=SegmentPlan(
... distribution=NormalSpec(mean=0.0, std=1.0),
... state=StateDescriptor(type="a"),
... name="a",
... ),
... b=SegmentPlan(
... distribution=NormalSpec(mean=3.0, std=1.0),
... state=StateDescriptor(type="b"),
... name="b",
... ),
... ),
... )
>>> series = GenericSeriesGenerator(seed=42).generate_from_scenario(scenario, name="demo")
>>> provider = build_plain_univariate_labeled_data(series, feature_name="value", name="demo")
>>> visualizer = UnivariateTimeseriesVisualizer(backend=DrawBackend.MATPLOTLIB)
>>> visualizer.set_data_provider(provider)
>>> fig, ax = plt.subplots()
>>> visualizer.draw(figure=fig, axes={"timeseries": ax})
Add vertical line and fill components to a Plotly figure:
>>> import plotly.graph_objects as go
>>> from plotly.subplots import make_subplots
>>> from pysatl_cpd.analysis.visualization import DrawBackend
>>> from pysatl_cpd.analysis.visualization.components import (
... VerticalFillComponent,
... VerticalLineVisualComponent,
... )
>>> fig = make_subplots(rows=1, cols=1)
>>> _ = fig.add_trace(go.Scatter(x=list(range(10)), y=list(range(10)), name="data"), row=1, col=1)
>>> line_component = (
... VerticalLineVisualComponent(DrawBackend.PLOTLY)
... .set_lines([3, 7])
... .set_style(color="red", linestyle="dash", linewidth=2, label="change points", legend=True)
... )
>>> fill_component = (
... VerticalFillComponent(DrawBackend.PLOTLY)
... .set_regions([(2, 4), (6, 8)])
... .set_style(fill_color="blue", fill_alpha=0.15, label="margin", legend=True)
... )
>>> fill_component.draw(fig, (1, 1), add_legend=True)
>>> line_component.draw(fig, (1, 1), add_legend=True)
Build a full online CPD visualization with OnlineCpdPlotter:
>>> from pysatl_cpd.analysis.visualization import DrawBackend, OnlineCpdPlotter
>>> from pysatl_cpd.core.online import OnlineResetDetector
>>> from pysatl_cpd.algorithms.online import ShewhartControlChart
>>> detector = OnlineResetDetector(
... ShewhartControlChart(learning_period_size=30, window_size=10),
... threshold=2.0,
... skip_period=8,
... )
>>> trace = detector.detect(provider)
>>> plotter = OnlineCpdPlotter(
... backend=DrawBackend.MATPLOTLIB,
... data_provider=provider,
... detection_trace=trace,
... layout="vertical",
... )
>>> fig, ax_mapping = plotter.default_layout()
>>> fig = plotter.draw(figure=fig, axes=ax_mapping)
Notes
Requires Python 3.12+ for PEP 695 generic syntax.
Matplotlib and plotly are required at runtime. Both are listed as optional dependencies in
pyproject.toml.Benchmarking visualizers additionally require pandas and numpy.
Change-point indices are zero-based throughout the visualization system.
The
drawmethod expects an axes mapping whose keys match the visualizer’saxesproperty. Matplotlib mappings useAxesobjects; Plotly mappings use(row, col)tuples.MultivariateTimeseriesVisualizeris a compatibility alias; preferPlainMultivariateTimeseriesVisualizerin new code.
- abstracts
- benchmarking
- components
- online
- timeseries
- specs
- typedefs
- utils
normalize_backend()is_plotly_figure()is_matplotlib_figure()is_plotly_axes()is_matplotlib_axes()is_plotly_mapping()is_matplotlib_mapping()get_plotly_subplot_annotation_index()translate_linestyle()to_plotly_color()to_plotly_dash()to_plotly_marker()resolve_legend_visibility()resolve_legend_label()resolve_legend_group()get_matplotlib_legend_label()get_plotly_legend_kwargs()line_spec_to_mpl_kwargs()line_spec_to_plotly_trace_kwargs()fill_spec_to_mpl_kwargs()fill_spec_to_plotly_trace_kwargs()filled_line_spec_to_mpl_line_kwargs()filled_line_spec_to_mpl_fill_kwargs()rgba_color()filled_line_spec_to_plotly_trace_kwargs()apply_matplotlib_plot_spec()apply_matplotlib_twin_plot_spec()apply_plotly_plot_spec()apply_plotly_twin_plot_spec()get_subplot_y_limits()