FigRecipe API Reference
figrecipe - Record and reproduce matplotlib figures.
A lightweight library for capturing matplotlib plotting calls and reproducing figures from saved recipes.
Usage
>>> import figrecipe as fr
>>> fig, ax = fr.subplots()
>>> ax.plot(x, y, id='my_data')
>>> fr.save(fig, 'recipe.yaml')
Examples
Recording a figure:
>>> import figrecipe as fr
>>> import numpy as np
>>>
>>> x = np.linspace(0, 10, 100)
>>> y = np.sin(x)
>>>
>>> fig, ax = fr.subplots()
>>> ax.plot(x, y, color='red', linewidth=2, id='sine_wave')
>>> ax.set_xlabel('Time')
>>> ax.set_ylabel('Amplitude')
>>> fr.save(fig, 'my_figure.yaml')
Reproducing a figure:
>>> fig, ax = fr.reproduce('my_figure.yaml')
>>> plt.show()
fr.utils: Unit conversions, font checks, low-level recipe access
fr.styles: Axis helpers, spine management, plot styling functions
fr.viz: Diagram and graph visualization utilities
>>> from figrecipe import utils
>>> utils.mm_to_inch(25.4) # Unit conversions
>>> from figrecipe import styles
>>> styles.hide_spines(ax) # Spine management
- figrecipe.subplots(nrows=1, ncols=1, axes_width_mm=None, axes_height_mm=None, margin_left_mm=None, margin_right_mm=None, margin_bottom_mm=None, margin_top_mm=None, space_w_mm=None, space_h_mm=None, style=None, apply_style_mm=True, panel_labels=None, **kwargs)[source]
Create a figure with recording-enabled axes.
This is a drop-in replacement for plt.subplots() that wraps the returned figure and axes with recording capabilities.
Supports mm-based layout control for publication-quality figures.
- Parameters:
nrows (int) – Number of rows and columns of subplots.
ncols (int) – Number of rows and columns of subplots.
axes_width_mm (float, optional) – Axes dimensions in mm.
axes_height_mm (float, optional) – Axes dimensions in mm.
margin_left_mm (float, optional) – Left/right margins in mm.
margin_right_mm (float, optional) – Left/right margins in mm.
margin_bottom_mm (float, optional) – Bottom/top margins in mm.
margin_top_mm (float, optional) – Bottom/top margins in mm.
space_w_mm (float, optional) – Horizontal/vertical spacing between axes in mm.
space_h_mm (float, optional) – Horizontal/vertical spacing between axes in mm.
style (dict, optional) – Style configuration dictionary.
apply_style_mm (bool) – If True (default), apply loaded style to axes.
panel_labels (bool or None) – If True, add panel labels (A, B, C, …).
**kwargs – Additional arguments passed to plt.subplots().
- Return type:
Tuple[RecordingFigure,Union[RecordingAxes,ndarray[tuple[int,...],dtype[TypeVar(_ScalarType_co, bound=generic, covariant=True)]]]]- Returns:
fig (RecordingFigure) – Wrapped figure object.
axes (RecordingAxes or ndarray) – Wrapped axes.
- figrecipe.save(fig, path, save_recipe=True, include_data=True, data_format='csv', csv_format='separate', validate=True, validate_mse_threshold=100.0, validate_error_level='error', verbose=True, dpi=None, image_format=None, facecolor=None, save_hitmap=True)[source]
Save a figure as image and recipe. Unified API with fig.savefig().
- Parameters:
fig (RecordingFigure or Figure) – The figure to save.
path (str or Path) – Output path (.png, .pdf, .svg, .yaml, etc.)
save_recipe (bool) – If True (default), save YAML recipe alongside the image.
include_data (bool) – If True (default), save large arrays to separate files.
data_format (str) – Format for data files: ‘csv’, ‘npz’, or ‘inline’.
csv_format (str) – CSV structure: ‘separate’ (default) or ‘single’ (scitex-compatible).
validate (bool) – If True (default), validate reproducibility after saving.
validate_mse_threshold (float) – Maximum acceptable MSE for validation (default: 100).
validate_error_level (str) – How to handle failures: ‘error’, ‘warning’, or ‘debug’.
verbose (bool) – If True (default), print save status.
dpi (int, optional) – DPI for image output.
image_format (str, optional) – Image format when path is YAML.
facecolor (str, optional) – Background color. When opaque, patches are made visible.
save_hitmap (bool) – If True (default), save hitmap image for GUI editor element selection.
- Returns:
If save_recipe=True: (image_path, yaml_path, ValidationResult or None) If save_recipe=False: (image_path, None, None)
- Return type:
- figrecipe.reproduce(path, calls=None, skip_decorations=False, apply_style=True)[source]
Reproduce a figure from a recipe file or bundle.
- Parameters:
path (str or Path) – Path to recipe. Supports multiple formats: - .yaml/.yml file: Direct recipe file - .png/.jpg/etc: Image with associated .yaml - Directory: Bundle containing recipe.yaml - .zip: ZIP bundle (both old recipe.yaml format and new spec.json format)
calls (list of str, optional) – If provided, only reproduce these specific call IDs.
skip_decorations (bool) – If True, skip decoration calls.
apply_style (bool) – If True (default), apply saved style.
- Return type:
- Returns:
fig (matplotlib.figure.Figure) – Reproduced figure.
axes (Axes or list of Axes) – Reproduced axes.
- figrecipe.load(path, calls=None, skip_decorations=False, apply_style=True)
Reproduce a figure from a recipe file or bundle.
- Parameters:
path (str or Path) – Path to recipe. Supports multiple formats: - .yaml/.yml file: Direct recipe file - .png/.jpg/etc: Image with associated .yaml - Directory: Bundle containing recipe.yaml - .zip: ZIP bundle (both old recipe.yaml format and new spec.json format)
calls (list of str, optional) – If provided, only reproduce these specific call IDs.
skip_decorations (bool) – If True, skip decoration calls.
apply_style (bool) – If True (default), apply saved style.
- Return type:
- Returns:
fig (matplotlib.figure.Figure) – Reproduced figure.
axes (Axes or list of Axes) – Reproduced axes.
- figrecipe.compose(sources, layout=None, canvas_size_mm=None, gap_mm=5.0, dpi=300, panel_labels=False, label_style='uppercase', **kwargs)[source]
Compose a new figure from multiple sources (recipes or raw images).
Supports two modes automatically detected from sources format:
Grid-based: sources={(row, col): path} Uses layout=(nrows, ncols) for subplot grid.
Mm-based: sources={path: {“xy_mm”: (x, y), “size_mm”: (w, h)}} Uses canvas_size_mm for precise positioning.
- Parameters:
sources (dict) – Either: - Grid-based: {(row, col): source_path} mapping positions to sources - Mm-based: {source_path: {“xy_mm”: (x, y), “size_mm”: (w, h)}}
layout (tuple, optional) – (nrows, ncols) for grid-based composition. Auto-detected if not provided.
canvas_size_mm (tuple, optional) – (width_mm, height_mm) for mm-based composition. Required for mm-based mode.
gap_mm (float) – Gap between panels in mm (for auto-layout modes like ‘horizontal’).
dpi (int) – DPI for the output figure.
panel_labels (bool) – If True, add panel labels (A, B, C…) to each panel.
label_style (str) – ‘uppercase’, ‘lowercase’, or ‘numeric’.
**kwargs – Additional arguments passed to figure creation.
- Return type:
Tuple[RecordingFigure,Union[RecordingAxes,ndarray[tuple[int,...],dtype[TypeVar(_ScalarType_co, bound=generic, covariant=True)]],List[RecordingAxes]]]- Returns:
fig (RecordingFigure) – Composed figure (editable, recordable).
axes (RecordingAxes, ndarray, or list) – Axes of the composed figure.
Examples
Grid-based composition:
>>> fig, axes = fr.compose( ... layout=(1, 2), ... sources={ ... (0, 0): "panel_a.yaml", ... (0, 1): "panel_b.yaml", ... } ... )
Mm-based free-form composition:
>>> fig, axes = fr.compose( ... canvas_size_mm=(180, 120), ... sources={ ... "panel_a.yaml": {"xy_mm": (0, 0), "size_mm": (85, 55)}, ... "panel_b.yaml": {"xy_mm": (90, 0), "size_mm": (85, 55)}, ... "panel_c.yaml": {"xy_mm": (0, 60), "size_mm": (175, 55)}, ... } ... )
- figrecipe.align_panels(fig, panels, mode, reference=None)[source]
Align multiple panels to a reference panel.
- Parameters:
fig (RecordingFigure) – The figure containing the panels.
panels (list of tuple) – List of (row, col) positions to align.
mode (str or AlignmentMode) – Alignment mode: ‘left’, ‘right’, ‘top’, ‘bottom’, ‘center_h’, ‘center_v’, ‘axis_x’, ‘axis_y’.
reference (tuple, optional) – Reference panel position. If None, uses first panel.
- Return type:
Examples
>>> import figrecipe as fr >>> fig, axes = fr.subplots(2, 2) >>> # Align left column panels to left edge >>> fr.align_panels(fig, [(0, 0), (1, 0)], mode="left")
- figrecipe.distribute_panels(fig, panels, direction='horizontal', spacing_mm=None)[source]
Distribute panels evenly with optional fixed spacing.
- Parameters:
fig (RecordingFigure) – The figure containing the panels.
panels (list of tuple) – List of (row, col) positions to distribute.
direction (str) – ‘horizontal’ or ‘vertical’.
spacing_mm (float, optional) – Fixed spacing in mm. If None, distribute evenly within current bounds.
- Return type:
Examples
>>> import figrecipe as fr >>> fig, axes = fr.subplots(1, 3) >>> # Distribute evenly >>> fr.distribute_panels(fig, [(0, 0), (0, 1), (0, 2)]) >>> # With fixed 5mm spacing >>> fr.distribute_panels(fig, [(0, 0), (0, 1), (0, 2)], spacing_mm=5)
- figrecipe.align_smart(fig, panels=None)[source]
Automatically align panels in a compact grid layout.
Works like human behavior: 1. Detect grid structure (nrows, ncols) 2. Place panels from top-left to bottom-right 3. Calculate minimum rectangle to cover all content in each row/column 4. Unify row heights and column widths 5. Use space effectively with theme margins and spacing
Uses margin and spacing values from the loaded SCITEX theme: - margins.left_mm, margins.right_mm, margins.top_mm, margins.bottom_mm - spacing.horizontal_mm, spacing.vertical_mm
- Parameters:
fig (RecordingFigure) – The figure containing the panels.
panels (list of tuple, optional) – Specific panels to align. If None, aligns all panels.
- Return type:
Examples
>>> import figrecipe as fr >>> fig, axes = fr.subplots(2, 2) >>> # ... add plots ... >>> fr.align_smart(fig) # Align all panels using theme settings
- figrecipe.gui(source=None, style=None, port=5050, host='127.0.0.1', open_browser=True, hot_reload=False, working_dir=None, desktop=False)[source]
Launch interactive GUI editor for figure styling.
- Parameters:
source (RecordingFigure, str, Path, or None) – Either a live RecordingFigure object, path to a .yaml recipe file, or None to create a new blank figure.
style (str or dict, optional) – Style preset name or style dict.
port (int, optional) – Django server port (default: 5050).
host (str, optional) – Host to bind server (default: “127.0.0.1”, use “0.0.0.0” for Docker).
open_browser (bool, optional) – Whether to open browser automatically (default: True).
hot_reload (bool, optional) – Enable hot reload (default: False).
working_dir (str or Path, optional) – Working directory for file browser (default: directory containing source).
desktop (bool, optional) – Launch as native desktop window using pywebview (default: False). Requires: pip install figrecipe[desktop]
- Returns:
Final style overrides after editing session.
- Return type:
- figrecipe.crop(input_path, output_path=None, margin_mm=1.0, margin_px=None, overwrite=False, verbose=False, return_offset=False)[source]
Crop a figure image to its content area with a specified margin.
- Parameters:
input_path (str or Path) – Path to the input image.
output_path (str or Path, optional) – Path to save the cropped image.
margin_mm (float, optional) – Margin in millimeters (default: 1.0mm).
margin_px (int, optional) – Margin in pixels (overrides margin_mm if provided).
overwrite (bool, optional) – Whether to overwrite the input file (default: False)
verbose (bool, optional) – Whether to print detailed information (default: False)
return_offset (bool, optional) – If True, also return crop offset info dict (default: False)
- Returns:
Path to the saved cropped image. If return_offset=True, returns (path, offset_dict).
- Return type:
Path or tuple
- figrecipe.validate(path, mse_threshold=100.0)[source]
Validate that a saved recipe can reproduce its original figure.
- figrecipe.extract_data(path)[source]
Extract data arrays from a saved recipe.
- Returns:
Nested dictionary: {call_id: {‘x’: array, ‘y’: array, …}}
- Return type:
- class figrecipe.Figz(path)[source]
Bases:
objectMulti-panel figure bundle (.fig.zip).
- Manages a ZIP file containing:
manifest.json - bundle type declaration spec.json - figure spec with panel list style.json - figure dimensions and theme panels/ - .plt.zip panel bundles
Example
>>> figz = Figz.create("Figure1.fig.zip", "Figure1") >>> figz.add_panel("A", pltz_path) >>> figz.add_panel("B", pltz_bytes)
- add_panel(label, pltz_source, position=None, size=None)[source]
Add a .plt.zip panel to this figure.
- add_panel_from_png(label, png_bytes, plot_type='image', position=None, size=None, hitmap_bytes=None, hitmap_color_map=None, data_csv=None)[source]
Create a .plt.zip bundle from PNG bytes and embed it as a panel.
Convenience wrapper around
add_panel()for the common case of adding a pre-rendered PNG image as a panel.- Parameters:
label (str) – Panel label (e.g., “A”, “B”).
png_bytes (bytes) – PNG image data.
plot_type (str, optional) – Plot type label stored in the panel’s spec.json (default: “image”).
position (dict, optional) – Panel position e.g. {“x_mm”: 5, “y_mm”: 5}.
size (dict, optional) – Panel size e.g. {“width_mm”: 80, “height_mm”: 68}.
- Return type:
- get_panel(label)[source]
Extract panel as Pltz instance (via temp file).
Note: The caller is responsible for cleaning up the temp file (accessible via the returned Pltz instance’s .path attribute).
- get_panel_data(panel_id)[source]
Get panel’s CSV data as DataFrame.
- Parameters:
panel_id (str) – Panel label.
- Return type:
DataFrame or None
- class figrecipe.Pltz(path)[source]
Bases:
objectSingle-plot bundle (.plt.zip).
Thin wrapper around figrecipe’s existing bundle functions: - load_bundle() - save_bundle() - reproduce_bundle()
- Bundle structure (inside ZIP):
- {stem}/
spec.json # WHAT to plot (semantic specification) style.json # HOW it looks (appearance settings) data.csv # Raw data recipe.yaml # Reproducible recipe exports/
figure.png
- classmethod create(path, fig)[source]
Save a RecordingFigure as a .plt.zip bundle.
- Parameters:
path (str or Path) – Output path. If it doesn’t end in .zip, .zip is appended.
fig (RecordingFigure) – Figure created with figrecipe.subplots().
- Returns:
Loaded Pltz instance wrapping the saved bundle.
- Return type:
- classmethod from_png(png_bytes, path, plot_type='image', spec=None, style=None, hitmap_bytes=None, hitmap_color_map=None, data_csv=None)[source]
Create a .plt.zip bundle wrapping a pre-rendered PNG image.
Useful when a figure is rendered externally (e.g., from a gallery template) and needs to be stored as a figrecipe bundle.
- Parameters:
- Returns:
Loaded Pltz instance wrapping the saved bundle.
- Return type:
- get_preview()[source]
Read pre-rendered preview PNG from bundle.
- Returns:
PNG bytes, or None if no preview image is stored.
- Return type:
bytes or None
- render_preview()[source]
Reproduce figure and render to PNG bytes.
- Returns:
PNG bytes, or None on failure.
- Return type:
bytes or None
- reproduce()[source]
Reproduce figure from bundle.
- Returns:
(fig, axes) reproduced from bundle.
- Return type:
- figrecipe.save_bundle(fig, path, dpi=None, image_formats=None, save_hitmap=True, verbose=True)[source]
Save figure as a layered bundle (ZIP format).
- Bundle structure inside ZIP:
spec.json # WHAT (semantic specification) style.json # HOW (appearance settings) data.csv # DATA (immutable source data) recipe.yaml # Reproducible recipe (for fr.reproduce()) exports/
figure.png figure_hitmap.png
- Parameters:
fig (RecordingFigure) – The figure to save.
path (str or Path) – Output path (.zip will be added if not present).
dpi (int, optional) – DPI for exports (default from style or 300).
image_formats (list, optional) – Image formats to export (default: [‘png’]).
save_hitmap (bool) – Whether to save hitmap for GUI editing (default: True).
verbose (bool) – Whether to print status (default: True).
- Returns:
Path to saved ZIP bundle.
- Return type:
Path
- figrecipe.load_style(style='SCITEX', dark=False, background=None)[source]
Load style configuration and apply it globally.
After calling this function, subsequent subplots() calls will automatically use the loaded style (fonts, colors, theme, etc.).
- Parameters:
style (str, Path, bool, or None) – One of: - “SCITEX” / “FIGRECIPE”: Scientific publication style (default) - “MATPLOTLIB”: Vanilla matplotlib defaults - Path to custom YAML file: “/path/to/my_style.yaml” - None or False: Unload style (reset to matplotlib defaults)
dark (bool, optional) – If True, apply dark theme transformation (default: False). Equivalent to appending “_DARK” to preset name.
background (str, optional) – Override default background color. E.g., ‘white’ for opaque figures. Sets theme.light.figure_bg and theme.light.axes_bg. Use ‘transparent’ for transparent background.
- Returns:
Style configuration with dot-notation access. Returns None if style is unloaded.
- Return type:
DotDict or None
Examples
>>> import figrecipe as fr
>>> # Load scientific style (default) >>> fr.load_style() >>> fr.load_style("SCITEX") # explicit
>>> # Load with white background (override transparent default) >>> fr.load_style("SCITEX", background='white')
>>> # Load dark theme >>> fr.load_style("SCITEX_DARK") >>> fr.load_style("SCITEX", dark=True) # equivalent
>>> # Reset to vanilla matplotlib >>> fr.load_style(None) # unload >>> fr.load_style(False) # unload >>> fr.load_style("MATPLOTLIB") # explicit vanilla
>>> # Access style values >>> style = fr.load_style("SCITEX") >>> style.axes.width_mm 40
- figrecipe.unload_style()[source]
Unload the current style and reset to matplotlib defaults.
After calling this, subsequent subplots() calls will use vanilla matplotlib behavior without FigRecipe styling.
Examples
>>> import figrecipe as fr >>> fr.load_style("SCITEX") # Apply scientific style >>> fig, ax = fr.subplots() # Styled >>> fr.unload_style() # Reset to matplotlib defaults >>> fig, ax = fr.subplots() # Vanilla matplotlib
- figrecipe.list_presets()[source]
List available style presets.
Examples
>>> import figrecipe as ps >>> ps.list_presets() ['MINIMAL', 'PRESENTATION', 'SCIENTIFIC']
- class figrecipe.Diagram(title=None, width_mm=170.0, height_mm=120.0, padding_mm=10.0, gap_mm=None)[source]
Bases:
objectBuilder for rich box-and-arrow diagrams with mm-based coordinates.
- _auto_box_height(box)[source]
Compute box height from content when height_mm is not specified.
- Return type:
- _finalize_canvas_size()[source]
Compute canvas height from element positions when height_mm=None.
- Return type:
- add_arrow(source, target, source_anchor='auto', target_anchor='auto', source_dx=0.0, source_dy=0.0, target_dx=0.0, target_dy=0.0, label=None, style='solid', color=None, curve=0.0, linewidth_mm=0.5, label_offset_mm=None, margin_mm=None)[source]
Add an arrow connecting two boxes.
- Return type:
- add_box(id, title, subtitle=None, content=None, emphasis='normal', shape='rounded', x_mm=None, y_mm=None, width_mm=None, height_mm=None, fill_color=None, border_color=None, title_color=None, padding_mm=5.0, margin_mm=0.0, node_class=None, state=None, language=None, bullet=None)[source]
Add a rich text box. See BoxSpec for node_class/state/language/bullet.
- Return type:
- add_container(id, title=None, children=None, emphasis='muted', x_mm=None, y_mm=None, width_mm=None, height_mm=None, fill_color=None, border_color=None, title_loc='upper center', direction='row', container_gap_mm=8.0, container_padding_mm=8.0, equalize_heights=True, equalize_widths=True)[source]
Add a container. equalize_heights/widths: match children in row/column.
- Return type:
- add_icon(id, source, x_mm, y_mm, width_mm=8.0, height_mm=8.0, color=None, opacity=1.0)[source]
Add an icon (SVG/PNG or built-in: warning/check/cross/info/lock).
- Return type:
- auto_layout(layout='lr', margin_mm=15.0, box_size_mm=None, gap_mm=10.0, avoid_overlap=True, justify='space-between', align_items='center')[source]
Automatically position boxes. See _layout for details.
- Return type:
- classmethod from_dict(data)[source]
Create Diagram from dictionary (recipe reproduction).
- Return type:
- render(ax=None, auto_fix=False, auto_curve=True)[source]
Render. auto_fix=True resolves violations; auto_curve=False skips R7.
- render_to_file(path, dpi=200, save_recipe=True, save_hitmap=True, save_debug=True, watermark=False)
Render, crop, and save. watermark=True adds ‘Plotted by scitex.ai’.
- Return type:
- save(path, dpi=200, save_recipe=True, save_hitmap=True, save_debug=True, watermark=False)[source]
Render, crop, and save. watermark=True adds ‘Plotted by scitex.ai’.
- Return type:
- figrecipe.signature(image_path=None, recipe_path=None)[source]
Compute verification signature for a saved figure.
- figrecipe.caption_with_signature(caption, image_path=None, recipe_path=None, style='short')[source]
Append verification signature to a figure caption.
- Parameters:
- Returns:
Caption with appended signature.
- Return type:
- figrecipe._Graphviz
alias of
Graphviz
- figrecipe._Mermaid
alias of
Mermaid
- figrecipe._get_version(distribution_name)
Get the version string for the named package.
- Parameters:
distribution_name – The name of the distribution package to query.
- Returns:
The version string for the package as defined in the package’s “Version” metadata key.
- figrecipe._rebrand_text(text)
Apply branding to a text string (e.g., docstring).
- Parameters:
text (str or None) – Text to rebrand.
- Returns:
Rebranded text, or None if input was None.
- Return type:
str or None
Examples
>>> os.environ["FIGRECIPE_BRAND"] = "mypackage" >>> os.environ["FIGRECIPE_ALIAS"] = "mp" >>> rebrand_text("import figrecipe as fr") 'import mypackage as mp'
Core Functions
- figrecipe.subplots(nrows=1, ncols=1, axes_width_mm=None, axes_height_mm=None, margin_left_mm=None, margin_right_mm=None, margin_bottom_mm=None, margin_top_mm=None, space_w_mm=None, space_h_mm=None, style=None, apply_style_mm=True, panel_labels=None, **kwargs)[source]
Create a figure with recording-enabled axes.
This is a drop-in replacement for plt.subplots() that wraps the returned figure and axes with recording capabilities.
Supports mm-based layout control for publication-quality figures.
- Parameters:
nrows (int) – Number of rows and columns of subplots.
ncols (int) – Number of rows and columns of subplots.
axes_width_mm (float, optional) – Axes dimensions in mm.
axes_height_mm (float, optional) – Axes dimensions in mm.
margin_left_mm (float, optional) – Left/right margins in mm.
margin_right_mm (float, optional) – Left/right margins in mm.
margin_bottom_mm (float, optional) – Bottom/top margins in mm.
margin_top_mm (float, optional) – Bottom/top margins in mm.
space_w_mm (float, optional) – Horizontal/vertical spacing between axes in mm.
space_h_mm (float, optional) – Horizontal/vertical spacing between axes in mm.
style (dict, optional) – Style configuration dictionary.
apply_style_mm (bool) – If True (default), apply loaded style to axes.
panel_labels (bool or None) – If True, add panel labels (A, B, C, …).
**kwargs – Additional arguments passed to plt.subplots().
- Return type:
Tuple[RecordingFigure,Union[RecordingAxes,ndarray[tuple[int,...],dtype[TypeVar(_ScalarType_co, bound=generic, covariant=True)]]]]- Returns:
fig (RecordingFigure) – Wrapped figure object.
axes (RecordingAxes or ndarray) – Wrapped axes.
- figrecipe.save(fig, path, save_recipe=True, include_data=True, data_format='csv', csv_format='separate', validate=True, validate_mse_threshold=100.0, validate_error_level='error', verbose=True, dpi=None, image_format=None, facecolor=None, save_hitmap=True)[source]
Save a figure as image and recipe. Unified API with fig.savefig().
- Parameters:
fig (RecordingFigure or Figure) – The figure to save.
path (str or Path) – Output path (.png, .pdf, .svg, .yaml, etc.)
save_recipe (bool) – If True (default), save YAML recipe alongside the image.
include_data (bool) – If True (default), save large arrays to separate files.
data_format (str) – Format for data files: ‘csv’, ‘npz’, or ‘inline’.
csv_format (str) – CSV structure: ‘separate’ (default) or ‘single’ (scitex-compatible).
validate (bool) – If True (default), validate reproducibility after saving.
validate_mse_threshold (float) – Maximum acceptable MSE for validation (default: 100).
validate_error_level (str) – How to handle failures: ‘error’, ‘warning’, or ‘debug’.
verbose (bool) – If True (default), print save status.
dpi (int, optional) – DPI for image output.
image_format (str, optional) – Image format when path is YAML.
facecolor (str, optional) – Background color. When opaque, patches are made visible.
save_hitmap (bool) – If True (default), save hitmap image for GUI editor element selection.
- Returns:
If save_recipe=True: (image_path, yaml_path, ValidationResult or None) If save_recipe=False: (image_path, None, None)
- Return type:
- figrecipe.reproduce(path, calls=None, skip_decorations=False, apply_style=True)[source]
Reproduce a figure from a recipe file or bundle.
- Parameters:
path (str or Path) – Path to recipe. Supports multiple formats: - .yaml/.yml file: Direct recipe file - .png/.jpg/etc: Image with associated .yaml - Directory: Bundle containing recipe.yaml - .zip: ZIP bundle (both old recipe.yaml format and new spec.json format)
calls (list of str, optional) – If provided, only reproduce these specific call IDs.
skip_decorations (bool) – If True, skip decoration calls.
apply_style (bool) – If True (default), apply saved style.
- Return type:
- Returns:
fig (matplotlib.figure.Figure) – Reproduced figure.
axes (Axes or list of Axes) – Reproduced axes.
- figrecipe.compose(sources, layout=None, canvas_size_mm=None, gap_mm=5.0, dpi=300, panel_labels=False, label_style='uppercase', **kwargs)[source]
Compose a new figure from multiple sources (recipes or raw images).
Supports two modes automatically detected from sources format:
Grid-based: sources={(row, col): path} Uses layout=(nrows, ncols) for subplot grid.
Mm-based: sources={path: {“xy_mm”: (x, y), “size_mm”: (w, h)}} Uses canvas_size_mm for precise positioning.
- Parameters:
sources (dict) – Either: - Grid-based: {(row, col): source_path} mapping positions to sources - Mm-based: {source_path: {“xy_mm”: (x, y), “size_mm”: (w, h)}}
layout (tuple, optional) – (nrows, ncols) for grid-based composition. Auto-detected if not provided.
canvas_size_mm (tuple, optional) – (width_mm, height_mm) for mm-based composition. Required for mm-based mode.
gap_mm (float) – Gap between panels in mm (for auto-layout modes like ‘horizontal’).
dpi (int) – DPI for the output figure.
panel_labels (bool) – If True, add panel labels (A, B, C…) to each panel.
label_style (str) – ‘uppercase’, ‘lowercase’, or ‘numeric’.
**kwargs – Additional arguments passed to figure creation.
- Return type:
Tuple[RecordingFigure,Union[RecordingAxes,ndarray[tuple[int,...],dtype[TypeVar(_ScalarType_co, bound=generic, covariant=True)]],List[RecordingAxes]]]- Returns:
fig (RecordingFigure) – Composed figure (editable, recordable).
axes (RecordingAxes, ndarray, or list) – Axes of the composed figure.
Examples
Grid-based composition:
>>> fig, axes = fr.compose( ... layout=(1, 2), ... sources={ ... (0, 0): "panel_a.yaml", ... (0, 1): "panel_b.yaml", ... } ... )
Mm-based free-form composition:
>>> fig, axes = fr.compose( ... canvas_size_mm=(180, 120), ... sources={ ... "panel_a.yaml": {"xy_mm": (0, 0), "size_mm": (85, 55)}, ... "panel_b.yaml": {"xy_mm": (90, 0), "size_mm": (85, 55)}, ... "panel_c.yaml": {"xy_mm": (0, 60), "size_mm": (175, 55)}, ... } ... )
- figrecipe.validate(path, mse_threshold=100.0)[source]
Validate that a saved recipe can reproduce its original figure.
- figrecipe.crop(input_path, output_path=None, margin_mm=1.0, margin_px=None, overwrite=False, verbose=False, return_offset=False)[source]
Crop a figure image to its content area with a specified margin.
- Parameters:
input_path (str or Path) – Path to the input image.
output_path (str or Path, optional) – Path to save the cropped image.
margin_mm (float, optional) – Margin in millimeters (default: 1.0mm).
margin_px (int, optional) – Margin in pixels (overrides margin_mm if provided).
overwrite (bool, optional) – Whether to overwrite the input file (default: False)
verbose (bool, optional) – Whether to print detailed information (default: False)
return_offset (bool, optional) – If True, also return crop offset info dict (default: False)
- Returns:
Path to the saved cropped image. If return_offset=True, returns (path, offset_dict).
- Return type:
Path or tuple
Recording Classes
These classes are available via from figrecipe import utils or from figrecipe._wrappers import RecordingFigure, RecordingAxes.
- class figrecipe._wrappers.RecordingFigure(fig, recorder, axes)[source]
Bases:
objectWrapper around matplotlib Figure that manages recording.
- Parameters:
fig (matplotlib.figure.Figure) – The underlying matplotlib figure.
recorder (Recorder) – The recorder instance.
axes (list of RecordingAxes) – Wrapped axes objects.
Examples
>>> import figrecipe as ps >>> fig, ax = ps.subplots() >>> ax.plot([1, 2, 3], [4, 5, 6]) >>> ps.save(fig, "my_figure.yaml")
- property axes: List[List[RecordingAxes]]
Get axes as 2D array.
- property dpi
Proxy dpi to underlying figure.
Needed as a class-level descriptor so matplotlib’s _setattr_cm can do getattr(type(obj), ‘dpi’) during savefig/print_figure.
- draw(renderer)[source]
Proxy draw to underlying figure.
Needed as a class-level method so matplotlib’s _setattr_cm can do getattr(type(obj), ‘draw’) during _get_renderer.
- property flat: List[RecordingAxes]
Get flattened list of all axes.
- property record: FigureRecord
Get the figure record.
- _get_theme_text_color(default='black')[source]
Get text color from loaded style’s theme settings.
- Return type:
- suptitle(t, **kwargs)[source]
Set super title for the figure and record it.
- Parameters:
t (str) – The super title text.
**kwargs – Additional arguments passed to matplotlib’s suptitle().
- Returns:
The matplotlib Text object.
- Return type:
Text
- supxlabel(t, **kwargs)[source]
Set super x-label for the figure and record it.
- Parameters:
t (str) – The super x-label text.
**kwargs – Additional arguments passed to matplotlib’s supxlabel().
- Returns:
The matplotlib Text object.
- Return type:
Text
- supylabel(t, **kwargs)[source]
Set super y-label for the figure and record it.
- Parameters:
t (str) – The super y-label text.
**kwargs – Additional arguments passed to matplotlib’s supylabel().
- Returns:
The matplotlib Text object.
- Return type:
Text
- colorbar(mappable, ax=None, **kwargs)[source]
Add a colorbar and record it for reproduction.
- Return type:
- add_panel_labels(labels=None, loc='upper left', offset=(-0.1, 1.05), fontsize=None, fontweight='bold', **kwargs)[source]
Add panel labels (A, B, C, D, etc.) to multi-panel figures.
- Parameters:
labels (list of str, optional) – Custom labels. If None, uses uppercase letters (A, B, C, …).
loc (str) – Location hint: ‘upper left’ (default), ‘upper right’, ‘lower left’, ‘lower right’.
offset (tuple of float) – (x, y) offset in axes coordinates from the corner. Default is (-0.1, 1.05) for upper left positioning.
fontsize (float, optional) – Font size in points. If None, uses style’s title_pt or 10.
fontweight (str) – Font weight (default: ‘bold’).
**kwargs – Additional arguments passed to ax.text().
- Returns:
The matplotlib Text objects created.
- Return type:
list of Text
Examples
>>> fig, axes = fr.subplots(2, 2) >>> fig.add_panel_labels() # Adds A, B, C, D >>> fig.add_panel_labels(['i', 'ii', 'iii', 'iv']) # Custom labels >>> fig.add_panel_labels(loc='upper right', offset=(1.05, 1.05))
- set_title_metadata(title)[source]
Set figure title metadata (not rendered, stored in recipe).
This is for storing a publication/reference title for the figure, separate from suptitle which is rendered on the figure.
- Parameters:
title (str) – The figure title for publication/reference.
- Returns:
Self for method chaining.
- Return type:
Examples
>>> fig, ax = fr.subplots() >>> fig.set_title_metadata("Effect of temperature on reaction rate") >>> fig.set_caption("Figure 1. Reaction rates measured at various temperatures.")
- set_caption(caption)[source]
Set figure caption metadata (not rendered, stored in recipe).
This is for storing a publication caption for the figure, typically used in scientific papers (e.g., “Fig. 1. Description…”).
- Parameters:
caption (str) – The figure caption text.
- Returns:
Self for method chaining.
- Return type:
Examples
>>> fig, ax = fr.subplots() >>> fig.set_caption("Figure 1. Temperature dependence of reaction rates.")
- set_stats(stats)[source]
Set figure-level statistics metadata (not rendered, stored in recipe).
- Parameters:
stats (dict) – Statistics dictionary (comparisons, summary, correction_method, alpha).
- Return type:
- generate_caption(style='publication', template=None)[source]
Generate caption from stored stats. Styles: publication, brief, detailed.
- Return type:
- savefig(fname, save_recipe=True, include_data=True, data_format='csv', csv_format='separate', validate=True, validate_mse_threshold=100.0, validate_error_level='error', verbose=True, dpi=None, image_format=None, facecolor=None, save_hitmap=True, **kwargs)[source]
Save figure — equivalent to fr.save(). Same DPI, crop, recipe.
Returns (image_path, yaml_path, result). **kwargs passed to matplotlib savefig for file-like objects.
- set_supxyt(xlabel=None, ylabel=None, title=None, **kwargs)[source]
Set supxlabel, supylabel, and suptitle in one call.
- Parameters:
- Return type:
Examples
>>> fig.set_supxyt('Time (s)', 'Amplitude', 'All Channels')
- set_supxytc(xlabel=None, ylabel=None, title=None, caption=None, **kwargs)[source]
Set supxlabel, supylabel, suptitle, and caption in one call.
- Parameters:
- Return type:
Examples
>>> fig.set_supxytc('Time', 'Voltage', 'Neural Data', ... 'Figure 1. Overview of neural recordings.')
- class figrecipe._wrappers.RecordingAxes(ax, recorder, position=(0, 0))[source]
Bases:
RecordingAxesMethods,AxesStyleMixin,SciTexMixin,DiagramMixinWrapper around matplotlib Axes that records all calls.
This wrapper intercepts calls to plotting methods and records them for later reproduction.
- Parameters:
ax (matplotlib.axes.Axes) – The underlying matplotlib axes.
recorder (Recorder) – The recorder instance to log calls to.
position (tuple) – (row, col) position in the figure grid.
Examples
>>> import figrecipe as ps >>> fig, ax = ps.subplots() >>> ax.plot([1, 2, 3], [4, 5, 6], color='red', id='my_line') >>> # The call is recorded automatically
- __dir__()[source]
Return list of attributes for tab completion.
Exposes all matplotlib plotting and decoration methods alongside figrecipe’s custom methods and properties.
- _create_recording_wrapper(method_name, method)[source]
Create a wrapper function that records the call.
- _create_legend_wrapper()[source]
Create wrapper for legend() that applies frame styling and records the call.
- set_caption(caption)[source]
Set panel caption metadata (not rendered, stored in recipe).
- Return type:
- set_stats(stats)[source]
Set panel-level statistics metadata (not rendered, stored in recipe).
- Return type:
- _record_seaborn_call(func_name, args, kwargs, data_arrays, call_id=None)[source]
Record a seaborn plotting call.
- Return type:
- property figure
- property xaxis
- property yaxis
Style Management
- figrecipe.load_style(style='SCITEX', dark=False, background=None)[source]
Load style configuration and apply it globally.
After calling this function, subsequent subplots() calls will automatically use the loaded style (fonts, colors, theme, etc.).
- Parameters:
style (str, Path, bool, or None) – One of: - “SCITEX” / “FIGRECIPE”: Scientific publication style (default) - “MATPLOTLIB”: Vanilla matplotlib defaults - Path to custom YAML file: “/path/to/my_style.yaml” - None or False: Unload style (reset to matplotlib defaults)
dark (bool, optional) – If True, apply dark theme transformation (default: False). Equivalent to appending “_DARK” to preset name.
background (str, optional) – Override default background color. E.g., ‘white’ for opaque figures. Sets theme.light.figure_bg and theme.light.axes_bg. Use ‘transparent’ for transparent background.
- Returns:
Style configuration with dot-notation access. Returns None if style is unloaded.
- Return type:
DotDict or None
Examples
>>> import figrecipe as fr
>>> # Load scientific style (default) >>> fr.load_style() >>> fr.load_style("SCITEX") # explicit
>>> # Load with white background (override transparent default) >>> fr.load_style("SCITEX", background='white')
>>> # Load dark theme >>> fr.load_style("SCITEX_DARK") >>> fr.load_style("SCITEX", dark=True) # equivalent
>>> # Reset to vanilla matplotlib >>> fr.load_style(None) # unload >>> fr.load_style(False) # unload >>> fr.load_style("MATPLOTLIB") # explicit vanilla
>>> # Access style values >>> style = fr.load_style("SCITEX") >>> style.axes.width_mm 40
- figrecipe.unload_style()[source]
Unload the current style and reset to matplotlib defaults.
After calling this, subsequent subplots() calls will use vanilla matplotlib behavior without FigRecipe styling.
Examples
>>> import figrecipe as fr >>> fr.load_style("SCITEX") # Apply scientific style >>> fig, ax = fr.subplots() # Styled >>> fr.unload_style() # Reset to matplotlib defaults >>> fig, ax = fr.subplots() # Vanilla matplotlib
Alignment Functions
- figrecipe.align_panels(fig, panels, mode, reference=None)[source]
Align multiple panels to a reference panel.
- Parameters:
fig (RecordingFigure) – The figure containing the panels.
panels (list of tuple) – List of (row, col) positions to align.
mode (str or AlignmentMode) – Alignment mode: ‘left’, ‘right’, ‘top’, ‘bottom’, ‘center_h’, ‘center_v’, ‘axis_x’, ‘axis_y’.
reference (tuple, optional) – Reference panel position. If None, uses first panel.
- Return type:
Examples
>>> import figrecipe as fr >>> fig, axes = fr.subplots(2, 2) >>> # Align left column panels to left edge >>> fr.align_panels(fig, [(0, 0), (1, 0)], mode="left")
- figrecipe.align_smart(fig, panels=None)[source]
Automatically align panels in a compact grid layout.
Works like human behavior: 1. Detect grid structure (nrows, ncols) 2. Place panels from top-left to bottom-right 3. Calculate minimum rectangle to cover all content in each row/column 4. Unify row heights and column widths 5. Use space effectively with theme margins and spacing
Uses margin and spacing values from the loaded SCITEX theme: - margins.left_mm, margins.right_mm, margins.top_mm, margins.bottom_mm - spacing.horizontal_mm, spacing.vertical_mm
- Parameters:
fig (RecordingFigure) – The figure containing the panels.
panels (list of tuple, optional) – Specific panels to align. If None, aligns all panels.
- Return type:
Examples
>>> import figrecipe as fr >>> fig, axes = fr.subplots(2, 2) >>> # ... add plots ... >>> fr.align_smart(fig) # Align all panels using theme settings
- figrecipe.distribute_panels(fig, panels, direction='horizontal', spacing_mm=None)[source]
Distribute panels evenly with optional fixed spacing.
- Parameters:
fig (RecordingFigure) – The figure containing the panels.
panels (list of tuple) – List of (row, col) positions to distribute.
direction (str) – ‘horizontal’ or ‘vertical’.
spacing_mm (float, optional) – Fixed spacing in mm. If None, distribute evenly within current bounds.
- Return type:
Examples
>>> import figrecipe as fr >>> fig, axes = fr.subplots(1, 3) >>> # Distribute evenly >>> fr.distribute_panels(fig, [(0, 0), (0, 1), (0, 2)]) >>> # With fixed 5mm spacing >>> fr.distribute_panels(fig, [(0, 0), (0, 1), (0, 2)], spacing_mm=5)
GUI Editor
- figrecipe.gui(source=None, style=None, port=5050, host='127.0.0.1', open_browser=True, hot_reload=False, working_dir=None, desktop=False)[source]
Launch interactive GUI editor for figure styling.
- Parameters:
source (RecordingFigure, str, Path, or None) – Either a live RecordingFigure object, path to a .yaml recipe file, or None to create a new blank figure.
style (str or dict, optional) – Style preset name or style dict.
port (int, optional) – Django server port (default: 5050).
host (str, optional) – Host to bind server (default: “127.0.0.1”, use “0.0.0.0” for Docker).
open_browser (bool, optional) – Whether to open browser automatically (default: True).
hot_reload (bool, optional) – Enable hot reload (default: False).
working_dir (str or Path, optional) – Working directory for file browser (default: directory containing source).
desktop (bool, optional) – Launch as native desktop window using pywebview (default: False). Requires: pip install figrecipe[desktop]
- Returns:
Final style overrides after editing session.
- Return type:
Diagram Class
- class figrecipe.Diagram(title=None, width_mm=170.0, height_mm=120.0, padding_mm=10.0, gap_mm=None)[source]
Builder for rich box-and-arrow diagrams with mm-based coordinates.
- add_box(id, title, subtitle=None, content=None, emphasis='normal', shape='rounded', x_mm=None, y_mm=None, width_mm=None, height_mm=None, fill_color=None, border_color=None, title_color=None, padding_mm=5.0, margin_mm=0.0, node_class=None, state=None, language=None, bullet=None)[source]
Add a rich text box. See BoxSpec for node_class/state/language/bullet.
- Return type:
- add_container(id, title=None, children=None, emphasis='muted', x_mm=None, y_mm=None, width_mm=None, height_mm=None, fill_color=None, border_color=None, title_loc='upper center', direction='row', container_gap_mm=8.0, container_padding_mm=8.0, equalize_heights=True, equalize_widths=True)[source]
Add a container. equalize_heights/widths: match children in row/column.
- Return type:
- add_arrow(source, target, source_anchor='auto', target_anchor='auto', source_dx=0.0, source_dy=0.0, target_dx=0.0, target_dy=0.0, label=None, style='solid', color=None, curve=0.0, linewidth_mm=0.5, label_offset_mm=None, margin_mm=None)[source]
Add an arrow connecting two boxes.
- Return type:
- add_icon(id, source, x_mm, y_mm, width_mm=8.0, height_mm=8.0, color=None, opacity=1.0)[source]
Add an icon (SVG/PNG or built-in: warning/check/cross/info/lock).
- Return type:
- validate_containers()[source]
Check every container fully encloses its declared children.
- Return type:
- auto_layout(layout='lr', margin_mm=15.0, box_size_mm=None, gap_mm=10.0, avoid_overlap=True, justify='space-between', align_items='center')[source]
Automatically position boxes. See _layout for details.
- Return type:
- _auto_box_height(box)[source]
Compute box height from content when height_mm is not specified.
- Return type:
- _finalize_canvas_size()[source]
Compute canvas height from element positions when height_mm=None.
- Return type:
- render(ax=None, auto_fix=False, auto_curve=True)[source]
Render. auto_fix=True resolves violations; auto_curve=False skips R7.
- save(path, dpi=200, save_recipe=True, save_hitmap=True, save_debug=True, watermark=False)[source]
Render, crop, and save. watermark=True adds ‘Plotted by scitex.ai’.
- Return type:
- render_to_file(path, dpi=200, save_recipe=True, save_hitmap=True, save_debug=True, watermark=False)
Render, crop, and save. watermark=True adds ‘Plotted by scitex.ai’.
- Return type: