spacr.qt.widgets.trellis_view

The trellis surface — the Graph Builder’s canvas, laid out as a grid.

TrellisCanvas subclasses spacr.qt.widgets.graph_builder.GraphCanvas rather than reimplementing it. That is the whole design decision in this file. The mark drawing, the fixed categorical hue order, the density raster, the selection ring, the legend and the brush are one implementation, and a second one would be a second set of rules to keep in step with the first — the mistake spacr.qt.widgets.pivot_builder avoids by not drawing anything at all.

What the subclass changes is the two things a trellis is:

  • the layout comes from spacr.qt.widgets.trellis_spec.trellis(), which knows about wrapping and about blank slots, rather than from facet_grid directly;

  • the scales are set per panel from that panel’s own group. Every panel’s limits are written explicitly rather than left to matplotlib’s sharex: sharing makes panels agree with each other, but on whatever the first one autoscaled to, which is not necessarily wide enough for the rest. Under SCALE_SHARED — the default — every panel is handed the identical tuple, which is a property a test can assert and an eye can trust.

Two conventions the grid earns

Inner tick labels are hidden only when the axis is genuinely shared. A trellis with per-panel scales that hides its inner ticks is a lie with a tidy layout; if a panel has its own limits it prints its own numbers.

Every panel’s title carries its n, from label(). Blank slots at the end of a wrapped grid are hidden entirely — they are not panels with no data, they are the remainder of a division.

Classes

TrellisCanvas

A grid of the same chart, one panel per group, on shared axes.

TrellisPanelWidget

The whole surface: a column well, the six zones, the grid's options,

Module Contents

class spacr.qt.widgets.trellis_view.TrellisCanvas(parent=None, *, link=None, source: str = 'trellis')[source]

Bases: spacr.qt.widgets.graph_builder.GraphCanvas

A grid of the same chart, one panel per group, on shared axes.

Everything GraphCanvas does — linked selection, brushing, the large-data policy, the colour order — with the layout and the scales taken from TrellisSpec.

Parameters:
  • parent – parent widget.

  • link – the LinkedSelection this view joins, so selecting here selects in every other view on it. None joins the shared one; pass a private one in a test so the selection does not reach the rest of the application.

  • source – this view’s name on that link, stamped onto everything it publishes – which is how a view knows not to answer its own selection.

Create the trellis canvas with an empty spec.

The spec is set after the base constructor, which builds the figure and subscribes to the link but does not render – so nothing reads these before they exist.

Parameters:
  • parent – parent widget, or None.

  • link – shared selection link.

  • source – this view’s name in the link, so its own publications can be told from everyone else’s.

brush(x0: float, y0: float, x1: float, y1: float, *, row: int = 0, col: int = 0, publish: bool = True) → spacr.selection.Selection | None[source]

Select the rows of one panel inside a swept rectangle.

Delegated to brush(), which evaluates the rectangle against the unsampled rows and against that panel’s own scales — so it is exact over a density raster and correct under a per-panel scale, where the drawn coordinates of a categorical axis differ from the grid’s.

Parameters:
  • x0 – horizontal position of one corner of the rectangle, in the panel’s data coordinates; the corners may be given in either order.

  • y0 – vertical position of that corner, in the panel’s data coordinates; the corners may be given in either order.

  • x1 – horizontal position of the opposite corner.

  • y1 – vertical position of the opposite corner.

on_linked_selection_changed(selection: spacr.selection.Selection) → None[source]

Move the highlight; redraw only when the marks cannot be re-styled.

Parameters:

selection – the new shared selection; not read directly, since the highlight is recomputed from the canvas’s linked selection.

render_now() → None[source]

Rebuild the grid from the frame, the spec, the filter and the selection.

set_channel(channel: str, column: str | None) → None[source]

Rebind one of the graph’s channels and redraw.

Parameters:
  • channel – the channel’s name, such as x or facet_row.

  • column – the column to bind, or None to clear it.

set_spec(spec: spacr.qt.widgets.graph_spec.GraphSpec, *, immediate: bool = True) → None[source]

Replace only the inner chart spec, keeping the grid’s own options.

Parameters:

spec – the inner chart spec, combined with the current grid options through TrellisSpec.with_graph.

set_trellis_spec(spec: spacr.qt.widgets.trellis_spec.TrellisSpec, *, immediate: bool = True) → None[source]

Replace the whole spec and redraw.

Parameters:

spec – the complete trellis spec: grid options plus the inner chart spec in its graph attribute.

property trellis: spacr.qt.widgets.trellis_spec.Trellis | None[source]

The last computed grid, or None before the first render.

property trellis_spec: spacr.qt.widgets.trellis_spec.TrellisSpec[source]

The grid this canvas is drawing.

Returns:

the trellis spec.

class spacr.qt.widgets.trellis_view.TrellisPanelWidget(parent=None, *, link=None, source: str = 'trellis')[source]

Bases: PySide6.QtWidgets.QWidget

The whole surface: a column well, the six zones, the grid’s options, and the canvas.

The well and the drop zones are ColumnWell and DropZone unchanged, so a column dragged here and a column dragged in the Graph Builder are the same gesture with the same payload type.

Parameters:
  • parent – parent widget.

  • link – the LinkedSelection this view joins, so selecting here selects in every other view on it. None joins the shared one; pass a private one in a test so the selection does not reach the rest of the application.

  • source – this view’s name on that link, stamped onto everything it publishes – which is how a view knows not to answer its own selection.

The three are handed straight to the TrellisCanvas this builds.

Build the channel shelf beside the trellis canvas.

The shelf (“Channels”) and the canvas (“Trellis”) are sections of one CollapsibleSplitter (trellis_view::panel): each folds by its heading and the edge between them drags, opening at the old 300 / 900 split.

Parameters:
  • parent – parent widget, or None.

  • link – shared selection link, passed to the canvas.

  • source – this view’s name in the link.

clear_channels() → None[source]

Empty every drop zone, leaving the table loaded.

closeEvent(event)[source]

Close the canvas first, so it can unlink from the shared selection.

Parameters:

event – the Qt close event.

set_frame(frame: pandas.DataFrame | None) → None[source]

Point the panel at a new table.

Parameters:

frame – the rows to plot, or None to clear.

set_spec(spec: spacr.qt.widgets.trellis_spec.TrellisSpec) → None[source]

Draw a different grid.

Parameters:

spec – the trellis spec.

zone(channel: str) → spacr.qt.widgets.graph_builder.DropZone[source]

One channel’s drop zone, for a caller that needs to drive it.

Parameters:

channel – the channel’s name.

Returns:

the zone widget, or None when there is no such channel.

property spec: spacr.qt.widgets.trellis_spec.TrellisSpec[source]

The grid the canvas is drawing.

Returns:

the trellis spec.