Visualization¶
fastcpd-python provides 5 publication-quality plotting functions for visualizing change point detection results and evaluation metrics.
Overview¶
Function |
Purpose |
Key Features |
|---|---|---|
|
Plot data with detected and true change points |
Automatic metric overlay |
|
Compare metrics across algorithms |
Side-by-side comparison |
|
Visualize multiple annotations |
Agreement visualization |
|
ROC curve for detection performance |
Threshold analysis |
|
Visualize dataset properties |
SNR, difficulty analysis |
Quick Start¶
Basic Detection Plot¶
from fastcpd.visualization import plot_detection
from fastcpd.segmentation import mean
from fastcpd.datasets import make_mean_change
import matplotlib.pyplot as plt
# Generate data
data_dict = make_mean_change(n_samples=500, n_changepoints=3, seed=42)
# Detect change points
result = mean(data_dict['data'], beta="MBIC")
# Visualize
fig, ax = plot_detection(
data=data_dict['data'],
true_cps=data_dict['changepoints'],
pred_cps=result.cp_set.tolist(),
title="Mean Change Detection"
)
plt.show()
With Metrics Overlay¶
from fastcpd.metrics import evaluate_all
# Evaluate metrics
metrics = evaluate_all(
data_dict['changepoints'],
result.cp_set.tolist(),
n_samples=500,
margin=10
)
# Plot with metrics
fig, ax = plot_detection(
data=data_dict['data'],
true_cps=data_dict['changepoints'],
pred_cps=result.cp_set.tolist(),
metric_result=metrics, # Automatically displays metrics
title="Mean Change Detection"
)
Plotting Functions¶
plot_detection¶
Main plotting function for visualizing detection results.
Signature:
plot_detection(
data,
true_cps=None,
pred_cps=None,
metric_result=None,
title=None,
figsize=(12, 6),
show_legend=True
)
Parameters:
data: Array of shape (n,) or (n, d) - data to plottrue_cps: List of true change point locations (optional)pred_cps: List of detected change point locations (optional)metric_result: Dictionary fromevaluate_all()(optional)title: Plot titlefigsize: Figure sizeshow_legend: Whether to show legend
Returns:
fig, ax: Matplotlib figure and axes objects
Example:
import numpy as np
from fastcpd.visualization import plot_detection
# Simple data
data = np.concatenate([
np.random.normal(0, 1, 200),
np.random.normal(3, 1, 200),
np.random.normal(1, 1, 200)
])
fig, ax = plot_detection(
data=data,
true_cps=[200, 400],
pred_cps=[198, 405],
title="Example Detection"
)
Multivariate Data:
For multivariate data, plots the first 3 dimensions:
# 5D data
data_5d = np.random.randn(500, 5)
# Plots first 3 dimensions automatically
plot_detection(
data=data_5d,
pred_cps=[200, 350]
)
plot_annotators¶
Visualize multiple expert annotations and detection agreement.
from fastcpd.visualization import plot_annotators
# Multiple annotators
annotators_list = [
[100, 200, 300], # Expert 1
[105, 195, 305], # Expert 2
[98, 203, 298] # Expert 3
]
detected_cps = [102, 201, 299]
fig, ax = plot_annotators(
data=data,
annotators_list=annotators_list,
pred_cps=detected_cps,
title="Multi-Annotator Detection"
)
Features:
Shows all annotators with different colors
Highlights agreement regions
Overlays detected change points
Computes covering metric
plot_metric_comparison¶
Compare detection performance across multiple algorithms or parameters.
from fastcpd.visualization import plot_metric_comparison
from fastcpd.segmentation import mean, rank, rbf
# Try multiple algorithms
algorithms = ['mean', 'rank', 'rbf']
metrics_list = []
for algo in algorithms:
if algo == 'mean':
result = mean(data, beta="MBIC")
elif algo == 'rank':
result = rank(data, beta=50.0)
elif algo == 'rbf':
result = rbf(data, beta=30.0)
metrics = evaluate_all(
true_cps=[100, 200, 300],
pred_cps=result.cp_set.tolist(),
n_samples=500,
margin=10
)
metrics_list.append(metrics)
# Compare
fig, axes = plot_metric_comparison(
metrics_list=metrics_list,
algorithm_names=algorithms,
metrics_to_plot=['precision', 'recall', 'f1_score']
)
Features:
Side-by-side bar charts
Multiple metrics simultaneously
Easy algorithm comparison
Customization¶
Custom Styling¶
All functions return fig, ax for further customization:
fig, ax = plot_detection(data, pred_cps=[100, 200])
# Customize
ax.set_xlabel('Time (seconds)', fontsize=14)
ax.set_ylabel('Signal Amplitude', fontsize=14)
ax.set_title('Custom Title', fontsize=16, fontweight='bold')
ax.grid(True, alpha=0.3, linestyle='--')
# Adjust legend
ax.legend(loc='upper right', fontsize=12)
# Tight layout
fig.tight_layout()
Custom Colors¶
fig, ax = plot_detection(data, pred_cps=[100])
# Get line objects
lines = ax.get_lines()
# Customize colors
lines[0].set_color('darkblue') # Data
lines[1].set_color('red') # Change points
lines[1].set_linewidth(3)
Saving Figures¶
fig, ax = plot_detection(data, pred_cps=[100, 200])
# Save as PNG
fig.savefig('detection_result.png', dpi=300, bbox_inches='tight')
# Save as PDF (vector graphics)
fig.savefig('detection_result.pdf', bbox_inches='tight')
# Save as SVG
fig.savefig('detection_result.svg', bbox_inches='tight')
Publication-Ready Figures¶
Recommended Settings¶
import matplotlib.pyplot as plt
# Set publication style
plt.rcParams['font.size'] = 12
plt.rcParams['axes.labelsize'] = 14
plt.rcParams['axes.titlesize'] = 16
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
plt.rcParams['legend.fontsize'] = 12
plt.rcParams['figure.titlesize'] = 16
plt.rcParams['lines.linewidth'] = 2
# Use publication-friendly backend
plt.rcParams['pdf.fonttype'] = 42 # TrueType fonts for PDFs
# Create plot
fig, ax = plot_detection(
data=data,
true_cps=[100, 200],
pred_cps=[98, 205],
figsize=(10, 5)
)
# Save high-quality figure
fig.savefig('figure1.pdf', dpi=300, bbox_inches='tight')
Complete Example¶
import numpy as np
import matplotlib.pyplot as plt
from fastcpd.visualization import plot_detection
from fastcpd.segmentation import mean
from fastcpd.datasets import make_mean_change
from fastcpd.metrics import evaluate_all
# Generate data
np.random.seed(42)
data_dict = make_mean_change(
n_samples=600,
n_changepoints=3,
mean_shift=3.0,
noise_std=1.0,
seed=42
)
# Detect
result = mean(data_dict['data'], beta="MBIC")
# Evaluate
metrics = evaluate_all(
data_dict['changepoints'],
result.cp_set.tolist(),
n_samples=600,
margin=10
)
# Plot
fig, ax = plot_detection(
data=data_dict['data'],
true_cps=data_dict['changepoints'],
pred_cps=result.cp_set.tolist(),
metric_result=metrics,
title='Mean Change Detection with PELT Algorithm',
figsize=(12, 6)
)
# Customize
ax.set_xlabel('Time Index', fontsize=14)
ax.set_ylabel('Signal Value', fontsize=14)
ax.grid(True, alpha=0.3)
# Save
fig.savefig('mean_detection_example.pdf', dpi=300, bbox_inches='tight')
plt.show()
Advanced Visualizations¶
Heatmap of Detection Across Parameters¶
import numpy as np
import matplotlib.pyplot as plt
from fastcpd.segmentation import mean
# Parameter grid
beta_values = np.logspace(0.5, 2, 20) # 10^0.5 to 10^2
n_values = len(beta_values)
# Store results
detection_matrix = np.zeros((n_values, len(data)))
for i, beta_val in enumerate(beta_values):
result = mean(data, beta=beta_val)
for cp in result.cp_set:
if 0 <= cp < len(data):
detection_matrix[i, int(cp)] = 1
# Plot heatmap
fig, ax = plt.subplots(figsize=(12, 6))
im = ax.imshow(detection_matrix, aspect='auto', cmap='YlOrRd',
extent=[0, len(data), beta_values[0], beta_values[-1]])
ax.set_xlabel('Time Index')
ax.set_ylabel('Beta Value')
ax.set_title('Change Point Detection Across Beta Values')
plt.colorbar(im, label='Detection')
plt.show()
Comparison of Multiple Models¶
from fastcpd.segmentation import mean, variance, rank, rbf
models = {
'Mean': mean(data, beta="MBIC"),
'Variance': variance(data, beta="MBIC"),
'Rank': rank(data, beta=50.0),
'RBF': rbf(data, beta=30.0)
}
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
axes = axes.flatten()
for i, (name, result) in enumerate(models.items()):
axes[i].plot(data, linewidth=1, alpha=0.7, label='Data')
for cp in result.cp_set:
axes[i].axvline(cp, color='red', linestyle='--', linewidth=2)
axes[i].set_title(f'{name} Model', fontsize=14)
axes[i].set_xlabel('Time')
axes[i].set_ylabel('Value')
axes[i].legend()
axes[i].grid(True, alpha=0.3)
fig.tight_layout()
plt.show()
Integration with Other Tools¶
Plotly for Interactive Plots¶
import plotly.graph_objects as go
fig = go.Figure()
# Add data trace
fig.add_trace(go.Scatter(
x=list(range(len(data))),
y=data,
mode='lines',
name='Data'
))
# Add change points
for cp in result.cp_set:
fig.add_vline(x=cp, line_dash="dash", line_color="red")
fig.update_layout(
title="Interactive Change Point Detection",
xaxis_title="Time",
yaxis_title="Value",
hovermode='x unified'
)
fig.show()
Seaborn for Statistical Plots¶
import seaborn as sns
import pandas as pd
# Create DataFrame with segments
segments = []
cps = [0] + result.cp_set.tolist() + [len(data)]
for i in range(len(cps) - 1):
segment_data = data[int(cps[i]):int(cps[i+1])]
segments.extend([i] * len(segment_data))
df = pd.DataFrame({'value': data, 'segment': segments})
# Violin plot by segment
sns.violinplot(data=df, x='segment', y='value')
plt.title('Distribution by Segment')
plt.show()
Next Steps¶
Visualization API - Complete visualization API reference
Evaluation Metrics - Learn about evaluation metrics
Tutorials - Follow step-by-step tutorials