spacr.ops_stitch

One well, one cycle, from a folder of tiles to a table of positions.

THE FOURTH VERB, AND THE ONE THAT PRINTS. spacr.ops_layout says which tiles touch, spacr.ops_register says how far apart a touching pair is, spacr.ops_solve says where each tile ends up, and this runs the three of them over a well and reports what happened.

THE OUTPUT IS COORDINATES, NOT PIXELS. A well of this acquisition is 26,855 x 26,865 px and one is enough to exhaust a machine; the transform table is a few kilobytes and every later phase reads through it. A canvas, if anybody wants one, is rendered from this at whatever downsample suits the screen.

IT PRINTS THREE NUMBERS AND NOT TWO, and that is the whole reason this module exists rather than three calls at a call site. The first end-to-end run of this pipeline reported

333 of 333 placed residual median 0.2 px canvas 35,374 x 35,367

and it was WRONG: the driver negated the correlation’s shift, the unwrap then chose the representative one period out, identically in every edge of a direction, and the well came out one pitch per column too large in both axes. Every edge still agreed with every other edge, so the residual was perfect and the count was perfect. A UNIFORM ERROR IS INVISIBLE TO A RESIDUAL. Only the canvas said otherwise, and only because 21 columns of a known pitch has an arithmetic answer – 20 x 1267 + 1480 = 26,820 – to check it against.

So StitchedWell.summary() gives the count, the residual AND the canvas in one line, and StitchedWell.expected_canvas carries what the layout says the canvas should be, because a number with nothing to compare it to is not a check.

Typical use:

from spacr.ops_stitch import stitch_well

well = stitch_well(read_tile, overlap=213, tolerance=4)
print(well.summary())
positions = well.placements          # site -> (y, x), in well pixels

Classes

StitchedWell

What one well's stitch produced, and what it cost.

Functions

stitch_well(→ StitchedWell)

Register a well's tiles against each other and solve their positions.

Module Contents

class spacr.ops_stitch.StitchedWell[source]

What one well’s stitch produced, and what it cost.

Variables:
  • placements – site -> (y, x) in well pixels, from the solve.

  • edges – (a, b) -> Registration for every pair the layout proposed, ACCEPTED OR NOT. A refused pair is a fact about the acquisition and belongs in ops_geometry, not in a debug log.

  • tile_shape – (height, width) of one tile.

  • layout – the well model the pairs came from.

  • overlap – the overlap in pixels the run was told to expect, or None when it was not told.

canvas_agrees(tolerance: float = 0.01) → bool[source]

Whether the measured canvas matches the layout’s arithmetic.

Parameters:

tolerance – allowed fractional difference on either axis. One per cent, because the layout’s number is exact and the stitch’s is not: it carries the real stage’s skew.

Returns:

True when both axes agree within tolerance.

summary() → str[source]

The three numbers, on one line, because two of them lie alone.

property accepted: int[source]

How many proposed pairs registered.

property canvas: Tuple[int, int][source]

(height, width) the placed tiles span, in pixels.

property expected_canvas: Tuple[int, int][source]

What the layout says the canvas should be.

THE ONLY THING THAT CAUGHT THE UNIFORM ERROR. Columns minus one pitches plus one tile, and the same down the tallest column. A measured canvas with nothing to compare it to is a number, not a check.

property placed: int[source]

How many tiles got a position.

property proposed: int[source]

How many pairs the layout offered.

property residuals: numpy.ndarray[source]

Per-edge disagreement between the solve and the measurement.

The distance, in pixels, between where an accepted edge SAID its two tiles sit relative to each other and where the solve put them. Sub-pixel across a well is what says the geometry closed.

spacr.ops_stitch.stitch_well(tiles, layout: spacr.ops_layout.WellLayout | None = None, *, overlap: int | None = None, tolerance: int | None = None, skew: int | None = None, gpu: bool = True, sites: Sequence[int] | None = None, **kwargs) → StitchedWell[source]

Register a well’s tiles against each other and solve their positions.

ONE WELL AT A TIME, AND ONE TILE PAIR AT A TIME WITHIN IT. tiles is normally a CALLABLE, because 333 tiles of 1480 px is 2.9 GB and nothing here needs two of them resident: the caller decides what to keep and what to re-read.

Parameters:
  • tiles – site -> 2-D array, or a callable taking a site.

  • layout – the well model. None fits the circle to sites or, failing that, to the measured 333-field well.

  • overlap – the raster’s overlap in pixels. Given, it sets the registration’s expectation and the layout’s canvas arithmetic; omitted, both fall back to weaker answers, so pass it.

  • tolerance – how far ALONG the raster an edge may land from the layout’s prediction and still be accepted. This is the acceptance the real well used – 624 of 624 – and without it the peak ratio decides, which on a real plate it cannot.

  • skew – how far ACROSS it may. The stage’s skew is real and constant – 9 px on the measured plate – so it is a separate number from the tolerance. None takes spacr.ops_register.SKEW_PX.

  • gpu – passed through to the registration.

  • sites – which sites to place. None uses every site the layout holds.

  • kwargs – passed to spacr.ops_register.register_edge().

Returns:

the stitch, its edges and its residuals.

Raises:

ValueError – when the well holds no tiles at all, which is a caller error rather than an empty result.