Skip to main content

Fig Foundry

Fig Foundry

A WYSIWYG figure studio for matplotlib.
Drag your data onto a free canvas, compose publication figures, and export the exact Python that draws them. The preview is the generated code, executed — so what you see is what the .py produces.

PyPI version License: MIT Python 3.10 and newer Runs on Windows, macOS and Linux

Install · Tour · Measured · How it works · Command line

The canvas: a nine-panel autocorrelation figure composed from the signals of one dataset, with the signal library on the left and a per-plot inspector on the right.

A nine-panel figure composed on the canvas from one dataset's signals. Every panel is a real matplotlib Axes placed by explicit coordinates, so it can sit anywhere, at any size.

You have the data; Fig Foundry is the table you lay it out on. Load a dataset, drag a signal onto the canvas and it becomes a plot. Move and resize plots with snapping, nudge and style each one in the inspector, add the second series or the σ-band, and when it is right, export the code. Because the preview is rendered by running that very code, there is no "close enough" — the figure you arrange and the script you ship are the same drawing.

WYSIWYG by construction
One drawing path. The browser preview executes the generated .py, so the export is byte-for-byte what you see. There is no second renderer to drift.
The atom is data
A figure is a scene of plots over named signals. Drag a signal to make a plot; drop it on one to overlay a line, a σ-band, or error bars. Nothing is hand-drawn.
Twenty-three plot types
Line, step, scatter, grouped scatter, bar, box, violin, histograms, hexbin, image, contour, pcolormesh, vector fields, streamplot, decision boundary, pie, polar, and three 3-D types.
Private, on your machine
A local web app. Your datasets, figures and exports live in ~/.figfoundry; nothing you load is sent anywhere. Pickle files load through a whitelist, not a deserializer.

A quick tour

The same nine-panel figure with the interface in dark mode: dark chrome around a white artboard.

Light, dark, or your system's. The interface re-skins; the figure itself stays on a white artboard, so the artwork is publication-clean in either theme.

The 3-D viewfinder: a surface plot with elevation, azimuth and zoom controls, and invert toggles for rotate and zoom.

3-D, to your angle. Double-click a 3-D plot to open the viewfinder: drag to rotate, scroll to zoom, or use the sliders. Accept writes the camera back to the figure and, with it, into the exported code.

The export dialog: the generated Python, with PNG, SVG and PDF figure buttons and a download.

Export the code and the figure. The standalone .py, plus the figure as PNG, SVG or PDF — SVG and PDF are vector, for the paper.

The picker: a New figure card and your saved figures, each with a live thumbnail.

Your figures. Every canvas is saved with a live thumbnail; open, duplicate or delete from here. Each one is tied to the dataset it was built from.

Measured, not claimed

Every figure below is reproducible from the repository: the test suite, the CI runs, and the security probes.

Plot types, each verified preview-identical to its export 23 of 23 (tests)
Tests, passing on Linux and Windows, Python 3.10 and 3.12 152 (CI)
Malicious pickle payloads the whitelist refuses to load 18, including np.fromfile, np.load, __import__, eval, exec (tests)
Separate renderers the export can drift from 0 — the preview executes the export

What it does

  • Composes on a free canvas. Plots are explicit rectangles, not a fixed grid, so they go anywhere and at any size. Move, resize with snapping, nudge with the arrow keys, and multi-select (Shift+click) to move, nudge or delete a group at once.
  • Twenty-three plot types. Line, step, scatter, grouped scatter (color-by-class), bar and horizontal bar, histogram, box plot, violin plot, 2-D histogram, hexbin, image, contour (filled and lines), pcolormesh, vector field, streamplot, decision boundary (a surface with the points on top), pie, polar, 3-D scatter, 3-D surface and 3-D wireframe.
  • Styles every element. Per plot: the data, plot type, color, line and marker, σ-band and error bars, ticks and tick labels, limits and scale, spines, title, colormap and colorbar, and artists — vertical and horizontal lines, text, annotations, arrows, boxes, circles, ellipses, polygons and legends. Figure-level axis labels, legend, suptitle and free text.
  • Suggests accessible color. One click applies the colorblind-safe Okabe–Ito palette to a plot's series; a palette menu (Okabe–Ito, Bright, Viridis, Plasma, Cividis) is available through the API.
  • Speaks LaTeX. Labels, titles and text take mathtext, so $x_0$ and $\alpha$ render.
  • Lays out for you. Arrange in a grid, align and distribute a selection, set margins and gaps, and sync axis ranges across every plot at once.
  • Exports clean code. The figure as a standalone .py that references the dataset, plus the rendered figure as PNG, SVG or PDF. The 3-D camera, the colors, the ticks — all of it is in the code.
  • Remembers your setup. Themes, and the 3-D rotate/zoom direction, persist; figures, datasets and exports live in ~/.figfoundry.

How it works

flowchart LR
    data(["Your data<br/>.npz / .pkl / .csv"]) --> spec["The spec<br/>a scene: canvas,<br/>plots, artists"]
    spec --> code["codegen<br/>a standalone .py"]
    code --> run["execute the .py"]
    run --> view(["Preview<br/>(what you see)"])
    code --> out(["Export<br/>.py + PNG / SVG / PDF"])
  • One path, both ends. codegen_canvas turns the spec into a plain .py — a list of fig.add_axes([...]) calls over the dataset. The preview is that file, run; the export is that file, saved. They cannot disagree, because they are the same code.
  • The spec is the source of truth. A figure is a JSON scene (canvas, plots, artists). The browser edits it; the backend renders it by executing the generated code. Save it and it is a canvas you can reopen, duplicate and drive over the API.
  • Data stays data. Signals are arrays, referenced by name. The exported code loads the dataset and indexes it — the numbers in the figure are the numbers in your file, unedited.

Data

A dataset is a named set of signals (arrays), 1-D and 2-D. Load one with Load data… (pick an existing dataset, or upload a file):

  • .npz — a numpy zip of named arrays. Safe by construction.
  • .pkl — a Python pickle, loaded through a whitelist unpickler that permits only numpy arrays and plain containers. A pickle that tries to run code — os, subprocess, eval, np.fromfile and the rest — is refused, not executed.
  • .csv — a table with a header row; each numeric column becomes a signal.

Command line

The same engines run from the shell, for scripting and automation:

figfoundry            # start the web app (default)
figfoundry serve      # ...with flags: --port, --host, --no-browser
figfoundry list       # list saved figures
figfoundry new        # create a blank figure, print its slug
figfoundry export SLUG [--out PATH]        # write a figure's .py
figfoundry render SLUG [--format png|svg|pdf] [--out PATH]
figfoundry datasets   # list available datasets

Install

From PyPI, with uv:

uv tool install figfoundry      # puts the `figfoundry` command on your PATH
figfoundry                      # → opens http://127.0.0.1:8037

Or:

pip install figfoundry
# or from this repository:
uv tool install figfoundry --from "git+https://github.com/ductai199x/figfoundry.git"

Python 3.10 or newer. It runs wherever Python and a browser do.

Development
uv sync --extra dev
uv run --extra dev pytest -q          # 152 tests
uv run --with ruff ruff check .       # lint
uv run figfoundry serve               # the app

The suite covers the WYSIWYG invariant for every plot type, the pickle whitelist, dataset I/O (npz/pkl/csv), vector export, the CLI, and the API through a test client. CI runs it, plus the build and an artifact check, on Linux and Windows for Python 3.10 and 3.12 (.github/workflows/ci.yml).

License

Copyright (C) 2026 Tai Duc Nguyen.

Fig Foundry is licensed under the MIT License: use it, study it, change it and share it. The one sample dataset it ships is synthetic; your own data never leaves your machine.

Metadata

Release files for figfoundry 0.3.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 figfoundry 0.3.0
File Size Uploaded Provenance
figfoundry-0.3.0.tar.gz 198.9 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 278.4 kB

Release files / figfoundry-0.3.0.tar.gz

Download URL figfoundry-0.3.0.tar.gz
Size 198.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3c0c577c4d26ec340f3b65027f6cb4836dfca2160103ebaeec3af7b7a5b466f8
BLAKE2b-256 checksum
How to use checksums
614be4865422f5fcd06d772630f7ba29d42764f883d82d88a778f80f4d9133fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / figfoundry-0.3.0-py3-none-any.whl

Download URL figfoundry-0.3.0-py3-none-any.whl
Size 79.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
491f357ed0d3216652a50cfbb80c53d5f1866db4daabaf9b5497e213ea3a66bf
BLAKE2b-256 checksum
How to use checksums
fe5416a0488c3ca016f08c703327e6ea4c3981e95dd1f1c1718289408282716f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for figfoundry 0.3.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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A 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.

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