linumpy.mosaic.motor#
Motor-position-based tile placement for mosaic stitching.
Consolidated from linum_stitch_3d_refined.py and linum_stitch_motor_only.py.
Attributes#
Functions#
|
Compute tile positions based on motor grid (ideal positions). |
|
Correlate neighboring tiles within a slice to measure displacement errors. |
|
Estimate a 2x2 affine displacement model from neighbor tile correlations. |
|
Pool neighbor-tile pair measurements across many mosaic grids and fit one affine. |
|
Compute tile positions using a 2x2 affine displacement model. |
|
Compute the output mosaic shape from affine tile positions. |
|
Apply registration refinement by shifting tile data in overlap regions. |
|
Compare motor-based positions with registration-based positions. |
Module Contents#
- linumpy.mosaic.motor.compute_motor_positions(nx, ny, tile_shape, overlap_fraction, scale_factor=1.0, rotation_deg=0.0)[source]#
Compute tile positions based on motor grid (ideal positions).
Assumes a regular grid where tiles are spaced by (1 - overlap) * tile_size. Optionally applies scale factor and rotation to test hypotheses about stage calibration issues.
- Parameters:
nx (int) – Number of tiles in each direction.
ny (int) – Number of tiles in each direction.
tile_shape (tuple) – Tile dimensions (z, height, width).
overlap_fraction (float) – Expected overlap between tiles (0-1).
scale_factor (float) – Scale applied to step size (default 1.0 = no scaling).
rotation_deg (float) – Global grid rotation in degrees (default 0.0).
- Returns:
positions (list) – List of (row_pos, col_pos) pixel positions for each tile.
step_y (int) – Y step in pixels.
step_x (int) – X step in pixels.
- Return type:
- linumpy.mosaic.motor.compute_registration_refinements(volume, tile_shape, nx, ny, overlap_fraction, max_refinement_px=10.0, *, histogram_match=False, max_empty_fraction=None, use_gpu=False)[source]#
Correlate neighboring tiles within a slice to measure displacement errors.
Phase-correlates overlapping regions of adjacent tiles (horizontal and vertical neighbors) to measure the difference between expected and actual tile positions. Returns both clamped residuals for blend refinement and unclamped absolute displacements for fitting the affine displacement model (Lefebvre et al. 2017, Eqs 1-6).
Note: this operates on tiles within a single slice – it is entirely separate from the Z-slice pairwise registration (
linum_register_pairwise.py).- Parameters:
volume (np.ndarray) – The mosaic grid volume (Z, nx*tile_h, ny*tile_w).
tile_shape (tuple) – Tile dimensions (z, height, width).
nx (int) – Number of tiles in each direction.
ny (int) – Number of tiles in each direction.
overlap_fraction (float) – Expected overlap fraction (0-1).
max_refinement_px (float) – Maximum residual shift retained for blend refinement. Larger residuals are clamped. Does not affect the absolute displacements in ‘pairs’.
histogram_match (bool, keyword-only) – If True, match the intensity histogram of the second overlap to the first before phase correlation. Improves robustness when tile-edge illumination is uneven; disabled by default to preserve existing behaviour.
max_empty_fraction (float or None, keyword-only) – If set, use an Otsu threshold on the central plane to classify tissue vs background, and skip any pair whose overlap contains more than this fraction of background pixels (mirrors the behaviour of
linumpy.registration.transforms.estimate_mosaic_transform). WhenNone(default), the priormean(overlap > 0) < 0.1heuristic is used.use_gpu (bool, keyword-only) – If True, run the pairwise phase correlations via
linumpy.gpu.fft_ops.phase_correlation()(CuPy-accelerated). Falls back silently to the CPU path when CuPy / a CUDA device is not available. Default is False.
- Returns:
‘pairs’ is a list of dicts with keys ‘row_delta’, ‘col_delta’, ‘measured_dy’, ‘measured_dx’ – the absolute observed pixel displacements used for affine model estimation.
- Return type:
dict with keys ‘horizontal’, ‘vertical’, ‘pairs’, ‘stats’.
- linumpy.mosaic.motor.estimate_affine_from_pairs(pairs, tile_shape, overlap_fraction)[source]#
Estimate a 2x2 affine displacement model from neighbor tile correlations.
Fits the Lefebvre et al. (2017) motor displacement model using least-squares on the absolute (step + residual) displacements returned by
compute_registration_refinements().Note: this uses phase correlation between neighboring tiles within a single slice, not the Z-slice pairwise registration that appears elsewhere in the pipeline.
The model is:
pixel_pos = A @ [i, j]^Twhere A is a general 2x2 matrix. Off-diagonal terms capture the scan-to-stage rotation (θ) and the non-perpendicularity of the motor axes (φ).- Parameters:
- Returns:
transform (np.ndarray) – Fitted 2x2 affine matrix mapping tile index to pixel position.
diagnostics (dict) – Extracted displacement model parameters (θ, φ, Ox, Oy) and fit residual statistics.
- Return type:
- linumpy.mosaic.motor.pool_pairs_and_fit_global_affine(volumes, overlap_fraction, *, histogram_match=False, max_empty_fraction=None, n_samples=None, seed=0, use_gpu=False)[source]#
Pool neighbor-tile pair measurements across many mosaic grids and fit one affine.
For each
(slice_id, path)entry, load only the central Z plane of the OME-Zarr volume and callcompute_registration_refinements()with the supplied options. All resulting pairs are concatenated, optionally sub-sampled with a deterministic seed, and fed toestimate_affine_from_pairs()for a single 2x2 affine fit.- Parameters:
volumes (list of (slice_id, path)) – Each
pathmust be a string orpathlib.Pathpointing at a*.ome.zarrmosaic grid.overlap_fraction (float) – Expected tile overlap fraction (must match acquisition).
histogram_match (bool, keyword-only) – Forwarded to
compute_registration_refinements().max_empty_fraction (float or None, keyword-only) – Forwarded to
compute_registration_refinements().n_samples (int or None, keyword-only) – If set and the pooled pair count exceeds this value, a reproducible random sub-sample of size
n_samplesis drawn before fitting.seed (int, keyword-only) – Seed used when sub-sampling. Ignored when
n_samplesis None.use_gpu (bool, keyword-only) – Forwarded to
compute_registration_refinements().
- Returns:
transform (np.ndarray) – Fitted 2x2 affine matrix.
diagnostics (dict) – Full diagnostics including per-slice stats, pooled pair count, chosen backend label, and the output of
estimate_affine_from_pairs().
- Return type:
- linumpy.mosaic.motor.compute_affine_positions(nx, ny, transform)[source]#
Compute tile positions using a 2x2 affine displacement model.
This is the corrected version of
compute_motor_positions()that accounts for scan-to-stage rotation (θ) and non-perpendicular motor axes (φ) via the off-diagonal terms in the transform matrix.- Parameters:
- Returns:
positions – Pixel positions for each tile, row-major order.
- Return type:
- linumpy.mosaic.motor.compute_affine_output_shape(nx, ny, tile_shape, transform)[source]#
Compute the output mosaic shape from affine tile positions.
With off-diagonal terms, tiles may extend beyond what the diagonal model predicts. This computes the bounding box over all tile corner positions.
- linumpy.mosaic.motor.apply_blend_shift_refinement(tile, refinements_for_tile)[source]#
Apply registration refinement by shifting tile data in overlap regions.
Applies a small sub-pixel shift (averaged from all neighbors) to improve blending quality without changing the tile’s position in the mosaic.
- Parameters:
tile (np.ndarray) – 3D tile data (Z, Y, X).
refinements_for_tile (list) – List of dicts with ‘dx’, ‘dy’ refinements from neighbors.
- Returns:
Shifted tile (or unmodified if shift is negligible).
- Return type:
np.ndarray
- linumpy.mosaic.motor.compare_motor_vs_registration(motor_positions, reg_positions, output_path=None)[source]#
Compare motor-based positions with registration-based positions.
Used diagnostically to identify stage calibration issues (systematic offset, dilation/scaling) and registration drift.
- Parameters:
- Returns:
Statistics including mean/std/max differences and diagnostic flags.
- Return type: