spacr.qt.widgets.mask_comparison

Lay several masks and images over one another, in a panel of their own.

Once a preview session has made more than one mask, the masks and the field can be ticked, given an opacity and put in a stacking order, and the composite is drawn in a panel beside the preview’s other views.

TWO HALVES. composite() is the arithmetic, on plain arrays, so the picture a user sees can be checked pixel by pixel against a hand calculation. MaskComparisonDialog is the popup that chooses what goes into it. Neither knows about the Mask module; the live preview hands in its session’s masks and its field, and draws the answer.

THE ARITHMETIC IS “OVER”, LAYER BY LAYER, FROM THE BOTTOM. The canvas starts black. Each ticked layer, bottom first, is laid on with its opacity a: where it covers, out = out * (1 - a) + colour * a; where it does not, out is left alone. An image covers every pixel; a mask covers its objects only, so the background of a mask never dims what is under it. The result is rounded to the nearest whole grey level.

THE STACKING ORDER READS LIKE A LAYER LIST. The popup lists the top of the stack first, the way every drawing program does, and chosen() hands the layers back bottom first, the order composite() lays them on.

Classes

Layer

One thing the comparison can draw.

MaskComparisonDialog

Tick, opacity and stacking order for each mask and image.

Functions

composite(→ Optional[numpy.ndarray])

Lay the ticked layers over a black canvas, bottom first.

layer_rgb(→ Tuple[numpy.ndarray, numpy.ndarray])

A layer's colour and the pixels it covers.

Module Contents

class spacr.qt.widgets.mask_comparison.Layer[source]

One thing the comparison can draw.

Parameters:
  • name – what the popup calls it.

  • kind – MASK or IMAGE.

  • array – an H x W label mask, or an H x W or H x W x 3 uint8 picture.

  • colour – the colour a mask’s objects are filled with.

  • ticked – whether it is drawn.

  • opacity – 0 to 1.

class spacr.qt.widgets.mask_comparison.MaskComparisonDialog(layers: Sequence[Layer], parent=None)[source]

Bases: PySide6.QtWidgets.QDialog

Tick, opacity and stacking order for each mask and image.

Rows are listed top of the stack first. The dialog is a plain QDialog, so spaCR’s card and rim reach it the way they reach every other popup.

Parameters:
  • layers – the choices, TOP OF THE STACK FIRST.

  • parent – parent widget; ownership only.

Build one row per layer, and OK and Cancel.

chosen() → List[Layer][source]

The ticked layers, BOTTOM FIRST, ready for composite().

listed() → List[Layer][source]

Every layer as the popup has it now, top of the stack first.

move(index: int, step: int) → None[source]

Move row index by step places; -1 is up the stack.

A move that would leave the stack does nothing.

Parameters:
  • index – the row to move, top of the stack first.

  • step – how many places to move it; negative is up.

rows() → List[Tuple[PySide6.QtWidgets.QCheckBox, PySide6.QtWidgets.QSlider]][source]

Each row’s tick and opacity slider, top of the stack first.

spacr.qt.widgets.mask_comparison.composite(layers: Sequence[Layer], shape: Tuple[int, int] | None = None) → numpy.ndarray | None[source]

Lay the ticked layers over a black canvas, bottom first.

Parameters:
  • layers – bottom of the stack first. Unticked layers and layers of another size than the first are skipped.

  • shape – the canvas size; the first ticked layer’s when omitted.

Returns:

H x W x 3 uint8, or None when nothing is ticked.

spacr.qt.widgets.mask_comparison.layer_rgb(layer: Layer) → Tuple[numpy.ndarray, numpy.ndarray][source]

A layer’s colour and the pixels it covers.

Parameters:

layer – a mask layer covers its non-zero pixels in its own colour; an image layer covers every pixel with its own values.

Returns:

(H x W x 3 float32 colour, H x W bool coverage).