spacr.qt.ortho_view

B15 — orthogonal views and the sliders that drive them.

Three panels over one volume: the top view, the view from the side and the view from the end, crossing at a point the user moves with a slider or a click. spacr.layers.OrthoViews is the model — it owns the geometry, including the part that is silently wrong everywhere else — and this module is the widget over it.

The z slider is labelled in world units

Not in slice numbers. “Slice 7” is a fact about the file; 12.0 µm is a fact about the sample, and it is the one a user can check against the acquisition settings. The slider steps by the stack’s own voxel size, so dragging it moves one slice at a time and the number it shows is where the plane actually is. On a stack with no calibration the unit is px and the step is 1, which reads as slice numbers again — the same widget, telling the truth in both cases.

Why the side panels are not one pixel per slice

Because a confocal stack is not isotropic. 0.65 µm in xy and 2 µm in z is an ordinary spaCR stack, and a side view drawn one pixel per slice is three times too thin — a picture that does not look broken, just slightly flat, and every 3-D shape read off it is wrong. spacr.layers.OrthoViews.covering() gives all three panels one world-units-per-pixel scale, so this module never divides anything by a slice count.

Classes

OrthoPanel

One plane of an orthogonal view, with the crosshair drawn on it.

OrthoView

XY, ZX and YZ over one volume, with a slider per extra dimension.

Module Contents

class spacr.qt.ortho_view.OrthoPanel(name: str, parent=None)[source]

Bases: PySide6.QtWidgets.QFrame

One plane of an orthogonal view, with the crosshair drawn on it.

Paints whatever Canvas it is given, at that canvas’s own resolution — the panel does not scale a pixmap, so the side views keep the world scale the model gave them however the widget is sized.

Parameters:
  • name – 'xy', 'zx' or 'yz'; used for the caption and reported with a click.

  • parent – parent widget; ownership only.

Build one of the three orthogonal cuts.

Parameters:
  • name – which cut this is.

  • parent – parent widget.

mousePressEvent(event) → None[source]

Move the crosshair to the clicked voxel.

MOVES ALL THREE PANELS. An orthogonal view is three cuts through one point, so clicking in any of them re-cuts the other two.

Parameters:

event – the Qt mouse event.

paintEvent(event) → None[source]

Draw this orthogonal slice.

Parameters:

event – the Qt paint event.

show_canvas(stack: spacr.layers.LayerStack, canvas: spacr.layers.Canvas, crosshair: Dict[str, float] | None = None) → None[source]

Paint stack through canvas, with the crosshair at a point.

Parameters:
  • stack – the layer stack to paint; kept for the next repaint.

  • canvas – the Canvas that maps the stack’s world coordinates onto this panel’s pixels; it also places the crosshair.

property canvas: spacr.layers.Canvas | None[source]

The world window being painted.

property name: str[source]

Which plane this panel shows.

class spacr.qt.ortho_view.OrthoView(stack: spacr.layers.LayerStack | None = None, parent=None, *, width: int = 320, frames: int = 0, axes: Tuple[str, str, str] = OrthoViews.DEFAULT_AXES)[source]

Bases: spacr.qt.linked_selection.LinkedView, PySide6.QtWidgets.QWidget

XY, ZX and YZ over one volume, with a slider per extra dimension.

Parameters:
  • stack – the LayerStack to show. Everything in it is drawn on all three planes, so a labels layer over a z-stack is an outline in the side views too.

  • width – the top panel’s width in pixels; every other panel size follows from the world extents.

  • frames – how many timepoints there are, when the volume is one frame of a series. Adds a t slider whose changes are announced through frame_changed rather than resolved here, because loading the next timepoint is the caller’s job (and often a background one).

  • parent – parent widget; ownership only.

  • axes – the volume’s axis names, slowest first. Defaults to DEFAULT_AXES (z, y, x). NAMES, NOT AN ORDER TO APPLY: the array is already in this order, and this is what to CALL each axis, so a volume stored t-first is described here rather than transposed.

Build the three cuts and the sliders that move them.

Parameters:
  • stack – the layers to cut through.

  • parent – parent widget.

  • width – the view’s width in pixels.

  • frames – how many time points there are.

  • axes – the world axes to cut along.

closeEvent(event) → None[source]

Leave the shared selection when the screen goes.

Parameters:

event – the close event, passed on to the base class after the view leaves the shared selection.

move_to(**coords: float) → None[source]

Move the crosshair: view.move_to(z=12.0).

Each coordinate is snapped to its own voxel grid and held inside the volume, so the crosshair is always on a plane that exists.

on_linked_selection_changed(selection) → None[source]

Move the crosshair onto the object another view selected.

Parameters:

selection – the shared Selection. Only a selection of exactly one key moves the crosshair, onto the centroid of the labels-layer object with that key.

reset_view() → None[source]

Fit the whole volume in all three panels.

set_stack(stack: spacr.layers.LayerStack) → None[source]

Show a different volume, rebuilding the sliders for its extents.

Parameters:

stack – the new layer stack; the view is refitted to it, and a stack with no volume leaves the panels empty with the reason in the status line.

slice_index(axis: str) → int[source]

Which slice the crosshair is on along axis, counting from 0.

Parameters:

axis – the world axis, one of the view’s axis names (z, y or x by default).

wheelEvent(event) → None[source]

Zoom all planes around the image position beneath the pointer.

Parameters:

event – the Qt wheel event.

zoom_in() → None[source]

Every panel one step closer, about the crosshair.

zoom_out() → None[source]

Every panel one step further away.

property stack: spacr.layers.LayerStack[source]

The stack being shown.

property views: spacr.layers.OrthoViews | None[source]

The three canvases, or None when the stack has no volume.