Skip to main content

pypgfplots

Open in molab

Minimal Python wrapper that renders pgfplots figures as high-quality PNG inside marimo notebooks. Figures are identical to what you would include in a LaTeX paper or slide deck — because they are LaTeX.

Requires a working LaTeX installation with pdflatex on $PATH, plus a PDF→PNG converter — install one of:

brew install poppler       # provides pdftoppm (recommended)
brew install mupdf-tools   # provides mutool
brew install imagemagick   # provides convert

Ghostscript (gs) is also accepted if already on $PATH.


Installation

uv add git+https://github.com/bjoseru/pypgfplots

Inside a marimo notebook

Add a cell at the top:

import subprocess
subprocess.run(["uv", "pip", "install", "git+https://github.com/bjoseru/pypgfplots"])

Or use marimo's package manager sidebar (requires uv backend).

Plain pip

pip install git+https://github.com/bjoseru/pypgfplots

Quick start

from pypgfplots import Axis

a = Axis(title="Parabola", xlabel=r"$x$", ylabel=r"$f(x)$")
a.addplot(r"x^2", color="red", domain="-2:2", samples=100)
a  # displays as PNG in marimo

Combine two axes side by side:

a = Axis(title="Left")
a.addplot(r"sin(deg(x))", domain="0:6.28")

b = Axis(title="Right", axis_lines="left")
b.addplot(r"cos(deg(x))", domain="0:6.28")

a + b  # renders both in one tikzpicture

Raw TikZ statements

tikz(line) appends a verbatim TikZ statement to the environment body — available on TikzPicture, Axis, and Groupplot. On Axis/Groupplot the statement lands inside the axis environment, so pgfplots coordinate systems such as (axis cs:…) work as expected.

Pure geometric drawing with TikzPicture:

from pypgfplots import TikzPicture

p = TikzPicture()
p.tikz(r"\fill[red]    (0,0) rectangle (2,2);")          # Bauhaus square
p.tikz(r"\fill[blue]   (3,1) circle (1);")               # Bauhaus disc
p.tikz(r"\fill[yellow] (5,0) -- (7,0) -- (6,1.732) -- cycle;")  # Bauhaus triangle
p

Annotating a plot with a dashed reference line and a label:

a = Axis(xlabel=r"$x$", ylabel=r"$f(x)$")
a.addplot(r"x^2", domain="-2:2", color="blue")
a.tikz(r"\draw[dashed, gray] (axis cs:-2,1) -- (axis cs:2,1);")
a.tikz(r"\node[right] at (axis cs:2,1) {$y=1$};")
a

Coordinate data

coords = " ".join(f"({x},{x**2})" for x in range(6))
a = Axis()
a.addplot(coords, _type="coordinates", mark="*", color="blue")
a

Table data

a = Axis()
a.addplot("data.csv", _type="table", col_sep="comma", x="time", y="value")
a

3-D plots

a = Axis()
a.addplot3(r"x^2 + y^2", domain="-2:2", samples=30)
a

Grouped subplots

Groupplot produces a pgfplots groupplot environment. Call nextgroupplot() before each subplot; all addplot*, addlegendentry, and legend methods work exactly as on Axis.

from pypgfplots import Groupplot

gp = Groupplot(group_style="{columns=2, rows=1}", width="0.45\\textwidth")
gp.nextgroupplot(title="Sine")
gp.addplot(r"sin(deg(x))", domain="0:6.28", color="blue")
gp.addlegendentry("sin")

gp.nextgroupplot(title="Cosine")
gp.addplot(r"cos(deg(x))", domain="0:6.28", color="red")
gp.addlegendentry("cos")

gp  # displays as PNG in marimo

Options passed to Groupplot(...) become \begin{groupplot}[...] options; options passed to nextgroupplot(...) become per-subplot options. The \usepgfplotslibrary{groupplots} line is added to the preamble automatically.

Note on nested key-value options: pgfplots options whose values are themselves key-value lists (such as group style) must be wrapped in braces so the comma is not interpreted as an option separator: group_style="{columns=2, rows=1}". The same applies to any option like legend style, axis background/.style, etc.

Legend images

addlegendimage inserts a phantom legend entry with a custom appearance — useful when the auto-generated swatch does not match what you want:

a = Axis()
a.addplot(r"x^2", color="red")
a.addlegendimage(color="red", mark="*")
a.addlegendentry(r"$x^2$")
a

Global settings

from pypgfplots import pgfplotset, preamble, classoptions

pgfplotset(compat="1.18")
preamble(r"\usepackage{amsmath}")
classoptions("border=5pt")

Export

a.save_pdf("figure.pdf")   # compile and write PDF
a.save_tex("figure.tex")   # write LaTeX source (no compilation)
src = a.latex()             # full standalone source as string
log = a.compile_log()       # pdflatex output of last run

Development

Clone the repo and install in editable mode:

git clone https://github.com/bjoseru/pypgfplots
cd pypgfplots
uv pip install -e .

Run the tests:

uv run --with pytest pytest

Tests that require pdflatex and a PDF→PNG converter are skipped automatically if those tools are not on $PATH. To run only the pure-Python unit tests:

uv run --with pytest pytest tests/test_core.py tests/test_options.py

Pipeline

Display:  Python API  →  .tex  →  pdflatex  →  PDF  →  pdftoppm  →  PNG  →  marimo
PDF:      Python API  →  .tex  →  pdflatex  →  PDF

The PNG is delivered via _repr_html_() and is therefore also usable in Jupyter.


License

MIT — see LICENSE.

Metadata

Release files for pypgfplots 0.2.2

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

Source distribution (sdist)

Source distribution for pypgfplots 0.2.2
File Size Uploaded
pypgfplots-0.2.2.tar.gz 14.5 kB Details

Built distribution (wheel)

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

Total release size: 25.1 kB

Release files / pypgfplots-0.2.2.tar.gz

Download URL pypgfplots-0.2.2.tar.gz
Size 14.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6b742b6059428bfc07df05eadd718d6c1647ce0d2724dfab23656197a79d747c
BLAKE2b-256 checksum
How to use checksums
9b5e48acb27142c21e34b8ae3106c802a54f171192a00998b2a5135a88b0c229
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 22, 2026.

Transparency log

Release files / pypgfplots-0.2.2-py3-none-any.whl

Download URL pypgfplots-0.2.2-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
15ea92f77ea3d620ace694fecdfbc5248e3932517eb399c98300cfe3cda8af47
BLAKE2b-256 checksum
How to use checksums
1babda0fa95b971ba020a3b50d8d79f990e9c1c86a4677e1cb0129dd882f4c5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.9

2 release files

0.1.8

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