FigRecipe API Reference

The full public surface of figrecipe is documented inline below via automodule. The __all__ declaration in figrecipe/__init__.py is the single source of truth for what appears here; do NOT add explicit autofunction / autoclass directives below — Sphinx already discovers them through automodule :members: and a second declaration triggers duplicate object description warnings (treated as errors on PR builds).

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()

Notes

Submodules:

  • 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[Any, ...], dtype[TypeVar(_ScalarT, bound= generic)]]]]

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', validate_axis_range_alignment=True, validate_axis_range_alignment_error_level='warning', verbose=True, dpi=None, image_format=None, facecolor=None, save_hitmap=False, save_editable=False)[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’.

  • validate_axis_range_alignment (bool) – If True (default), run the runtime axis_range_alignment check on the rendered figure. Catches the autoscale-with- different-data case that the static STX-FIG001 lint misses.

  • validate_axis_range_alignment_error_level (str) – Dispatch level for the axis-range-alignment check: ‘warning’ (default), ‘error’, or ‘debug’ (silent).

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

  • save_editable (bool) – If True, write the editable-figure JSON (schema scitex.plt.figure.editable) to <stem>.json next to the image. Default False — opt in for the GUI / web editor.

Returns:

If save_recipe=True: (image_path, yaml_path, ValidationResult or None) If save_recipe=False: (image_path, None, None)

Return type:

tuple

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:

Tuple[Figure, Union[Axes, List[Axes]]]

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:

Tuple[Figure, Union[Axes, List[Axes]]]

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=2.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:

  1. Grid-based: sources={(row, col): path} Uses layout=(nrows, ncols) for subplot grid.

  2. 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[Any, ...], dtype[TypeVar(_ScalarT, bound= generic)]], 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:

None

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:

None

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:

None

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:

dict

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.info(path)[source]

Get information about a recipe without reproducing.

Return type:

Dict[str, Any]

figrecipe.validate(path, mse_threshold=100.0)[source]

Validate that a saved recipe can reproduce its original figure.

Parameters:
  • path (str or Path) – Path to .yaml recipe file.

  • mse_threshold (float) – Maximum acceptable MSE for validation to pass (default: 100).

Returns:

Detailed comparison results.

Return type:

ValidationResult

figrecipe.extract_data(path)[source]

Extract data arrays from a saved recipe.

Returns:

Nested dictionary: {call_id: {‘x’: array, ‘y’: array, …}}

Return type:

dict

figrecipe.add_qr_to_figure(fig, metadata, position='bottom-right', size=0.08)[source]

Add a minimal QR code to a matplotlib figure.

Parameters:
  • fig (matplotlib.figure.Figure) – Target figure to overlay onto.

  • metadata (dict) – Payload to encode. If "url" is absent, "https://scitex.ai" is added so the QR resolves to something even when consumers don’t provide one.

  • position (str) – One of "bottom-right", "bottom-left", "top-right", "top-left". Unknown values fall back to "bottom-right".

  • size (float) – Relative size of the QR overlay (fraction of figure width).

Returns:

The same figure, with a QR overlay axes added. If the optional qrcode / Pillow dependencies are not installed, the figure is returned unmodified and a warning is logged.

Return type:

matplotlib.figure.Figure

class figrecipe.Figz(path)[source]

Bases: object

Multi-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)
__init__(path)[source]
classmethod create(path, name, size_mm=None)[source]

Create a new empty .fig.zip bundle.

Parameters:
  • path (str or Path) – Output path (should end in .fig.zip).

  • name (str) – Figure name / ID.

  • size_mm (dict, optional) – Canvas size e.g. {“width_mm”: 170, “height_mm”: 120}.

Returns:

Loaded Figz instance.

Return type:

Figz

save()[source]

Save spec/style changes back to bundle.

Return type:

None

add_panel(label, pltz_source, position=None, size=None)[source]

Add a .plt.zip panel to this figure.

Parameters:
  • label (str) – Panel label (e.g., “A”, “B”).

  • pltz_source (bytes, str, or Path) – Panel bytes or path to a .plt.zip file.

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

None

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:

None

remove_panel(label)[source]

Remove a panel (rebuilds ZIP).

Parameters:

label (str) – Panel label to remove.

Return type:

None

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

Parameters:

label (str) – Panel label.

Returns:

Loaded Pltz instance for the panel.

Return type:

Pltz

get_panel_pltz(panel_id)[source]

Get panel as raw bytes.

Parameters:

panel_id (str) – Panel label.

Returns:

Raw .plt.zip bytes, or None if panel not found.

Return type:

bytes or None

list_panel_ids()[source]

List panel labels in order.

Returns:

Panel labels.

Return type:

list of str

get_panel_data(panel_id)[source]

Get panel’s CSV data as DataFrame.

Parameters:

panel_id (str) – Panel label.

Return type:

DataFrame or None

render_preview()[source]

Return preview of first panel as PNG bytes.

Return type:

bytes or None

class figrecipe.Pltz(path)[source]

Bases: object

Single-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
__init__(path)[source]
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:
  • png_bytes (bytes) – PNG image data.

  • path (str or Path) – Output path for the .plt.zip file.

  • plot_type (str, optional) – Plot type label stored in spec.json (default: “image”).

  • spec (dict, optional) – Additional spec entries (default: {}).

  • style (dict, optional) – Style entries (default: {}).

Returns:

Loaded Pltz instance wrapping the saved bundle.

Return type:

Pltz

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:

Pltz

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

save()[source]

Save spec/style changes back to bundle in-place.

Updates spec.json and style.json inside the ZIP without re-rendering the figure.

Return type:

None

update_preview()[source]

Re-render and update preview PNG in bundle.

Return type:

None

reproduce()[source]

Reproduce figure from bundle.

Returns:

(fig, axes) reproduced from bundle.

Return type:

tuple

figrecipe.save_bundle(fig, path, dpi=None, image_formats=None, save_hitmap=False, 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   # only if save_hitmap=True
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 the per-pixel hitmap PNG used by the GUI editor for diff visualisation (default: False). Hitmap rendering is expensive and the typical save() caller doesn’t need it; opt in with save_hitmap=True when persisting bundles for the editor.

  • verbose (bool) – Whether to print status (default: True).

Returns:

Path to saved ZIP bundle.

Return type:

Path

figrecipe.load_bundle(path)[source]

Load bundle components from ZIP file.

Parameters:

path (str or Path) – Path to bundle ZIP file.

Returns:

(spec, style, data) where data is DataFrame or None.

Return type:

tuple

figrecipe.reproduce_bundle(path, apply_style=True)[source]

Reproduce figure from bundle.

Parameters:
  • path (str or Path) – Path to bundle (ZIP file or directory).

  • apply_style (bool) – Whether to apply saved style (default: True).

Returns:

(fig, axes) reproduced from bundle.

Return type:

tuple

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.

Returns:

Names of available presets.

Return type:

list of str

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

Builder for rich box-and-arrow diagrams with mm-based coordinates.

__init__(title=None, width_mm=170.0, height_mm=120.0, padding_mm=10.0, gap_mm=None)[source]
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:

Diagram

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:

Diagram

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:

Diagram

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:

Diagram

validate_containers()[source]

Check every container fully encloses its declared children.

Return type:

None

validate_no_overlap()[source]

Check that no two boxes overlap each other.

Return type:

None

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:

Diagram

_auto_box_height(box)[source]

Compute box height from content when height_mm is not specified.

Return type:

float

_finalize_canvas_size()[source]

Compute canvas height from element positions when height_mm=None.

Return type:

None

_get_anchor(pos, anchor)[source]

Get absolute position of an anchor point on the visual box edge.

Return type:

Tuple[float, float]

_auto_anchor(src, tgt)[source]

Determine best anchor points automatically.

Return type:

Tuple[str, str]

render(ax=None, auto_fix=False, auto_curve=True)[source]

Render. auto_fix=True resolves violations; auto_curve=False skips R7.

Return type:

Tuple[Figure, Axes]

save(path, dpi=200, save_recipe=True, save_hitmap=False, save_debug=True, watermark=False)[source]

Render, crop, and save. watermark=True adds ‘Plotted by scitex.ai’.

Return type:

Path

render_to_file(path, dpi=200, save_recipe=True, save_hitmap=False, save_debug=True, watermark=False)

Render, crop, and save. watermark=True adds ‘Plotted by scitex.ai’.

Return type:

Path

to_dict()[source]

Convert diagram to dictionary for serialization.

Return type:

Dict[str, Any]

classmethod from_dict(data)[source]

Create Diagram from dictionary (recipe reproduction).

Return type:

Diagram

figrecipe.build_spec(params)[source]

Convert a parameter dict to a figrecipe spec dict.

Parameters:

params (dict) – Flat parameter dict. Required key: kind. For XY plots: x, y (comma-separated floats or strings). For distributions: data, data2 .. data6, labels. For pie: data, labels. For heatmap: data, nrows, ncols. Optional: color, title, xlabel, ylabel, width, height, yerr.

Returns:

Figrecipe-compatible spec.

Return type:

dict

Raises:

ValueError – If required parameters are missing or kind is unsupported.

figrecipe.build_spec_from_csv(csv_path, params)[source]

Build a figrecipe spec from a CSV file path and parameters.

Uses figrecipe’s native data_file + column name resolution.

Parameters:
  • csv_path (str or Path) – Path to the CSV file.

  • params (dict) – Flat parameter dict. Required: kind. For XY: x_col, y_col. For distributions: data_col. For pie: data_col, labels_col. For heatmap: data_col.

Returns:

Figrecipe-compatible spec.

Return type:

dict

Raises:

ValueError – If required parameters are missing or kind is unsupported.

figrecipe.render_spec_to_bytes(spec, *, dpi=300, fmt='png', facecolor='white')[source]

Render a figrecipe spec dict to image bytes.

Parameters:
  • spec (dict) – Figrecipe-compatible spec dict (as produced by build_spec).

  • dpi (int) – Output resolution (default 300).

  • fmt (str) – Image format: "png", "pdf", or "svg" (default "png").

  • facecolor (str) – Background colour (default "white").

Returns:

Encoded image bytes.

Return type:

bytes

figrecipe.termplot(*args)[source]

Plot y (and optional x) values in the terminal using termplotlib.

Parameters:

*args – Either (y,) — plotted against its indices — or (x, y, ...) where extra positional arguments are ignored.

Returns:

Displays the plot in the terminal.

Return type:

None

figrecipe.draw_graph(ax, G, *, layout='spring', pos=None, seed=42, node_size=100, node_color='#3498db', node_alpha=0.8, node_shape='o', node_edgecolors='white', node_linewidths=0.34, edge_width=0.34, edge_color='gray', edge_alpha=0.5, edge_style='solid', arrows=None, arrowsize=10, arrowstyle='-|>', connectionstyle='arc3,rad=0.0', labels=False, font_size=6, font_color='black', font_weight='normal', font_family='sans-serif', colormap='viridis', vmin=None, vmax=None, **layout_kwargs)[source]

Draw a NetworkX graph on matplotlib axes.

Parameters:
  • ax (matplotlib.axes.Axes) – The axes to draw on.

  • G (networkx.Graph) – The graph to draw.

  • layout (str) – Layout algorithm: ‘spring’, ‘circular’, ‘kamada_kawai’, ‘shell’, ‘spectral’, ‘random’, ‘planar’, ‘spiral’, ‘hierarchical’.

  • pos (dict, optional) – Pre-computed node positions {node: (x, y)}.

  • seed (int) – Random seed for layout reproducibility.

  • node_size (str, callable, or float) – Node sizes. Can be attribute name, callable (node, data) -> size, or scalar.

  • node_color (str, callable, or any) – Node colors. Can be attribute name, callable, color name, or array.

  • node_alpha (float) – Node transparency.

  • node_shape (str) – Node marker shape.

  • edge_width (str, callable, or float) – Edge widths. Can be attribute name, callable (u, v, data) -> width, or scalar.

  • edge_color (str, callable, or any) – Edge colors.

  • edge_alpha (float) – Edge transparency.

  • arrows (bool, optional) – Draw arrows for directed graphs. Auto-detected if None.

  • arrowsize (float) – Arrow head size for directed edges.

  • labels (bool, dict, or str) – Node labels. True for node IDs, dict for custom labels, str for attribute name.

  • font_size (float) – Label font size (default 6pt for scitex).

  • colormap (str) – Matplotlib colormap for numeric node colors.

  • **layout_kwargs – Additional kwargs passed to layout algorithm.

Returns:

Dictionary with ‘pos’, ‘node_collection’, ‘edge_collection’.

Return type:

dict

figrecipe.smart_align(fig, panels=None)

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:

None

Examples

>>> import figrecipe as fr
>>> fig, axes = fr.subplots(2, 2)
>>> # ... add plots ...
>>> fr.align_smart(fig)  # Align all panels using theme settings
figrecipe.edit(source=None, style=None, port=5050, host='127.0.0.1', open_browser=True, hot_reload=False, working_dir=None, desktop=False)

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:

dict

figrecipe.export_editable(fig, title='', description='', include_full_paths=False, simplify_threshold=0.5)

Export a matplotlib figure with geometry data for interactive editing.

This produces a Schema v0.3 compliant dictionary with axes-local pixel coordinates for all visual elements, suitable for shape-based hit testing.

Parameters:
  • fig (matplotlib.figure.Figure or scitex.plt.FigureWrapper) – The figure to export

  • title (str) – Optional title for the figure metadata

  • description (str) – Optional description for the figure metadata

  • include_full_paths (bool) – If True, include full (unsimplified) paths for lines. Default False.

  • simplify_threshold (float) – Maximum pixel error for path simplification. Default 0.5.

Returns:

Schema v0.3 compliant dictionary with structure: - scitex_schema: “scitex.plt.figure.editable” - scitex_schema_version: “0.3.0” - figure: {size_px, dpi, …} - axes: {ax_id: {bbox_px, …}, …} - elements: {elem_id: {geometry_px, style, …}, …} - statistics: {} (placeholder for stats integration) - data: {} (placeholder for linked data) - output: {} (rendering metadata)

Return type:

dict

figrecipe.enable_svg()[source]

Manually enable SVG format for Jupyter notebook display.

Call this if figures appear pixelated in notebooks.

Examples

>>> import figrecipe as fr
>>> fr.enable_svg()  # Enable SVG rendering
>>> fig, ax = fr.subplots()  # Now renders as crisp SVG
figrecipe.apply_style(ax, style=None)[source]

Apply mm-based styling to an axes.

Parameters:
  • ax (matplotlib.axes.Axes) – Target axes to apply styling to.

  • style (dict or DotDict, optional) – Style configuration. If None, uses default FIGRECIPE_STYLE.

Returns:

Trace line width in points.

Return type:

float

Examples

>>> import figrecipe as ps
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots()
>>> trace_lw = ps.apply_style(ax)
>>> ax.plot(x, y, lw=trace_lw)
figrecipe.signature(image_path=None, recipe_path=None)[source]

Compute verification signature for a saved figure.

Parameters:
  • image_path (str or Path, optional) – Path to the saved image file.

  • recipe_path (str or Path, optional) – Path to the saved recipe YAML file.

Returns:

Signature with keys: image_hash, recipe_hash, image_path, recipe_path.

Return type:

dict

figrecipe.caption_with_signature(caption, image_path=None, recipe_path=None, style='short')[source]

Append verification signature to a figure caption.

Parameters:
  • caption (str) – Original caption text.

  • image_path (str or Path, optional) – Path to the saved image.

  • recipe_path (str or Path, optional) – Path to the saved recipe YAML.

  • style (str) – ‘short’ (default): hash only. ‘full’: includes “Generated by figrecipe” prefix.

Returns:

Caption with appended signature.

Return type:

str

Recording Wrappers (internal)

These classes back the public subplots() return value. They live under figrecipe._wrappers rather than the top-level namespace, so they’re documented here separately.

class figrecipe._wrappers.RecordingFigure(fig, recorder, axes)[source]

Bases: object

Wrapper around matplotlib Figure that manages recording.

Parameters:

Examples

>>> import figrecipe as ps
>>> fig, ax = ps.subplots()
>>> ax.plot([1, 2, 3], [4, 5, 6])
>>> ps.save(fig, "my_figure.yaml")
__init__(fig, recorder, axes)[source]
_on_draw_finalize(event)[source]

Apply figrecipe finalize hooks once per figure lifetime.

Run-once: setting a new locator marks the canvas stale, which on the inline notebook backend triggers another draw and a SECOND inline render of the same figure. We only need to finalize once per figure — cache the flag and short-circuit on subsequent draws.

Re-entrancy guard: finalize_ticks may swap a locator, which on some backends triggers another draw and would recurse. The flag breaks the loop.

property fig: Figure

Get the underlying matplotlib figure.

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_style_fontsize(key, default)[source]

Get fontsize from loaded style.

Return type:

float

_get_theme_text_color(default='black')[source]

Get text color from loaded style’s theme settings.

Return type:

str

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

text(x, y, s, **kwargs)[source]

Place text on the figure and record it.

Proxy for matplotlib.figure.Figure.text that also captures the call in the recipe so reproduce() can replay it. Without this, fig.text annotations would be rendered in the original figure but missing from the reproduction, leading to dimension mismatches during reproducibility validation.

Parameters:
  • x (float) – Position in figure coordinates.

  • y (float) – Position in figure coordinates.

  • s (str) – The text string.

  • **kwargs – Additional arguments passed to matplotlib’s fig.text().

Returns:

The matplotlib Text object.

Return type:

Text

colorbar(mappable, ax=None, **kwargs)[source]

Add a colorbar and record it for reproduction.

Return type:

Any

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:

RecordingFigure

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:

RecordingFigure

Examples

>>> fig, ax = fr.subplots()
>>> fig.set_caption("Figure 1. Temperature dependence of reaction rates.")
property title_metadata: str | None

Get the figure title metadata.

property caption: str | None

Get the figure caption metadata.

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:

RecordingFigure

property stats: Dict[str, Any] | None

Get the figure-level statistics metadata.

generate_caption(style='publication', template=None)[source]

Generate caption from stored stats. Styles: publication, brief, detailed.

Return type:

str

__getattr__(name)[source]

Delegate attribute access to underlying figure.

Return type:

Any

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=False, **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:
  • xlabel (str, optional)

  • ylabel (str, optional)

  • title (str, optional)

  • **kwargs (dict) – Passed to the underlying methods.

Return type:

RecordingFigure

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:
  • xlabel (str, optional)

  • ylabel (str, optional)

  • title (str, optional)

  • caption (str, optional) – Figure caption metadata (stored in recipe, not rendered).

  • **kwargs (dict) – Passed to the underlying methods.

Return type:

RecordingFigure

Examples

>>> fig.set_supxytc('Time', 'Voltage', 'Neural Data',
...                 'Figure 1. Overview of neural recordings.')
save_recipe(path, include_data=True, data_format='csv', csv_format='separate')[source]

Save the recording recipe to YAML.

Parameters:
  • path (str or Path) – Output path for the recipe file.

  • include_data (bool) – If True, save array data alongside recipe.

  • data_format (str) – Format for data files: ‘csv’ (default), ‘npz’, or ‘inline’.

  • csv_format (str) – CSV structure: ‘separate’ (default) or ‘single’ (scitex-compatible).

Return type:

Path

class figrecipe._wrappers.RecordingAxes(ax, recorder, position=(0, 0))[source]

Bases: RecordingAxesMethods, AxesStyleMixin, SciTexMixin, DiagramMixin

Wrapper 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
__init__(ax, recorder, position=(0, 0))[source]
property ax: Axes

Get the underlying matplotlib axes.

property position: Tuple[int, int]

Get axes position in grid.

__getattr__(name)[source]

Intercept attribute access to wrap methods.

Return type:

Any

__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_bar_wrapper()[source]

Create wrapper for bar() with SCITEX error bar styling.

_create_boxplot_wrapper()[source]

Create wrapper for boxplot() with patch_artist=True default.

_create_stem_wrapper()[source]

Create wrapper for stem() that accepts color kwarg.

_create_legend_wrapper()[source]

Build the legend() wrapper that handles SCITEX styling + figrecipe loc extensions + recording. Implementation lives in _legend_wrapper.py so this file stays focused.

set_caption(caption)[source]

Set panel caption metadata (not rendered, stored in recipe).

Return type:

RecordingAxes

property panel_caption: str | None

Get the panel caption metadata.

set_stats(stats)[source]

Set panel-level statistics metadata (not rendered, stored in recipe).

Return type:

RecordingAxes

property stats: Dict[str, Any] | None

Get the panel-level statistics metadata.

_no_record()[source]

Context manager to temporarily disable recording (internal).

_record_seaborn_call(func_name, args, kwargs, data_arrays, call_id=None)[source]

Record a seaborn plotting call.

Return type:

None

property figure
property xaxis
property yaxis
get_xlim()[source]
get_ylim()[source]
get_xlabel()[source]
get_ylabel()[source]
get_title()[source]
property caption: str | None

Get the panel caption metadata.

generate_panel_caption(label=None, style='publication')[source]

Generate a caption for this panel from stats metadata.

Return type:

str