Skip to main content

PlotSmith for ML models

Project description

PlotSmith

PyPI version Python 3.12+ License: MIT Tests 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: Time series, scatter plots, histograms, bar charts, heatmaps, residuals, and more
  • 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() - SignalPlot-style 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)     # SignalPlot-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+
  • matplotlib >= 3.5.0
  • numpy >= 1.20.0
  • pandas >= 1.3.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}
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

plotsmith-0.1.5.tar.gz (25.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

plotsmith-0.1.5-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file plotsmith-0.1.5.tar.gz.

File metadata

  • Download URL: plotsmith-0.1.5.tar.gz
  • Upload date:
  • Size: 25.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for plotsmith-0.1.5.tar.gz
Algorithm Hash digest
SHA256 5854c45b26dbfb48477d75186551a0c1ed03b81e9b1d5d4e369a4d3024fdabf2
MD5 37e475967fee1bf8d0efd890cd7ad35b
BLAKE2b-256 f3c3f9119f4a3f13f2ce6f6d668354318297888388a7e18f33959a083e99dd6d

See more details on using hashes here.

Provenance

The following attestation bundles were made for plotsmith-0.1.5.tar.gz:

Publisher: release.yml on kylejones200/plotsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file plotsmith-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: plotsmith-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 22.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for plotsmith-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 872bfb1618180083fab2348affcd8b304ac78b07ec37fd762f72e58090c612c0
MD5 dc620cb365cb7c01cd91e7aacba1cc3d
BLAKE2b-256 917b0c8455a84a0695fc8bfab8c459ab40e344f6d5688456f9edc7f2e8e422ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for plotsmith-0.1.5-py3-none-any.whl:

Publisher: release.yml on kylejones200/plotsmith

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page