Skip to main content

anyplotlib

codecov Tests

anyplotlib is a fast, interactive plotting library for Jupyter, built on anywidget and a pure-JavaScript canvas renderer. It follows matplotlib's object-oriented API — create a Figure, call methods on Axes — so switching is often a one-line change:

import anyplotlib as apl

fig, ax = apl.subplots(1, 1)        # same shape as plt.subplots(1, 1)
ax.imshow(data)                     # pan, zoom, and inspect — live
fig                                 # display in a Jupyter cell

If you have used matplotlib's OO interface, you already know most of anyplotlib. What you gain is interactivity that stays fast on large data — without a kernel round-trip per frame.

Why another plotting library?

Matplotlib is a superb tool for publication-quality static figures, but its interactive notebook story (ipympl) re-renders the whole figure on the Python side for every frame. anyplotlib makes the opposite trade-off:

  • All rendering happens in the browser. Python serialises compact state (raw image bytes, base64-encoded float arrays) once; pan/zoom/drag never touch the kernel.
  • Each image, line collection, or marker group is a single canvas object, so blitting works and drag interactions run at full frame rate.
  • The scope is deliberately limited. The OO API only (no plt.plot() global state), a curated set of plot types and marker styles, and raster canvas output rather than vector graphics. For print-quality SVG/PDF figures, matplotlib remains the right tool.

Features

  • Plot typesplot (1-D lines with markers, linestyles, legends, log y), imshow (2-D images with colormaps, colorbars, scale bars, overlay masks), pcolormesh (non-uniform 2-D meshes), bar (grouped, horizontal, log, value labels), and 3-D plot_surface / scatter3d / plot3d. 3-D surfaces can be wrapped in an image with set_texture — globes, planets, star charts.
  • Layoutssubplots, matplotlib-compatible GridSpec indexing (slices, spans, negative indices), width_ratios/height_ratios, sharex/sharey linked pan-zoom, and floating inset axes with minimize/maximize.
  • Markers — static overlays (points, circles, ellipses, rectangles, polygons, arrows, line segments, text, h/v lines) with matplotlib-style kwargs and live .set() updates.
  • Widgets — draggable overlays (RectangleWidget, CircleWidget, AnnularWidget, CrosshairWidget, PolygonWidget, VLineWidget, HLineWidget, RangeWidget, …) that report positions back to Python.
  • Events — a two-tier callback system: pointer_move fires every drag frame for cheap updates; pointer_settled / pointer_up fire once for expensive recomputation. Plus key_down, wheel, double_click, and per-line scoped handlers.
  • Interactive docs — the bundled anyplotlib.sphinx_anywidget extension makes any anywidget figure live in Sphinx Gallery pages via Pyodide — no kernel or server needed.
  • Embeddable anywhere — figures don't require Jupyter. Export self-contained HTML (fig.save_html("plot.html")), mount the renderer directly in an Electron app or web page via the JS mount() API, or run a live Python backend over any transport with anyplotlib.embed.FigureBridge (full callback support). See the embedding guide in the docs.
import numpy as np
import anyplotlib as apl

fig, (ax_img, ax_spec) = apl.subplots(1, 2, figsize=(900, 400))
img  = ax_img.imshow(stack.mean(axis=2), cmap="viridis")
spec = ax_spec.plot(stack[64, 64], units="eV")

cross = img.add_widget("crosshair", cx=64, cy=64)

@cross.add_event_handler("pointer_move")   # every drag frame — keep it cheap
def update(event):
    spec.set_data(stack[int(cross.cy), int(cross.cx)])

Installation

pip install anyplotlib

Works anywhere anywidget does: JupyterLab, Jupyter Notebook, VS Code, PyCharm, Google Colab, and marimo. Dependencies are intentionally light: anywidget, numpy, traitlets, and colorcet (no matplotlib required).

Documentation

Full docs, a live example gallery (interactive in the browser — no install), and the event-system guide are at cssfrancis.github.io/anyplotlib.

Development

git clone https://github.com/CSSFrancis/anyplotlib
cd anyplotlib
uv sync                              # install with dev dependencies
uv run playwright install chromium   # browsers for rendering tests
uv run pytest                        # full suite (unit + Playwright + visual)
make html                            # build the docs locally

The architecture is a single anywidget.AnyWidget (Figure) that owns all traitlets; plot objects are plain Python classes that serialise their state dicts to per-panel traits, and figure_esm.js renders them. See AGENTS.md for the codebase guide and anyplotlib/FIGURE_ESM.md for a map of the JS renderer.

License

MIT — see LICENSE.

Release files for anyplotlib 0.8.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 anyplotlib 0.8.0
File Size Uploaded
anyplotlib-0.8.0.tar.gz 1.5 MB Details

Built distribution (wheel)

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

Total release size: 1.9 MB

Release files / anyplotlib-0.8.0.tar.gz

Download URL anyplotlib-0.8.0.tar.gz
Size 1.5 MB
Tags Source
SHA-256 checksum
How to use checksums
de6e538cf7e9a026ddb4ba2975d3f969c25aaab58bb7fd5840457df30a28ede6
BLAKE2b-256 checksum
How to use checksums
919c0a6f744a3119ffcdcae3f5fdd84169381fad4fdca8e6449322a718cb3fef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 25, 2026.

Transparency log

Release files / anyplotlib-0.8.0-py3-none-any.whl

Download URL anyplotlib-0.8.0-py3-none-any.whl
Size 330.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c7fad2f5d203cde5c0dcdc54d7c6ac7dd75335489328380640e7fdc539f7b9b
BLAKE2b-256 checksum
How to use checksums
d057c5db02a2ca3c0641d8dbd52a4b4b9014d6ea658d868cdd517d8109d540c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 25, 2026.

Transparency log

Release history Release notifications | RSS feed

0.10.1

2 release files

0.10.0

2 release files

0.9.0

2 release files

This release

0.8.0 This release

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

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