Skip to content

digiLab-ai/digiPlot

Repository files navigation

digiPlot

Coverage

digiPlot is a typed Matplotlib plotting library for the digiLab ecosystem. It is built around a simple idea: keep rendering predictable and composable, and build higher-level semantic plots from a small set of reusable primitives.

What it provides

  • typed plot configuration with Pydantic
  • consistent styling across plot types
  • primitive plot functions for direct rendering
  • composed plot functions built from those primitives
  • figure creation or drawing onto existing Axes
  • schema export for frontend or node-driven configuration

Plot layers

Primitive plots are the reusable building blocks. Composed plots are the next layer up and combine primitives into more semantic diagnostics.

flowchart TD
    A["Primitive plots"] --> B["Histogram"]
    A --> C["Scatter"]
    A --> D["Line"]
    A --> E["Bar"]
    A --> F["Box"]
    A --> G["Heat map"]

    H["Composed plots"] --> I["Observed vs predicted"]
    H --> J["Residuals vs fitted"]
    H --> K["Posterior predictive intervals"]
    H --> L["Calibration curve"]
    H --> M["Coverage plot"]
    H --> N["Uncertainty vs error"]
    H --> O["QQ plot"]
    H --> P["Parity plot"]
    H --> Q["Standardised residual plot"]
    H --> R["Active learning progress"]
    H --> S["Forecasting back-test"]

    I --> C
    I --> D
    J --> C
    J --> D
    K --> D
    K --> C
    L --> D
    L --> C
    M --> D
    N --> C
    N --> D
    O --> C
    P --> C
    P --> D
    Q --> C
    Q --> D
    Q --> B
    R --> D
    S --> D
    S --> C
Loading

Available plots

Primitive plots

  • create_histogram_plot / draw_histogram_plot
  • create_scatter_plot / draw_scatter_plot
  • create_line_plot / draw_line_plot
  • create_bar_plot / draw_bar_plot
  • create_box_plot / draw_box_plot
  • create_heat_map / draw_heat_map

Composed plots

  • create_observed_vs_predicted_plot / draw_observed_vs_predicted_plot
  • create_residuals_vs_fitted_plot / draw_residuals_vs_fitted_plot
  • create_posterior_predictive_interval_plot / draw_posterior_predictive_interval_plot
  • create_calibration_curve_plot / draw_calibration_curve_plot
  • create_coverage_plot / draw_coverage_plot
  • create_uncertainty_vs_error_plot / draw_uncertainty_vs_error_plot
  • create_active_learning_progress_plot / draw_active_learning_progress_plot
  • create_forecasting_backtest_plot / draw_forecasting_backtest_plot
  • create_qq_plot / draw_qq_plot
  • draw_parity_plot
  • create_standardised_residual_plot / draw_standardised_residual_plot

Configuration models

Each plot is configured with a dedicated Pydantic model:

  • HistogramPlotConfig
  • ScatterPlotConfig
  • LinePlotConfig
  • BarPlotConfig
  • BoxPlotConfig
  • HeatMapPlotConfig
  • ObservedVsPredictedPlotConfig
  • ResidualsVsFittedPlotConfig
  • PosteriorPredictiveIntervalPlotConfig
  • CalibrationCurvePlotConfig
  • CoveragePlotConfig
  • UncertaintyErrorPlotConfig
  • ActiveLearningProgressPlotConfig
  • ForecastingBacktestPlotConfig
  • QQPlotConfig
  • ParityPlotConfig
  • StandardisedResidualPlotConfig

All config models inherit from PlotConfigBase, which exposes a schema payload:

from digiplot.configs.scatter import ScatterPlotConfig

payload = ScatterPlotConfig.get_schema_payload()

That payload includes:

  • the config class name
  • the generated JSON schema
  • the default values

Installation

From PyPI

python -m pip install digiplot-digilab

Import it as:

import digiplot

Local development

pyenv local 3.11.15
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .

Install release tooling when you need to package or publish:

python -m pip install -e '.[release]'

Publishing

  1. Create a PyPI project for digiplot-digilab.
  2. Install release tooling with python -m pip install -e '.[release]'.
  3. Run ./scripts/release_check.sh.
  4. Trigger the Publish GitHub Actions workflow for TestPyPI.
  5. Verify the TestPyPI install with ./scripts/release_smoke_test.sh testpypi ==0.2.0.
  6. Tag a release like v0.2.0 and publish to PyPI.
  7. Verify the public install with ./scripts/release_smoke_test.sh pypi ==0.2.0.

The published package name is digiplot-digilab, but the Python import remains digiplot.

For the full release checklist, see RELEASING.md.

Notebook support in VS Code

python -m pip install jupyter ipykernel
python -m ipykernel install --user --name=digiplot --display-name="Python (.venv) digiPlot"

Quick start

Primitive plot example

import numpy as np

from digiplot.configs.scatter import ScatterPlotConfig
from digiplot.plots.scatter import create_scatter_plot

x = np.linspace(0.0, 10.0, 200)
y = 0.8 * x + np.random.normal(scale=1.0, size=200)

fig = create_scatter_plot(
    x,
    y,
    config=ScatterPlotConfig(
        title="Scatter Example",
        xlabel="Input",
        ylabel="Response",
    ),
)

Composed plot example

import numpy as np

from digiplot.configs.composed.residual import StandardisedResidualPlotConfig
from digiplot.plots.composed.residual import create_standardised_residual_plot

y_true = np.array([1.0, 2.0, 3.0, 4.0])
predictions = np.array([0.9, 2.1, 3.2, 3.8])
uncertainties = np.array([0.2, 0.2, 0.3, 0.25])

fig = create_standardised_residual_plot(
    y_true,
    predictions,
    uncertainties,
    config=StandardisedResidualPlotConfig(
        plot_type="scatter",
        title="Residual Diagnostics",
    ),
)

Composition model

Every plot follows one of two entry points:

  • create_*: create a new figure if no ax is supplied
  • draw_*: render directly onto an existing Axes

That makes it easy to build multi-panel figures:

import matplotlib.pyplot as plt
import numpy as np

from digiplot.configs.histogram import HistogramPlotConfig
from digiplot.configs.scatter import ScatterPlotConfig
from digiplot.plots.histogram import create_histogram_plot
from digiplot.plots.scatter import create_scatter_plot

values = np.random.normal(size=400)
x = np.linspace(0, 10, 120)
y = x + np.random.normal(scale=1.0, size=120)

fig, axes = plt.subplots(1, 2, figsize=(12, 4))

create_histogram_plot(
    values,
    config=HistogramPlotConfig(title="Distribution"),
    ax=axes[0],
)

create_scatter_plot(
    x,
    y,
    config=ScatterPlotConfig(title="Relationship"),
    ax=axes[1],
)

fig.tight_layout()

Package layout

digiplot/
  configs/
  plots/
    composed/
  styles/
  utils/
tests/
scripts/
coverage/
  • configs/: typed configuration models
  • plots/: primitive plotting functions
  • plots/composed/: higher-level plots built from primitives
  • styles/: palette and shared axes/title styling
  • utils/: general utilities
  • tests/: unit test suite
  • scripts/: project utilities such as coverage generation
  • coverage/: generated badge and coverage summaries

Testing and coverage

Run the full test suite:

MPLCONFIGDIR=/tmp/matplotlib python -m unittest discover -s tests -v

Generate the repository coverage outputs:

python scripts/generate_coverage_report.py

This writes:

  • coverage/badge.svg
  • coverage/summary.md
  • coverage/summary.json

Documentation site

Build the repo-native documentation website:

python scripts/build_docs.py

The editable source pages live in:

  • docs/content/plots/
  • docs/content/configs/
  • docs/assets/style.css

The generated site entry point is:

  • docs/index.html

Release checklist

Current package version: 0.2.0

Before publishing to PyPI:

  1. Verify the project URLs in pyproject.toml match the real public repository.
  2. Install release tooling in the active environment.
  3. Run the local release check script.
  4. Upload to TestPyPI first if this is the first public release.
  5. Upload to PyPI once the package metadata and install flow look correct.

Typical commands:

python -m pip install -e '.[release]'
./scripts/release_check.sh
.venv/bin/python -m twine upload --repository testpypi dist/*
.venv/bin/python -m twine upload dist/*

./scripts/release_check.sh runs the unit tests, rebuilds build/ and dist/, then validates the generated artifacts with twine check.

Roadmap

Near-term

  • strengthen the currently implemented primitive and composed plot set
  • refine the documentation site and generated examples
  • keep semantic plots thin and built on shared primitives
  • define the remaining PML requests that still need plot semantics agreed

PML plot requests

Additional plot requests from the PML team look feasible within the current architecture when they can be expressed as:

  • a new primitive plot
  • a composed plot built from scatter, line, histogram, or heat map
  • a domain-specific wrapper with a dedicated config model

The current PML request list is:

Core fit plots

  • observed vs predicted
  • residuals vs fitted
  • posterior predictive intervals
  • parity plot

Assurance plots

  • calibration curve
  • coverage plot
  • uncertainty vs error plot
  • support or out-of-sample score plot
  • drift comparison plot

Workflow plots

  • acquisition function plot
  • active learning progress plot
  • forecasting back-test plot

Feasibility against the current architecture

Straightforward next additions:

  • support or out-of-sample score plot: feasible, but the exact semantics need defining first
  • drift comparison plot: feasible, but depends on whether this should be histogram-based, density-based, or matrix-based
  • acquisition function plot: feasible, but shape depends on the acquisition strategy and whether the output is 1D, 2D, or batch-oriented

Already implemented:

  • observed vs predicted
  • residuals vs fitted
  • posterior predictive intervals
  • calibration curve
  • coverage plot
  • uncertainty vs error plot
  • active learning progress plot
  • forecasting back-test
  • parity plot: already implemented

This makes the roadmap a good fit for the existing primitive/composed layering. Most of the requested items look like composed diagnostics rather than entirely new low-level primitives.

Design notes

  • plotting is rendering-only; analysis should live elsewhere
  • composed plots should stay thin and build on primitives
  • config fields defaulting to None are treated as optional overrides
  • plots should avoid overwriting existing axes state unless explicitly asked

Current status

The package currently has:

  • a tested primitive plotting layer
  • a tested composed plotting layer
  • generated repository coverage reporting

The coverage summary lives in coverage/summary.md.

About

a lightweight plotting library for the digiLab ecosystem

Resources

Stars

Watchers

Forks