Record and reproduce matplotlib figures with YAML recipes
Project description
figrecipe
Record and reproduce matplotlib figures.
figrecipe captures matplotlib plotting calls and saves them as human-readable YAML "recipes" that can be used to reproduce figures exactly.
Example Output
| Original | Reproduced from Recipe |
Multi-panel figures with publication-quality styling:
Features
- Drop-in replacement: Use
ps.subplots()instead ofplt.subplots() - Automatic tracking: All plotting calls are recorded automatically
- YAML recipes: Human-readable format for figure specifications
- Efficient storage: Large arrays saved to separate CSV/NPZ files
- One-line reproduction:
fig, ax = ps.reproduce("figure.yaml") - Selective replay: Reproduce only specific plotting calls
- MM-based layout: Precise control with millimeter-based sizing
- Publication styling: Style presets (SCIENTIFIC, MINIMAL, PRESENTATION) and colorblind-friendly palettes
- Seaborn support: Record and reproduce seaborn plots
Installation
pip install figrecipe
Quick Start
Recording a Figure
import figrecipe as ps
import numpy as np
# Create data
x = np.linspace(0, 10, 100)
y = np.sin(x)
# Create figure (drop-in replacement for plt.subplots)
fig, ax = ps.subplots()
# Plot as usual - calls are recorded automatically
ax.plot(x, y, color='red', linewidth=2, id='sine_wave')
ax.scatter(x[::10], y[::10], s=50, color='blue', id='peaks')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Amplitude')
ax.set_title('Sine Wave Example')
ax.legend()
# Save the recipe
ps.save(fig, 'sine_wave.yaml')
Reproducing a Figure
import figrecipe as ps
import matplotlib.pyplot as plt
# Reproduce the entire figure
fig, ax = ps.reproduce('sine_wave.yaml')
plt.show()
# Or reproduce only specific calls
fig, ax = ps.reproduce('sine_wave.yaml', calls=['sine_wave'])
plt.show()
Publication-Quality Figures with MM Layout
import figrecipe as ps
import numpy as np
# List available style presets
print(ps.list_presets()) # ['MINIMAL', 'PRESENTATION', 'SCIENTIFIC']
# Load a style preset (SCIENTIFIC is default)
style = ps.load_style() # or ps.load_style("SCIENTIFIC")
# Create figure with precise mm-based dimensions
fig, ax = ps.subplots(
axes_width_mm=60, # 60mm wide axes
axes_height_mm=40, # 40mm tall axes
margin_left_mm=15, # Space for y-axis labels
margin_bottom_mm=12, # Space for x-axis labels
apply_style_mm=True, # Apply publication style
)
# Plot with auto-cycling colorblind-friendly colors
x = np.linspace(0, 2*np.pi, 100)
ax.plot(x, np.sin(x), label='sin(x)') # Auto: Blue (#0072B2)
ax.plot(x, np.cos(x), label='cos(x)') # Auto: Orange (#D55E00)
ax.set_xlabel('x (radians)')
ax.set_ylabel('y')
ax.legend()
# Save with transparent background
fig.fig.savefig('publication_figure.png', dpi=300, transparent=True)
ps.save(fig, 'publication_figure.yaml')
Inspecting a Recipe
import figrecipe as ps
# Get recipe information without reproducing
info = ps.info('sine_wave.yaml')
print(f"Created: {info['created']}")
print(f"Figure size: {info['figsize']}")
print(f"Number of calls: {len(info['calls'])}")
for call in info['calls']:
print(f" - {call['id']}: {call['function']}()")
Recipe Format
Recipes are saved as YAML files:
figrecipe: "1.0"
id: fig_a1b2c3d4
created: "2025-12-21T14:30:00"
matplotlib_version: "3.8.0"
figure:
figsize: [10, 6]
dpi: 100
axes:
ax_0_0:
calls:
- id: sine_wave
function: plot
args:
- name: x
data: sine_wave_data/sine_wave_x.csv
- name: y
data: sine_wave_data/sine_wave_y.csv
kwargs:
color: "#0072B2"
linewidth: 2
decorations:
- id: set_xlabel_000
function: set_xlabel
args:
- name: arg0
data: "Time (s)"
kwargs: {}
Advanced Usage
Custom Call IDs
Use the id parameter to give meaningful names to your plots:
ax.plot(x, y, color='red', id='experimental_data')
ax.plot(x, y_fit, color='blue', id='fitted_curve')
Multiple Subplots
fig, axes = ps.subplots(2, 2, figsize=(12, 10))
axes[0][0].plot(x, y1, id='top_left')
axes[0][1].scatter(x, y2, id='top_right')
axes[1][0].bar(categories, values, id='bottom_left')
axes[1][1].hist(data, id='bottom_right')
ps.save(fig, 'multi_panel.yaml')
Seaborn Integration
import figrecipe as ps
import pandas as pd
df = pd.DataFrame({'x': x, 'y': y, 'category': categories})
fig, ax = ps.subplots()
ps.sns.scatterplot(data=df, x='x', y='y', hue='category', ax=ax, id='scatter')
ps.save(fig, 'seaborn_figure.yaml')
Temporarily Disable Recording
fig, ax = ps.subplots()
# Recorded
ax.plot(x, y, id='main_data')
# Not recorded
with ax.no_record():
ax.axhline(0, color='gray', linestyle='--')
# Recorded again
ax.scatter(x_points, y_points, id='highlights')
Style Configuration
figrecipe includes a preset-based style system with easy YAML customization:
import figrecipe as ps
# List available presets
print(ps.list_presets()) # ['MINIMAL', 'PRESENTATION', 'SCIENTIFIC']
# Load a preset (SCIENTIFIC is default)
style = ps.load_style() # Default: SCIENTIFIC
style = ps.load_style("MINIMAL") # Minimal, clean design
style = ps.load_style("PRESENTATION") # Large fonts for slides
# Load custom YAML style
style = ps.load_style("/path/to/my_style.yaml")
# Inspect style values
print(f"Axes width: {style.axes.width_mm} mm")
print(f"Font: {style.fonts.family}")
print(f"Colors: {style.colors.palette[:4]}")
# Use style parameters directly
fig, ax = ps.subplots(**style.to_subplots_kwargs())
Colorblind-Friendly Palette
The SCIENTIFIC preset uses Wong (2011) colorblind-safe colors:
- Blue:
#0072B2 - Orange:
#D55E00 - Green:
#009E73 - Purple:
#CC79A7 - Yellow:
#F0E442 - Cyan:
#56B4E9
Why figrecipe?
Scientific Reproducibility
Share the exact specification of your figures alongside your papers. Reviewers and readers can reproduce your figures exactly.
Version Control Friendly
YAML recipes are human-readable and diff-friendly, making it easy to track changes to figures in git.
Data Separation
Large arrays are automatically saved to efficient CSV or NPZ files, keeping recipes small and readable while preserving full data fidelity.
Collaboration
Share figure "recipes" with collaborators who can modify and re-run them with their own data or styling preferences.
API Reference
Main Functions
ps.subplots(nrows=1, ncols=1, **kwargs)- Create recording-enabled figureps.save(fig, path)- Save figure recipe to YAMLps.reproduce(path, calls=None)- Reproduce figure from recipeps.info(path)- Get recipe informationps.load(path)- Load recipe as FigureRecord object
Style Functions
ps.list_presets()- List available style presetsps.load_style(style=None)- Load style from preset name or YAML pathps.apply_style(ax, style=None)- Apply styling to axesps.STYLE- Global style proxy object
Unit Conversions
ps.mm_to_inch(mm)- Convert mm to inchesps.mm_to_pt(mm)- Convert mm to pointsps.inch_to_mm(inch)- Convert inches to mmps.pt_to_mm(pt)- Convert points to mm
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file figrecipe-0.4.0.tar.gz.
File metadata
- Download URL: figrecipe-0.4.0.tar.gz
- Upload date:
- Size: 3.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22c16798f147fc6949fa4c82fa6d957574a479cc4b9753fdab73929e3cf9a504
|
|
| MD5 |
2fa7528cd320a850d4f310773c75e863
|
|
| BLAKE2b-256 |
a8566daf8d481f4e53bb9b5ac821661b1309d2864548b11fa274d8fd10b9de08
|
File details
Details for the file figrecipe-0.4.0-py3-none-any.whl.
File metadata
- Download URL: figrecipe-0.4.0-py3-none-any.whl
- Upload date:
- Size: 60.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e7c174fb652f355204815acce8c290e3c8b8447e4e6d3a109587a44d14a918d
|
|
| MD5 |
99b66c2a598d81f1956fcc0a4816c92c
|
|
| BLAKE2b-256 |
b726b3f35daaf8dd95b97775a80d0a78e733ca52fde1ce8e251c9e2c195b88d5
|