Standard Plot
A standardized wrapper around matplotlib targeting a variety of canvases.
Installation
Default installation is via pip:
pip install stdplot
For notebook and GUI support, install the optional dependencies:
pip install stdplot[notebook,qt] # or [all]
The qt extra installs PySide6 for convenience only: any Qt binding matplotlib supports (PyQt6, PyQt5,
PySide2) works as well. Qt is imported only when a window opens, never by import stdplot.
Usage
Quickstart
import numpy as np
import stdplot
time = np.linspace(0.0, 10.0, 500)
displacement = np.exp(-0.3 * time) * np.cos(2.0 * np.pi * 0.8 * time)
with stdplot.figure("damped_oscillation") as (fig, ax):
ax.plot(time, displacement)
ax.set_xlabel(r"Time $t$ [s]")
ax.set_ylabel(r"Displacement $x$ [mm]")
stdplot.figure opens a figure styled with the scienceplots science, grid and ieee styles and yields a
plain matplotlib Figure and Axes. When the block exits, the figure is shown: inline in a Jupyter kernel, in a
Qt window from a script, and nowhere when matplotlib's backend cannot open windows (MPLBACKEND=Agg). Without
LaTeX, text is rendered with matplotlib's mathtext instead, after a single warning.
Four objects cover the rest:
Configsays what: the style, the size figures are drawn at, thetargetswritten when saving, theoutput_dir, the inlinepreview, the layout engine and the display.Targetis one file: a format, an optional size (none means "the size the figure was drawn at"), a dpi and its margins (Bbox.TIGHTby default).Plottersays how: it binds aConfigto whether figures are saved and shown.stdplot.figureandstdplot.plotare the methods of a defaultPlotter, which saves nothing.AxesGridis what the block receives instead of anAxesas soon asnrowsorncolsis given.
Runnable versions of the recipes below are in examples/.
Figure size
with stdplot.figure("training_loss", size=(6, 4)) as (fig, ax):
...
Config(size=stdplot.Size(6, 4)) sets it for every figure. Targets without a size, such as SCREEN, are
written at the size the figure was drawn at.
Saving SVG only
config = stdplot.Config(targets=(stdplot.SCREEN,), output_dir="figures")
with stdplot.Plotter(config).figure("training_loss", save=True) as (fig, ax):
...
for path in config.paths("training_loss"): # the files saving writes
print(path) # figures/training_loss.svg
The default targets include an IEEE PGF, which needs LaTeX; SCREEN alone saves everywhere.
Notebook vs script: one switch for saving
SAVE = False # flip once to write every figure of the notebook
PLOTS = stdplot.Plotter(stdplot.Config(targets=(stdplot.SCREEN,), output_dir="figures"), save=SAVE)
with PLOTS.figure("training_loss", size=(6, 4)) as (fig, ax):
...
with PLOTS.figure("scratch", save=False) as (fig, ax): # a call overrides the Plotter
...
In a notebook, figures appear below their cell. In a script, each figure opens a Qt window that blocks until it is
closed; run the script under MPLBACKEND=Agg (or call matplotlib.use("Agg") first) and it never blocks. To
never show anything, use stdplot.Plotter(config, show=False) or Config(display=stdplot.Display.NONE).
PGF for LaTeX
paper = stdplot.Config(targets=(stdplot.IEEE_PGF, stdplot.SCREEN), output_dir="figures")
# 6.33589 in is the \textwidth of the thesis.
thesis = stdplot.Config(targets=(stdplot.pgf(6.33589),), output_dir="figures")
IEEE_PGF is one IEEE column wide, ieee_pgf(scale=0.5) half of one, and pgf(width, aspect) any width. They
keep standard margins (Bbox.STANDARD), so the PGF is exactly as wide as asked; include it with
\input{figures/name.pgf}. Saving a PGF needs the configured TeX system (pdflatex by default) on the PATH:
without it, LatexNotFoundError is raised before your drawing code runs.
Subplot options
with stdplot.figure("signals", nrows=2, ncols=2, sharex=True) as (fig, axes):
axes[0, 1].plot(...) # by row and column
image = axes[3].imshow(...) # the 4th axes, counted row by row
for ax in axes:
ax.set_xlabel("Time [s]")
fig.colorbar(image, ax=axes) # an AxesGrid goes wherever matplotlib takes several axes
sharex, sharey, width_ratios, height_ratios, subplot_kw and gridspec_kw are forwarded to matplotlib's
Figure.subplots. A 3D axes is still typed Axes; cast it to reach the 3D methods:
import typing
from mpl_toolkits.mplot3d import Axes3D
with stdplot.figure("saddle_point", subplot_kw={"projection": "3d"}) as (fig, ax):
typing.cast(Axes3D, ax).plot_surface(x, y, z)
Two styles for the same figure
The style applies while the figure is drawn, because matplotlib reads fonts and text.usetex when each artist is
created. One drawn figure therefore cannot be written under two styles: draw it once per config.
latex = stdplot.Config(targets=(stdplot.pgf(6.33589),), output_dir="figures")
plain = stdplot.Config(
style=stdplot.Style().without_latex(),
targets=(stdplot.Target(stdplot.Format.PNG, dpi=300),),
output_dir="figures",
)
for config in (latex, plain):
with stdplot.Plotter(config, save=True, show=False).figure("umap") as (fig, ax):
draw_umap(ax)
Disclaimer
This repository originated from a personal script I've developped on my own. Now it is rewriten heavily using Claude based on that previous work. It is mostly a project use by me as introduction and exploration of the capabilities of such tools in my workflow.
Metadata
Release files for stdplot 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| stdplot-0.1.0.tar.gz | 19.9 kB | With provenance | Details for stdplot-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| stdplot-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for stdplot-0.1.0-py3-none-any.whl |
Total release size: 42.9 kB
Release files / stdplot-0.1.0.tar.gz
| Download URL | stdplot-0.1.0.tar.gz |
|---|---|
| Size | 19.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b3df5a3a0a1f15b62b1f4af527174d7d6cb2ee6e9cc6cc15d825a50ba392005e
|
|
BLAKE2b-256 checksum How to use checksums |
8660955b10ab4a3ac8324b286047b70b7f61a004e9134d9d036666397d9efc16
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 28, 2026.
Transparency logRelease files / stdplot-0.1.0-py3-none-any.whl
| Download URL | stdplot-0.1.0-py3-none-any.whl |
|---|---|
| Size | 23.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
acb4a06b67059762ca50cd0a6c57ff6f5843f15fb349e8b77fee07956f54fcb3
|
|
BLAKE2b-256 checksum How to use checksums |
f75104a58f595034e5deea09df44cef81cbc5faab408a149e27c75519ac99475
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 28, 2026.
Transparency logSecurity for stdplot 0.1.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
Both files in this release have been uploaded with provenance metadata.
Attestation for stdplot-0.1.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 Oct 28, 2026.
Transparency logA 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.