spacr.ops_compose¶
The canonical nuclear map, composed one window at a time.
ops_stitch solves where every tile sits and deliberately does not hold the
pixels – well A1 is 26,855 x 26,865, which is 1.4 GB as uint16 for one
channel, and every later phase would read through it. This module composes the
same well window by window instead, which is what segmentation wants anyway:
segment once, on the composite, a window at a time.
A window that a segmenter can hold is also a window a composer can build, so nothing ever materialises the whole canvas. The join key the object numbering needs – a plate-level object number in the well frame – survives because every window carries its own offset into that frame.
Averaging the overlaps gives a measured noise gain of about 1.15x on the channel segmentation runs on. There is only one DAPI acquisition, so averaging across cycles does not apply; the gain comes from the raster’s 14% overlap, where two tiles imaged the same nuclei.
Exceptions¶
Raised when a window cannot be composed, with the reason. |
Classes¶
A rectangle of the well frame, and where it sits in it. |
Functions¶
|
Average every tile that overlaps |
|
The noise gain from averaging, over pixels a tile reached. |
|
Tile a canvas into overlapping windows, in raster order. |
Module Contents¶
- exception spacr.ops_compose.ComposeError[source]¶
Bases:
ValueErrorRaised when a window cannot be composed, with the reason.
Initialize self. See help(type(self)) for accurate signature.
- class spacr.ops_compose.Window[source]¶
A rectangle of the well frame, and where it sits in it.
- Parameters:
top – first row in well pixels.
left – first column in well pixels.
height – rows.
width – columns.
- spacr.ops_compose.compose_window(window: Window, placements: Mapping[int, Tuple[float, float]], read_tile: Callable[[int], numpy.ndarray], *, tile_shape: Tuple[int, int] | None = None, dtype: type = np.float32) Tuple[numpy.ndarray, numpy.ndarray][source]¶
Average every tile that overlaps
windowinto one image.Averaged, not last-writer-wins. A tile pasted over its neighbour keeps a seam where two tiles disagree, and a segmenter can detect that seam as an edge. Averaging removes the seam and also gives the 1.15x noise gain.
- Parameters:
window – the rectangle of the well frame to build.
placements –
site -> (y, x)from the solve, in well pixels.read_tile – called with a site number, returns that tile. Called only for tiles that touch the window, so a well of 333 tiles costs a handful of reads per window rather than 333.
tile_shape –
(height, width); read from the first tile when omitted.
- Returns:
(image, coverage)– the averaged window and how many tiles contributed to each pixel. Coverage is returned because a pixel no tile reached is not a black pixel, and only the count tells them apart.
- spacr.ops_compose.overlap_gain(count: numpy.ndarray) float[source]¶
The noise gain from averaging, over pixels a tile reached.
sqrt of the mean coverage: averaging n independent samples of one signal divides the noise by sqrt(n). Reported over covered pixels only, because a well’s corners are reached by one tile and including the uncovered background would report a gain for pixels nothing measured.
A gain of 1.15x was measured for well A1 at a 14% raster overlap; a much larger value on the same geometry indicates that something is averaged twice.
- Parameters:
count – the coverage array from
compose_window().
- spacr.ops_compose.windows_over(canvas: Tuple[int, int], size: int = 4096, overlap: int = 256) Iterator[Window][source]¶
Tile a canvas into overlapping windows, in raster order.
The windows overlap so objects can be sewn across them: an object straddling a window boundary is one object, and it can only be matched across the seam if both windows saw all of it. The overlap has to exceed the largest object, not merely touch.
- Parameters:
canvas –
(height, width)of the well frame.size – window edge in pixels.
overlap – how much neighbouring windows share.
- Raises:
ComposeError – when the overlap is not smaller than the window, which would make the stride zero and the iteration infinite.