Skip to main content

FigRecipe

SciTeX

Reproducible scientific figures as first-class objects

PyPI Python Documentation License: AGPL-3.0

Tests Install-Check Coverage

Full Documentation · uv pip install figrecipe[all]


Problem and Solution

# Problem Solution
1 Figures drift from data -- plt.savefig(...) produces a PNG whose source data disappears the moment the notebook closes Recipe + data + PNG atomic -- each ax.plot() call records inputs; fr.save(fig) writes .png + .csv + .yaml so figures are replayable from the recipe
2 Restyling requires re-running analysis -- changing fonts/colors/layout means rebuilding the figure from scratch Reproduce from recipe -- fr.reproduce("fig.yaml", style="nature") restyles without touching data; hashes stay valid for Clew
3 mm-precision layout hard -- matplotlib uses inches/pixels; journals demand mm Native mm layout -- figure_mm() + figure_from_axes_mm() give journal-grade column widths without conversion math

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:31296

Demo

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

Figure 2. FigRecipe concept: recipe, data, and style as first-class figure attributes.

Installation

Requires Python >= 3.10.

This coordinated source candidate requires the reviewed scitex-sdk>=0.3.0 owner. Install its reviewed wheel or checkout first while that release is pending; the following registry commands describe the published package.

uv pip install "figrecipe[all]"
Per-feature extras
Extra Contents Install
editor GUI editor (Django + Pillow) uv pip install "figrecipe[editor]"
desktop Standalone desktop shell (pywebview/Qt) uv pip install "figrecipe[desktop]"
app Embedded app runtime (Django + Pillow + scitex-sdk) uv pip install "figrecipe[app]"
seaborn Seaborn recording wrapper uv pip install "figrecipe[seaborn]"
imaging Image utilities (Pillow) uv pip install "figrecipe[imaging]"
graph Diagram graph backend (networkx) uv pip install "figrecipe[graph]"
graph-interactive Interactive graphs (networkx + pyvis) uv pip install "figrecipe[graph-interactive]"
mcp MCP server for AI agents (fastmcp) uv pip install "figrecipe[mcp]"
demo Demo verification (playwright + tesseract) uv pip install "figrecipe[demo]"
scitex SciTeX suite integration uv pip install "figrecipe[scitex]"

Table 1. Per-feature extras; figrecipe[all] installs everything.

Architecture

FigRecipe is the first app built on the SciTeX platform -- it proves the app pattern that other apps follow. It works standalone (figrecipe gui open) AND embedded inside scitex-cloud.

flowchart TD
    A[scitex orchestrator<br/>re-exports figrecipe as scitex.plt] --> D[figrecipe<br/>reference app]
    D --> B[scitex-sdk<br/>app runtime + UI components]
    D --> E[figrecipe<br/>standalone package]
    D --> F[figrecipe._django<br/>cloud embedding]
    E --> G[Figure engine<br/>recipes + provenance]
    E --> H[Diagram system<br/>mm-based boxes & arrows]
    E --> I[GUI editor]

Figure 1. Package architecture: figrecipe as the reference app on the SciTeX platform.

What this package owns: Figure creation, reproduction, and composition engine; YAML recipe format and data provenance; Diagram system (box-and-arrow with mm-based coordinates); GUI editor; Django integration.

The shared app runtime and UI components come from scitex-sdk through scitex_sdk.app, scitex_sdk.ui, and @scitex/sdk/ui/.... FigRecipe owns its workspace templates and editor behavior. The candidate preserves standalone and generic plugin integration; legacy Hub route cutover remains coordinated.


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

The SciTeX system follows the Four Freedoms for Research below, inspired by the Free Software Definition:

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 we believe research infrastructure deserves the same freedoms as the software it runs on.

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

Figure 3. SCITEX style anatomy: millimeter-precise control over every visual element.

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

Figure 4. GUI editor for precise visual adjustments.

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 import Diagram

d = Diagram(title="EEG Pipeline", gap_mm=10)
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")
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
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. Output files from d.save(): out.png (auto-cropped), out.yaml (recipe), out_hitmap.png (GUI click regions), out_debug.png (debug overlay).

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 are normalized automatically.

Validation Rules
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

Table 2. Diagram validation rules enforced by d.save().

Four Interfaces

Python API
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, figure.yaml, figure_data/sine.csv

fr.save(fig, "fig.zip")     # self-contained zip bundle
fr.load("fig.png")          # reload from any format
fig, ax = fr.reproduce("figure.yaml")
fr.gui(fig)                 # Launch visual editor
fr.compose(sources=["panel_a.yaml", "panel_b.yaml"], output_path="composed.png", layout="horizontal")
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 open 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 via the Model Context Protocol.

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
diagram_compile_mermaid Compile diagram spec to Mermaid
diagram_render Render diagram to PNG/SVG/PDF
audio_speak Text-to-speech relay to user's speakers

Table 3. MCP tools exposed to AI agents.

Add .mcp.json to your project root (use SCITEX_ENV_SRC for environment switching):

{"mcpServers": {"scitex": {"command": "scitex", "args": ["mcp", "start"], "env": {"SCITEX_ENV_SRC": "${SCITEX_ENV_SRC}"}}}}

Full MCP specification

Skills — for AI Agent Discovery

Skills provide workflow-oriented guides that AI agents query to discover capabilities and usage patterns.

figrecipe skills list              # List available skill pages
figrecipe skills get SKILL         # Show main skill page
scitex-dev skills export --package figrecipe  # Export to Claude Code
Skill Content
quick-start Core workflow: subplots, save, reproduce
plot-types All supported plot types with examples
composition Multi-panel figure composition
styles Style presets, SCITEX/MATPLOTLIB, custom styles
bundle ZIP bundle format
diagram Box-and-arrow diagrams, Mermaid, Graphviz
cli-reference All CLI commands
mcp-tools MCP tool reference for AI agents

Table 4. Skill pages bundled under _skills/figrecipe/.

Part of SciTeX

figrecipe is part of SciTeX. Install via the umbrella with pip install scitex[plt] to use as scitex.plt (Python) or scitex plt ... / scitex figrecipe ... (CLI; the umbrella shells out to the standalone figrecipe binary).

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

Table 5. Lint rules reported by scitex-linter for this package.

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

Table 6. Supported matplotlib plot-type categories.


SciTeX

Metadata

Release files for figrecipe 0.36.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 figrecipe 0.36.0
File Size Uploaded
figrecipe-0.36.0.tar.gz 15.8 MB Details

Built distribution (wheel)

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

Total release size: 28.9 MB

Release files / figrecipe-0.36.0.tar.gz

Download URL figrecipe-0.36.0.tar.gz
Size 15.8 MB
Tags Source
SHA-256 checksum
How to use checksums
6ef3df21f72f20094bcbabd1d3a2593d3543c465fabc5e80429ed7b32bf5b64b
BLAKE2b-256 checksum
How to use checksums
66496d084c09268105ede645edb4f1454ffa6184eabd7ee26529fc08047b9a8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / figrecipe-0.36.0-py3-none-any.whl

Download URL figrecipe-0.36.0-py3-none-any.whl
Size 13.1 MB
Tags Python 3
SHA-256 checksum
How to use checksums
00b93bc90a16fe05041307187fb0fb3fce5482ea0958f0689505036742746786
BLAKE2b-256 checksum
How to use checksums
c13657aaad49621a7c5487b1dce5ed9044b94407e571f67d7ed7911525abbaa0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.12.14

Release history Release notifications | RSS feed

0.36.2

2 release files

This release

0.36.0 This release

2 release files

0.35.0

2 release files

0.34.8

2 release files

0.34.7

2 release files

0.34.6

2 release files

0.34.5

2 release files

0.34.4

2 release files

0.34.3

2 release files

0.34.2

2 release files

0.34.1

2 release files

0.34.0

2 release files

0.33.0

2 release files

0.32.1

2 release files

0.32.0

2 release files

0.31.0

2 release files

0.30.0

2 release files

0.29.9

2 release files

0.29.8

2 release files

0.29.7

2 release files

0.29.6

2 release files

0.29.5

2 release files

0.29.4

2 release files

0.29.3

2 release files

0.29.2

2 release files

0.29.0

2 release files

0.28.9

2 release files

0.28.8

2 release files

0.28.4

2 release files

0.28.3

2 release files

0.28.2

2 release files

0.28.1

2 release files

0.27.0

2 release files

0.26.6

2 release files

0.26.5

2 release files

0.26.4

2 release files

0.26.1

2 release files

0.26.0

2 release files

0.25.1

2 release files

0.24.1

2 release files

0.24.0

2 release files

0.18.0

2 release files

0.16.0

2 release files

0.15.0

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

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