Skip to main content

Reproducible matplotlib wrapper with mm-precision layouts

Project description

FigRecipe (scitex-plt)

SciTeX

Reproducible scientific figures as first-class objects

PyPI version Documentation Tests License: AGPL-3.0

Full Documentation · pip install figrecipe


Installation

Requires Python >= 3.9.

pip install figrecipe

For the GUI editor:

pip install figrecipe[editor]

SciTeX users: pip install scitex[plt] already includes FigRecipe.

Quickstart

import figrecipe as fr
import numpy as np

x = np.linspace(0, 2 * np.pi, 100)

fig, ax = fr.subplots()
ax.plot(x, np.sin(x), id="sine")
fr.save(fig, "figure.png")
# Produces: figure.png, figure.yaml, figure_data/sine.csv

Reload and edit from the saved recipe:

fig, ax = fr.reproduce("figure.yaml")
fr.gui(fig)  # Launch visual editor at http://127.0.0.1:5050

FigRecipe — Reproducible, editable, publication-ready scientific figures. Part of SciTeX.

Four Freedoms for Research

  1. The freedom to run your research anywhere — your machine, your terms.
  2. The freedom to study how every step works — from raw data to final manuscript.
  3. The freedom to redistribute your workflows, not just your papers.
  4. The freedom to modify any module and share improvements with the community.

AGPL-3.0 — because research infrastructure deserves the same freedoms as the software it runs on.

SciTeX users: pip install scitex[plt] includes FigRecipe. scitex.plt delegates to figrecipe — they share the same API.

Overview

FigRecipe treats recipe, data, and style as first-class attributes of every figure. This enables data governance and style editing without losing scientific rigor.

FigRecipe: Reproducible Scientific Figures

Created with Diagrams

Styling

FigRecipe provides millimeter-precise control over every visual element. The SCITEX style preset is applied by default, producing publication-ready figures with standard matplotlib plotting.

SCITEX Style Anatomy

Millimeter-based Layout
fig, ax = fr.subplots(
    axes_width_mm=60,
    axes_height_mm=40,
    margin_left_mm=15,
)
Style Presets
fr.load_style("SCITEX")       # Publication defaults
fr.load_style("SCITEX_DARK")  # Dark theme
fr.load_style("MATPLOTLIB")   # Pure Matplotlib

GUI Editor

For precise adjustments, GUI editor is available.

FigRecipe GUI Editor

Migration from Matplotlib

Matplotlib-compatibility

FigRecipe is a drop-in replacement for matplotlib — just change your import:

# Before
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(x, y)
plt.savefig("fig.png")

# After
import figrecipe as fr
fig, ax = fr.subplots()
ax.plot(x, y, id="my_trace")
fr.save(fig, "fig.png")  # → fig.png + fig.yaml + fig_data/

Systematic Migration

scitex-linter detects and auto-fixes matplotlib patterns into mm-based FigRecipe equivalents (check, format, python). It also works as a pre-commit hook, ensuring AI agents follow FigRecipe conventions.

Diagrams

Create publication-quality box-and-arrow diagrams with mm-based coordinates. See Overview for an example output.

Usage
from figrecipe._diagram import Diagram

d = Diagram(title="EEG Pipeline", gap_mm=10)

# Boxes
d.add_box(
    "raw", "Raw EEG", subtitle="64 ch", emphasis="muted", shape="cylinder"
)
d.add_box("filter", "Bandpass", subtitle="0.5-45 Hz", emphasis="primary")
d.add_box("ica", "ICA", subtitle="Artifact removal", emphasis="primary")

# Arrows
d.add_arrow("raw", "filter")
d.add_arrow("filter", "ica")

d.save(
    "pipeline.png"
)  # → pipeline.png + pipeline.yaml + pipeline_hitmap.png + pipeline_debug.png
Containers & Flex Layout

Use gap_mm on the Diagram for automatic flex layout (no manual x/y needed):

d = Diagram(title="System Overview", gap_mm=10)

d.add_box("a", "Module A")
d.add_box("b", "Module B")
d.add_container("grp", title="Core", children=["a", "b"], direction="row")
d.add_box("out", "Output", shape="document")
d.add_arrow("grp", "out")
d.save("overview.png")
Auto-Fix & Save Options

auto_fix=True automatically resolves layout violations (overlaps, container enclosure, canvas bounds, arrow collisions):

fig, ax = d.render(auto_fix=True)

# d.save() renders, auto-crops, and optionally watermarks:
d.save("out.png", watermark=True)  # "Plotted by FigRecipe" stamp

Output files from d.save():

File Content
out.png Auto-cropped diagram
out.yaml Recipe for reproduction
out_hitmap.png Click-target regions for GUI editing
out_debug.png Debug overlay showing positions and anchors
Shapes & Anchors

Shapes: rounded (default), box, stadium, cylinder, document, file, codeblock. Use node_class for semantic defaults: "code" → codeblock, "input" → cylinder, "claim" → document.

Anchors: top, bottom, left, right, top-left, top-right, bottom-left, bottom-right, center, or auto (default). Aliases like n/s/e/w, tl/tr/bl/br are normalized automatically.

Validation Rules

All rules are enforced on render. Failed figures are saved with a _FAILED suffix for inspection.

Rule Check Severity
W Width exceeds 185 mm (double-column max) Warning
R1 Container must enclose all children Error
R2 No two boxes may overlap Error
R3 Container title must clear children (5 mm zone) Warning
R4 Box text must fit within padded inner area Warning
R5 Text-to-text margin >= 2 mm Error
R6 Text-to-edge margin >= 2 mm Error
R7 Arrow visible-length ratio >= 90% Error
R8 Curved-arrow label on same side as arc Error
R9 All elements within canvas bounds Error

Three Interfaces

🐍 Python API

Create and save — standard matplotlib API with auto-recording:

import figrecipe as fr
import numpy as np

fig, ax = fr.subplots()
ax.plot(np.sin(np.linspace(0, 10, 100)), id="sine")
fr.save(fig, "figure.png")  # Saves + validates pixel-identical reproduction

Output:

figure.png                # Publication-ready image
figure.yaml               # Reproducible recipe (validated on save)
figure_data/
  sine.csv                # Plot data (one CSV per trace)

Save / Load Formats — from recipe or bundle:

fr.save(fig, "fig.png")     # fig.png + fig.yaml
fr.save(fig, "fig.zip")     # self-contained zip bundle
fr.load("fig.png")          # reload from any format
Format Save Load
PNG / PDF / SVG
YAML
Directory / ZIP

Reproduce and edit — from recipe or bundle:

fig, ax = fr.reproduce("figure.yaml")
fr.gui(fig)  # Launch visual editor (at http://127.0.0.1:5050 by default)

Compose — multi-panel figures:

fr.compose(
    sources=["panel_a.yaml", "panel_b.yaml"],
    output_path="composed.png",
    layout="horizontal",
)

Composed multi-panel figure

Statistics — significance brackets:

ax.add_stat_annotation(x1=0, x2=1, p_value=0.01, style="stars")

Full API reference

🖥️ CLI Commands
figrecipe --help-recursive            # Show all commands
figrecipe reproduce fig.yaml          # Recreate figure from recipe
figrecipe gui figure.png              # Launch visual editor
figrecipe validate fig.yaml           # Verify pixel-identical reproduction
figrecipe extract fig.yaml            # Extract plotted data as CSV
figrecipe compose a.yaml b.yaml       # Compose multi-panel figure
figrecipe crop figure.png             # Auto-crop whitespace
figrecipe info fig.yaml               # Show recipe metadata

Full CLI reference

🔧 MCP Server — for AI Agents

AI agents can create, compose, and reproduce publication-ready figures autonomously.

Tool Description
plot Create figure from declarative YAML spec
reproduce Recreate figure from recipe
compose Combine panels into multi-panel layout
crop Auto-crop whitespace
info Inspect recipe metadata
validate Verify reproduction fidelity
# Install to Claude Code
figrecipe mcp install

Full MCP specification

Lint Rules

Detected by scitex-linter when this package is installed.

Rule Severity Message
STX-FM001 warning figsize= detected — inch-based figure sizing is imprecise for publications
STX-FM002 warning tight_layout() detected — layout is unpredictable across plot types
STX-FM003 warning bbox_inches="tight" detected — can crop important elements unpredictably
STX-FM004 info constrained_layout=True detected — conflicts with mm-based layout control
STX-FM005 info subplots_adjust() with hardcoded fractions — fragile across figure sizes
STX-FM006 info plt.savefig() detected — no provenance tracking
STX-FM007 info rcParams direct modification detected — hard to maintain across figures
STX-FM008 warning set_size_inches() detected — bypasses mm-based layout control
STX-FM009 warning ax.set_position() detected — conflicts with mm-based layout control
STX-P001 info ax.plot() — consider ax.stx_line() for automatic CSV data export
STX-P002 info ax.scatter() — consider ax.stx_scatter() for automatic CSV data export
STX-P003 info ax.bar() — consider ax.stx_bar() for automatic sample size annotation
STX-P004 info plt.show() is non-reproducible in batch/CI environments
STX-P005 info print() inside @stx.session — use logger for tracked logging

47 matplotlib plot types supported

Category Plot Types
Line & Curve plot, step, fill, fill_between, fill_betweenx, errorbar, stackplot, stairs
Scatter & Points scatter
Bar & Categorical bar, barh
Distribution hist, hist2d, boxplot, violinplot, ecdf
2D Image & Matrix imshow, matshow, pcolor, pcolormesh, hexbin, spy
Contour & Surface contour, contourf, tricontour, tricontourf, tripcolor, triplot
Spectral & Signal specgram, psd, csd, cohere, angle_spectrum, magnitude_spectrum, phase_spectrum, acorr, xcorr
Vector & Flow quiver, barbs, streamplot
Special pie, stem, eventplot, loglog, semilogx, semilogy, graph

SciTeX

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

figrecipe-0.26.4.tar.gz (2.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

figrecipe-0.26.4-py3-none-any.whl (993.0 kB view details)

Uploaded Python 3

File details

Details for the file figrecipe-0.26.4.tar.gz.

File metadata

  • Download URL: figrecipe-0.26.4.tar.gz
  • Upload date:
  • Size: 2.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for figrecipe-0.26.4.tar.gz
Algorithm Hash digest
SHA256 2d8e698a27c2f6e9189755b31ac46829bfa5f58c7556a7300012667fa61a9b48
MD5 aede49cb00c1e91dcff807b907ebbdb5
BLAKE2b-256 e4d649d417344bb61766d20391ec2795786f9ca799cdc1c15ea16c2a85314114

See more details on using hashes here.

Provenance

The following attestation bundles were made for figrecipe-0.26.4.tar.gz:

Publisher: publish-pypi.yml on ywatanabe1989/figrecipe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file figrecipe-0.26.4-py3-none-any.whl.

File metadata

  • Download URL: figrecipe-0.26.4-py3-none-any.whl
  • Upload date:
  • Size: 993.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for figrecipe-0.26.4-py3-none-any.whl
Algorithm Hash digest
SHA256 f53e321f6cc2f1f9465e560f3ab558c89eaddab41dcd425aa97ec3477eb2c855
MD5 11253b83681b7f79e0c5752250f56461
BLAKE2b-256 7f1226c67ecf36a6d8a116936eaa8813c836241af0dd17aba7bb4fc3b94f8c0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for figrecipe-0.26.4-py3-none-any.whl:

Publisher: publish-pypi.yml on ywatanabe1989/figrecipe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page