Skip to main content

PlotSmith

PyPI version Python 3.12+ License: MIT CI Documentation Code style: black

PlotSmith is a layered plotting library for ML models with strict architectural boundaries. It provides clean, minimalist visualizations following best practices for analytical figures.

Features

  • 4-Layer Architecture: Strict separation of concerns with clear boundaries
  • Minimalist Styling: Clean, publication-ready plots with serif fonts and minimal clutter
  • Type-Safe: Full type hints and immutable data structures
  • Comprehensive Chart Types:
    • Time Series: Time series plots with confidence bands
    • Statistical: Histograms, box plots, violin plots, scatter plots
    • Categorical: Bar charts, lollipop charts, dumbbell charts, range charts
    • Specialized: Waterfall charts, waffle charts, slope charts, metric displays
    • ML Analysis: Residual plots, backtest visualization, model comparison, forecast comparison
    • Correlation: Correlation heatmaps
  • ML-Focused: Built for model evaluation, backtesting, and analysis workflows

Installation

pip install plotsmith

Quick Start

import pandas as pd
import numpy as np
from plotsmith import plot_timeseries, plot_residuals, plot_heatmap

# Time series with confidence bands
data = pd.Series([1, 2, 3, 4, 5], index=pd.date_range('2020-01-01', periods=5))
lower = data - 0.5
upper = data + 0.5
fig, ax = plot_timeseries(
    data,
    bands={'95% CI': (lower, upper)},
    title='Time Series with Confidence Bands'
)

# Residual analysis
actual = np.array([1, 2, 3, 4, 5])
predicted = np.array([1.1, 2.2, 2.9, 4.1, 4.8])
fig, ax = plot_residuals(actual, predicted, plot_type='scatter')

# Correlation heatmap
corr_matrix = df.corr()
fig, ax = plot_heatmap(corr_matrix, annotate=True, cmap='RdYlGn')

Architecture

PlotSmith follows a strict 4-layer architecture with clear boundaries:

Layer 1: Objects (plotsmith.objects)

Immutable dataclasses representing plot-ready data. No matplotlib imports.

  • SeriesView - Time series data
  • BandView - Confidence bands
  • ScatterView - Scatter plot data
  • HistogramView - Histogram data
  • BarView - Bar chart data
  • HeatmapView - 2D heatmap data
  • FigureSpec - Figure styling specification

Layer 2: Primitives (plotsmith.primitives)

Drawing functions that accept only Layer 1 objects. All matplotlib calls here.

  • draw_series(), draw_scatter(), draw_histogram(), draw_bar(), draw_heatmap()
  • minimal_axes() - Minimalist axes styling
  • tidy_axes() - Minimalist axes cleanup
  • style_line_plot(), style_scatter_plot(), style_bar_plot()
  • event_line(), direct_label(), note(), accent_point()

Layer 3: Tasks (plotsmith.tasks)

Translate user intent into Layer 1 objects. Can import pandas/numpy, not matplotlib.

  • TimeseriesPlotTask - Convert Series/DataFrame to views
  • BacktestPlotTask - Convert results table to scatter views
  • HistogramPlotTask - Convert data to histogram views
  • BarPlotTask - Convert data to bar views
  • HeatmapPlotTask - Convert 2D data to heatmap views
  • ResidualsPlotTask - Convert actual/predicted to residual views

Layer 4: Workflows (plotsmith.workflows)

Public API entry points. Orchestrate tasks → primitives → save/show.

  • plot_timeseries() - Time series plotting
  • plot_backtest() - Backtest results visualization
  • plot_histogram() - Histogram plotting (supports overlaid)
  • plot_bar() - Bar chart plotting
  • plot_heatmap() - Heatmap/correlation matrix plotting
  • plot_residuals() - Residual analysis plots
  • plot_model_comparison() - Compare multiple model predictions
  • figure() - Create styled figure
  • small_multiples() - Create grid of small-multiple axes

Workflows

Time Series Plotting

from plotsmith import plot_timeseries
import pandas as pd

# Single series
data = pd.Series([1, 2, 3, 4, 5], index=pd.date_range('2020-01-01', periods=5))
fig, ax = plot_timeseries(data, title='My Time Series')

# Multiple series (DataFrame)
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, 
                  index=pd.date_range('2020-01-01', periods=3))
fig, ax = plot_timeseries(df)

# With confidence bands
bands = {'CI': (lower_series, upper_series)}
fig, ax = plot_timeseries(data, bands=bands, save_path='output.png')

Residual Analysis

from plotsmith import plot_residuals

# Scatter plot (predicted vs actual)
fig, ax = plot_residuals(actual, predicted, plot_type='scatter', add_perfect_line=True)

# Time series (residuals over time)
fig, ax = plot_residuals(actual, predicted, x=dates, plot_type='series')

Model Comparison

from plotsmith import plot_model_comparison

models = {
    'LSTM': lstm_predictions,
    'XGBoost': xgb_predictions,
    'SARIMA': sarima_predictions
}
fig, ax = plot_model_comparison(
    actual_data,
    models,
    test_start_idx=100,  # Optional: mark test period start
    title='Model Comparison'
)

Heatmaps

from plotsmith import plot_heatmap
import pandas as pd

# Correlation matrix
corr = df.corr()
fig, ax = plot_heatmap(
    corr,
    annotate=True,
    fmt='.2f',
    cmap='RdYlGn',
    vmin=-1,
    vmax=1
)

# Any 2D array
data = np.random.rand(10, 10)
fig, ax = plot_heatmap(data, title='Custom Heatmap')

Histograms

from plotsmith import plot_histogram

# Single histogram
fig, ax = plot_histogram(data, bins=30, title='Distribution')

# Overlaid histograms
fig, ax = plot_histogram(
    [normal_data, anomaly_data],
    labels=['Normal', 'Anomalies'],
    colors=['blue', 'red'],
    alpha=0.7
)

Bar Charts

from plotsmith import plot_bar

categories = ['A', 'B', 'C', 'D']
values = [10, 20, 15, 25]
fig, ax = plot_bar(
    categories,
    values,
    force_zero=True,  # Honest scale
    title='Bar Chart'
)

Backtest Results

from plotsmith import plot_backtest

results = pd.DataFrame({
    'y_true': [1, 2, 3, 4, 5],
    'y_pred': [1.1, 2.2, 2.9, 4.1, 4.8],
    'fold_id': [0, 0, 1, 1, 2]
})
fig, ax = plot_backtest(results, fold_id_col='fold_id')

Styling Helpers

PlotSmith provides minimalist styling by default and includes helpers for customization:

from plotsmith import minimal_axes, tidy_axes, event_line, direct_label, ACCENT

fig, ax = plt.subplots()
minimal_axes(ax)  # Minimalist styling (serif font, clean spines)
# or
tidy_axes(ax)     # Minimalist style (gray spines, clean ticks)

# Add event markers
event_line(ax, x=2020, text='Policy Change', color=ACCENT)

# Direct labels
direct_label(ax, x=5, y=10, text='Peak', use_accent=True)

Examples

See examples/basic_timeseries.py for a complete example:

python examples/basic_timeseries.py

This generates examples/out/basic_timeseries.png with a time series plot including confidence bands.

Architecture Principles

  1. Strict Boundaries: Each layer can only import from layers below it
  2. Immutable Data: All view objects are frozen dataclasses
  3. Validation: Shape and alignment checks before drawing
  4. Separation of Concerns: Data representation (Layer 1) is separate from drawing (Layer 2)
  5. Type Safety: Full type hints throughout

Requirements

  • Python 3.12+ (only)
  • matplotlib >= 3.5.0, < 4.0.0
  • numpy >= 1.20.0, < 3.0.0
  • pandas >= 1.3.0, < 3.0.0

Development

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=plotsmith --cov-report=html

License

MIT License - see LICENSE file for details.

Contributing

See CONTRIBUTING.md for guidelines.

Citation

If you use PlotSmith in your research, please cite:

@software{plotsmith,
  title={PlotSmith: A Layered Plotting Library for ML Models},
  author={Jones, Kyle T.},
  year={2025},
  url={https://github.com/kylejones200/plotsmith}
}

Metadata

Release files for plotsmith 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for plotsmith 0.2.0
File Size Uploaded Provenance Actions
plotsmith-0.2.0.tar.gz 48.3 kB With provenance Details for plotsmith-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for plotsmith 0.2.0
File Interpreter ABI Platform Actions
plotsmith-0.2.0-py3-none-any.whl Python 3 none any Details for plotsmith-0.2.0-py3-none-any.whl

Total release size: 86.2 kB

Release files / plotsmith-0.2.0.tar.gz

Download URL plotsmith-0.2.0.tar.gz
Size 48.3 kB
Tags Source
SHA-256 checksum
How to use checksums
1536fae23bacca23eaa044d5675899faa503c06fa6c45bff65024a2e75de0b44
BLAKE2b-256 checksum
How to use checksums
2b5c7954638ab515c3d520dc94b1e19d263a8142f4b3a50bbe8b9e738123e310
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 12, 2026.

Transparency log

Release files / plotsmith-0.2.0-py3-none-any.whl

Download URL plotsmith-0.2.0-py3-none-any.whl
Size 37.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a8ef80d771b9cc68b81b26b0820dd0c8b9720e36152f09cc7bbf8c9250fa6f81
BLAKE2b-256 checksum
How to use checksums
1eee57cfac67126e2b3991fba7505d835a3413d953d422c1b41d60d0b618bf56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 12, 2026.

Transparency log

Security for plotsmith 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for plotsmith-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page