FigRecipe
Reproducible scientific figures as first-class objects
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.
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
- The freedom to run your research anywhere -- your machine, your terms.
- The freedom to study how every step works -- from raw data to final manuscript.
- The freedom to redistribute your workflows, not just your papers.
- 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.
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.
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")
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
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}"}}}}
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.
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)
| File | Size | Uploaded | |
|---|---|---|---|
| figrecipe-0.36.0.tar.gz | 15.8 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|