spacr.qt.widgets.figure_settings

Restyle and export live Matplotlib figures from the Qt interface.

The settings dialog builds its controls from the artists present in a figure, so only applicable options are shown. It can update data-dependent properties, such as axis scales, without rerunning the analysis. This module also manages reusable graph-style files and optional data, statistics, and caption sidecars.

Classes

FigureSettingsDialog

Edit the supported appearance settings of a live figure.

FigureStylePreferences

Edit general and graph-specific figure-style preferences.

Functions

add_graph_style_file_entries(→ None)

Add graph-style save and load actions to a menu.

apply_font_colour(→ int)

Apply one colour to every text object in a figure.

apply_graph_style(→ None)

Save graph-style overrides as the active preferences.

apply_line_colour(→ int)

Apply one colour to figure lines, spines, and tick marks.

build_figure_context_menu(→ PySide6.QtWidgets.QMenu)

Build the context menu for a displayed figure.

derive_replot_recipe(figure)

Derive a grouped-plot recipe from an existing matplotlib figure.

export_sidecars(→ list)

Export available figure data, statistics, and caption sidecars.

figure_follows_the_theme(→ None)

Restore line and font colours from the active theme preferences.

figure_line_artists(→ list)

Collect artists affected by the global line-colour control.

graph_style_as_dict(→ dict)

Serialize graph-style preference overrides to a dictionary.

load_graph_style(→ tuple)

Read graph-style preference overrides from a JSON file.

save_figure_as(→ str)

Save a figure using its current styling and export preferences.

save_figure_bundle(→ str)

Export a Matplotlib figure with its source data and statistics.

save_graph_style(→ str)

Write graph-style preference overrides to a JSON file.

style_choices_for(→ tuple)

Return the choices available for a style setting.

style_setting_label(→ str)

Convert a style setting name to a display label.

Module Contents

class spacr.qt.widgets.figure_settings.FigureSettingsDialog(figure, parent=None, *, on_change: Callable | None = None, propagate_callback: Callable | None = None)[source]

Bases: PySide6.QtWidgets.QDialog

Edit the supported appearance settings of a live figure.

Controls are created from the figure’s current axes, artists, legends, and optional spaCR metadata. Changes are previewed after a short debounce; rejecting the dialog restores the opening state when it could be captured.

Build the figure settings dialog with a live preview.

A pickled snapshot of the figure is taken so Cancel has something to go back to: live apply with no way out is a trap – the user drags a spin box to see what it does and there is no longer an “as it was”. The per-figure text-size override is kept separately, because Cancel restores the figure by copying axes out of the snapshot rather than by swapping the object, so that attribute would otherwise survive an undo of everything it applies to.

The Statistics tab appears only for a figure that compares groups: one offering a t-test on a Q-Q plot would be an invitation to report a number that means nothing. The UMAP tab appears only for a figure carrying the embedding it was drawn from – without it, “live” would mean re-running the reduction and every point would move.

Parameters:
  • figure – the matplotlib figure to restyle.

  • parent – parent widget, or None.

  • on_change – called to redraw; takes preview when it can.

  • propagate_callback – writes the values into the owning module’s settings panel. None disables Propagate and says why.

closeEvent(event)[source]

Complete a full-quality redraw before closing the dialog.

Parameters:

event (PySide6.QtGui.QCloseEvent) – Qt close event forwarded to the parent implementation.

eventFilter(obj, event)[source]

Prevent unfocused inputs from consuming scroll-wheel events.

Parameters:
  • obj (PySide6.QtCore.QObject) – Object receiving the event.

  • event (PySide6.QtCore.QEvent) – Event being filtered.

Returns:

bool – True when an unfocused input’s wheel event was consumed; otherwise the result from the parent event filter.

reject()[source]

Restore the opening figure state and close the dialog.

Restoration is best-effort when the figure could not be serialized or an artist cannot be reconstructed.

umap_values() → dict[source]

Return the current Image UMAP figure settings.

Returns:

dict – Current settings, or an empty dictionary when the figure has no Image UMAP controls.

class spacr.qt.widgets.figure_settings.FigureStylePreferences(general=None, per_graph=None, parent=None)[source]

Bases: PySide6.QtWidgets.QWidget

Edit general and graph-specific figure-style preferences.

General settings apply to every figure. Each graph type can override only the settings it needs, and the panel stores differences from package defaults rather than a fully resolved style.

Build the figure-style preference page.

Parameters:
  • general – the saved general style values; missing keys fall back to the shipped defaults.

  • per_graph – saved per-graph-kind overrides, keyed by kind.

  • parent – parent widget, or None.

apply_values(general=None, per_graph=None) → None[source]

Load style overrides into the preference controls.

Parameters:
  • general (mapping, optional) – General style overrides.

  • per_graph (mapping of str to mapping, optional) – Style overrides keyed by graph type.

Notes

A control omitted from the supplied mappings is reset to its package default rather than retaining its previous value.

reset() → None[source]

Reset every style control to its package default.

select_kind(kind: str) → None[source]

Display the preference page for one graph type.

Parameters:

kind (str) – Graph type from spacr.figure_style.GRAPH_KINDS. Unknown values leave the current page unchanged.

values() → tuple[source]

Return style settings that differ from package defaults.

Returns:

  • general (dict) – General style overrides.

  • per_graph (dict) – Non-default style settings keyed by graph type. Graph types with no overrides are omitted.

spacr.qt.widgets.figure_settings.add_graph_style_file_entries(menu, parent=None, *, on_change=None) → None[source]

Add graph-style save and load actions to a menu.

Parameters:
  • menu (PySide6.QtWidgets.QMenu) – Menu that receives the actions.

  • parent (PySide6.QtWidgets.QWidget, optional) – Parent for file dialogs and actions. If None, use menu.

  • on_change (callable, optional) – Callback invoked after a style is loaded. Callbacks may accept a preview keyword argument.

spacr.qt.widgets.figure_settings.apply_font_colour(figure, colour) → int[source]

Apply one colour to every text object in a figure.

Parameters:
Returns:

int – Number of text objects successfully updated. This includes titles, axes labels, tick labels, legends, and annotations.

spacr.qt.widgets.figure_settings.apply_graph_style(general, per_graph) → None[source]

Save graph-style overrides as the active preferences.

Parameters:
  • general (mapping) – General style overrides.

  • per_graph (mapping of str to mapping) – Style overrides keyed by graph type. Values that are not mappings are omitted.

spacr.qt.widgets.figure_settings.apply_line_colour(figure, colour) → int[source]

Apply one colour to figure lines, spines, and tick marks.

Line styles and dash patterns are preserved. Gridlines and text are not changed.

Parameters:
Returns:

int – Number of line, spine, and legend artists successfully updated. Tick marks are updated separately and are not included in this count.

spacr.qt.widgets.figure_settings.build_figure_context_menu(parent, figure, *, on_change=None, open_settings=None) → PySide6.QtWidgets.QMenu[source]

Build the context menu for a displayed figure.

The menu provides direct legend, grid, scale, colour, and export actions. Figures with grouped-plot metadata can also be redrawn as another plot type. More detailed controls are delegated to open_settings.

Parameters:
  • parent (PySide6.QtWidgets.QWidget) – Parent for the returned menu and its dialogs.

  • figure (matplotlib.figure.Figure or None) – Figure to edit. If None, the menu contains a disabled status action.

  • on_change (callable, optional) – Callback invoked after a direct edit. Callbacks may accept a preview keyword argument or a replacement figure.

  • open_settings (callable, optional) – Callback invoked by the Figure settings action.

Returns:

PySide6.QtWidgets.QMenu – Context menu owned by parent.

spacr.qt.widgets.figure_settings.derive_replot_recipe(figure)[source]

Derive a grouped-plot recipe from an existing matplotlib figure.

This fallback supports figures without a _spacr_replot payload by reading plotted values from bars, scatter collections, and data lines on a single axes. Artist-derived data are exact for bar heights and point coordinates but are necessarily lossy for summary artists such as box or violin plots, which do not retain their source observations. Figures created by spacr.plot.create_grouped_plot() use their attached source frame instead of this fallback.

Parameters:

figure – Matplotlib Figure containing exactly one axes.

Returns:

Recipe dictionary for spacr.plot.create_grouped_plot(), or None when sufficient plottable values cannot be recovered.

spacr.qt.widgets.figure_settings.export_sidecars(figure, path) → list[source]

Export available figure data, statistics, and caption sidecars.

Parameters:
  • figure (matplotlib.figure.Figure) – Figure carrying optional _spacr_data, _spacr_groups, or _spacr_caption metadata.

  • path (path-like) – Figure output path. Sidecars use the same directory and basename.

Returns:

list of str – Successfully written sidecar paths. Depending on available metadata, these may include <name>.csv, <name>_stats.csv, and <name>_legend.txt.

Notes

The data sidecar contains the rows attached to the rendered figure. The statistics sidecar contains all usable pairwise comparisons with multiple testing correction provided by spaCR’s statistics table helper. Individual sidecar failures are logged and do not interrupt the remaining exports.

spacr.qt.widgets.figure_settings.figure_follows_the_theme(figure) → None[source]

Restore line and font colours from the active theme preferences.

Parameters:

figure (matplotlib.figure.Figure) – Figure to update. If the preference store is unavailable, black is used for both line and font colours.

spacr.qt.widgets.figure_settings.figure_line_artists(figure) → list[source]

Collect artists affected by the global line-colour control.

Parameters:

figure (matplotlib.figure.Figure) – Figure whose artists should be collected.

Returns:

list – Data and reference lines, axes spines, and legend sample lines.

Notes

Gridlines are excluded. Tick marks are updated separately by apply_line_colour() because Matplotlib recreates them during draws.

spacr.qt.widgets.figure_settings.graph_style_as_dict(general=None, per_graph=None) → dict[source]

Serialize graph-style preference overrides to a dictionary.

Parameters:
  • general (mapping, optional) – General style overrides. If None, read the current preference.

  • per_graph (mapping of str to mapping, optional) – Overrides keyed by graph type. If None, read the current preference.

Returns:

dict – Style data with spacr_style_kind, general, and per_graph keys. Per-graph values that are not mappings are omitted.

Notes

Only preference overrides are stored. Theme-resolved colours and package defaults are not captured from the currently displayed figure.

spacr.qt.widgets.figure_settings.load_graph_style(path: str) → tuple[source]

Read graph-style preference overrides from a JSON file.

Parameters:

path (str) – Path to a graph-style file created by save_graph_style().

Returns:

  • general (dict) – General style overrides.

  • per_graph (dict) – Style overrides keyed by graph type.

Raises:

Notes

Unknown setting names are preserved for compatibility with files created by other spaCR versions.

spacr.qt.widgets.figure_settings.save_figure_as(parent, figure, path: str = '') → str[source]

Save a figure using its current styling and export preferences.

Parameters:
  • parent (PySide6.QtWidgets.QWidget or None) – Parent for the file chooser when path is empty.

  • figure (matplotlib.figure.Figure or None) – Figure to save. None cancels the operation.

  • path (str, optional) – Destination path. If empty, prompt for a PNG, PDF, or SVG path.

Returns:

str – Path returned by the writer, or an empty string when saving is cancelled or fails.

Notes

A recognized filename extension takes precedence over the default output format. Available data, statistics, and caption metadata are exported by export_sidecars() beside the requested path.

spacr.qt.widgets.figure_settings.save_figure_bundle(figure, folder: str, name: str = '') → str[source]

Export a Matplotlib figure with its source data and statistics.

Group definitions come from the attached replot recipe so statistical comparisons match the displayed figure. When no recipe is available, the standard files are still written and the statistics artifact records that no comparison could be formed.

Parameters:
  • figure – Matplotlib figure to export.

  • folder – destination directory for the bundle.

  • name – optional base name for generated files.

Returns:

path to the written bundle directory.

spacr.qt.widgets.figure_settings.save_graph_style(path: str, general=None, per_graph=None) → str[source]

Write graph-style preference overrides to a JSON file.

Parameters:
  • path (str) – Destination path. An empty path cancels the operation.

  • general (mapping, optional) – General style overrides. If None, read the current preference.

  • per_graph (mapping of str to mapping, optional) – Overrides keyed by graph type. If None, read the current preference.

Returns:

str – path after a successful write, or an empty string if the path is empty or the file cannot be written.

Raises:

TypeError – If a supplied setting value cannot be serialized as JSON.

spacr.qt.widgets.figure_settings.style_choices_for(name: str) → tuple[source]

Return the choices available for a style setting.

Parameters:

name (str) – Style setting name.

Returns:

tuple – Canonical choices from spacr.figure_style. If that module is unavailable, return the local fallback choices. An empty tuple denotes a free-form or unknown setting.

spacr.qt.widgets.figure_settings.style_setting_label(name: str) → str[source]

Convert a style setting name to a display label.

Parameters:

name (str) – Underscore-delimited style key, such as 'grid_colour'.

Returns:

str – Capitalized, space-delimited label, such as 'Grid colour'.

Nested helpers

FigureSettingsDialog._add_series_rules.apply_edge(value)

Set the edge width on every series that has one.

spacr/qt/widgets/figure_settings.py:397

FigureSettingsDialog._add_series_rules.apply_opacity(value)

Set the alpha on every series.

spacr/qt/widgets/figure_settings.py:384

FigureSettingsDialog._add_series_rules.apply_palette(*_)

Recolour every series from the chosen palette.

spacr/qt/widgets/figure_settings.py:344

FigureSettingsDialog._add_series_rules.apply_size(value)

Resize every series that has a size to set.

spacr/qt/widgets/figure_settings.py:368

FigureSettingsDialog._axes_tab.apply_grid(*_)

Show or hide the grid, passing line properties ONLY when enabling.

matplotlib warns “First parameter to grid() is false, but line properties are supplied” and then turns the grid ON regardless – so passing them unconditionally made the checkbox unable to switch the grid off, which is the opposite of what it says.

spacr/qt/widgets/figure_settings.py:822

FigureSettingsDialog._axes_tab.apply_legend(*_)

Rebuild the legend from the current choices.

spacr/qt/widgets/figure_settings.py:899

FigureSettingsDialog._axes_tab.apply_limits(*_, s=setter, b=boxes)

Apply one axis’s limits, refusing a zero-width range.

Equal bounds collapse the axis and matplotlib draws nothing, so the value is left alone rather than applied.

spacr/qt/widgets/figure_settings.py:776

FigureSettingsDialog._axes_tab.do_autoscale()

Recompute the limits from the data now on the axis.

spacr/qt/widgets/figure_settings.py:793

FigureSettingsDialog._axes_tab.set_colour(colour, a=artist)

Recolour one artist. The artist is bound as a default argument.

Bound at definition rather than closed over: a loop variable closed over gives every callback the LAST artist, which is the classic way a row of per-artist controls all end up editing one of them.

spacr/qt/widgets/figure_settings.py:938

FigureSettingsDialog._axes_tab.set_spines(value)

Set every spine’s width, or hide them all at zero.

spacr/qt/widgets/figure_settings.py:854

FigureSettingsDialog._axes_tab.set_top_right(hidden)

Hide or show the top and right spines together.

spacr/qt/widgets/figure_settings.py:867

FigureSettingsDialog._figure_tab.resize(*_)

Resize the figure to the width and height on screen.

spacr/qt/widgets/figure_settings.py:650

FigureSettingsDialog._figure_tab.set_all_text(size)

Set one font size on every piece of text in the figure.

spacr/qt/widgets/figure_settings.py:670

FigureSettingsDialog._figure_tab.set_face(colour)

Set the figure’s own background colour.

spacr/qt/widgets/figure_settings.py:634

FigureSettingsDialog._figure_tab.set_font_ink(colour)

Recolour every piece of text in the figure.

spacr/qt/widgets/figure_settings.py:689

FigureSettingsDialog._figure_tab.set_line_ink(colour)

Recolour every line in the figure.

spacr/qt/widgets/figure_settings.py:684

FigureSettingsDialog._statistics_tab._recompute()

Re-run the test with the current choices and redraw.

spacr/qt/widgets/figure_settings.py:581

FigureStylePreferences._control._set_colour(v, b=button, h=holder)

Store a colour and repaint the swatch that shows it.

spacr/qt/widgets/figure_settings.py:2926

FigureStylePreferences._control._set_combo(v, box=combo)

Select the entry whose data is v, if the box has one.

spacr/qt/widgets/figure_settings.py:2915

FigureStylePreferences._ground_control._get()

The ground: the transparent sentinel, or the chosen colour.

spacr/qt/widgets/figure_settings.py:2991

FigureStylePreferences._ground_control._paint_button(colour: str) → None

Show the ground colour on the button, as swatch and text.

spacr/qt/widgets/figure_settings.py:2976

FigureStylePreferences._ground_control._set(new_value)

Apply a ground, ticking transparent when that is what it means.

spacr/qt/widgets/figure_settings.py:2996

FigureStylePreferences._ground_control._sync(*_)

Grey the colour button while transparent is ticked.

spacr/qt/widgets/figure_settings.py:2985

_add_bundle_save._save() → None

Ask for a folder and write the whole bundle into it.

spacr/qt/widgets/figure_settings.py:1624

_add_group_colours._recolour(group: str) → None

Pick a colour for one group and store it on the recipe.

spacr/qt/widgets/figure_settings.py:1587

_colour_button._choose()

Ask for a colour and keep it if the dialog returned one.

spacr/qt/widgets/figure_settings.py:99

_colour_button._paint()

Show the current colour on the button, as a swatch and as text.

spacr/qt/widgets/figure_settings.py:90

add_graph_style_file_entries._load()

Read a graph style back and apply it.

spacr/qt/widgets/figure_settings.py:1303

add_graph_style_file_entries._save()

Write the current graph style to a JSON file.

spacr/qt/widgets/figure_settings.py:1295

build_figure_context_menu._apply(func)

Run func against every axis in the figure.

spacr/qt/widgets/figure_settings.py:1791

build_figure_context_menu._notify() → None

Redraw after a menu toggle, CHEAPLY.

A context-menu toggle is the same kind of edit the settings dialog makes, and the dialog learned long ago to preview: a full-quality render rewrites the raster AND the vector page, measured at ~263 ms on an 823-point volcano, and the user is mid-gesture. Preview here too, and let the next full render – a resize, an export, closing the settings dialog – catch up.

on_change may be a callable that predates preview rendering, so the keyword is offered and withdrawn rather than assumed.

spacr/qt/widgets/figure_settings.py:1771

build_figure_context_menu._pick_ink(title, apply_to)

Pick a colour and apply it through apply_to.

spacr/qt/widgets/figure_settings.py:1843

build_figure_context_menu.toggle_legend(checked)

Show or hide the legend on every axis.

spacr/qt/widgets/figure_settings.py:1804

save_figure_as.figure_bg_is_transparent(value)

Whether a stored ground value means “no background at all”.

spacr/qt/widgets/figure_settings.py:2469

save_figure_bundle._render(path: str) → None

Render one file of the bundle through the SHARED export path.

Both formats go through save_figure rather than each drawing itself, so print colours, embedded fonts and raster DPI match every other figure the user keeps.

spacr/qt/widgets/figure_settings.py:1665