linumpy.mosaic.stacking#

3D slice stacking utilities.

Consolidated from linum_stack_slices_motor.py and linum_stack_motor_only.py.

Attributes#

Functions#

enforce_z_consistency(z_matches[, ...])

Correct outlier Z-overlaps using neighbor interpolation.

find_z_overlap(fixed_vol, moving_vol, ...)

Find optimal Z-overlap between consecutive slices using cross-correlation.

apply_2d_transform(image_2d, transform[, ...])

Apply a SimpleITK 2D/3D transform to a single 2D image (Z-slice).

apply_transform_to_volume(vol, transform[, ...])

Apply a 2D transform to each Z-slice of a volume.

apply_xy_shift(vol, dx_px, dy_px, output_shape)

Compute destination region for placing a shifted volume.

blend_overlap_z(fixed_region, moving_region)

Blend overlapping Z-region using a cosine (Hann) ramp along Z-axis.

blend_overlap_xy(existing, new_data[, method])

Blend overlapping XY regions for motor-only stacking.

refine_z_blend_overlap(existing, moving_overlap, ...)

Find and apply a small XY shift to align moving_overlap with existing before blending.

Module Contents#

linumpy.mosaic.stacking.logger[source]#
linumpy.mosaic.stacking.enforce_z_consistency(z_matches, confidence_per_slice=None, outlier_threshold_frac=0.3, confidence_protect_threshold=0.6)[source]#

Correct outlier Z-overlaps using neighbor interpolation.

Scans pairwise Z-overlap measurements for outliers (deviating more than outlier_threshold_frac from the median) and replaces them with the local median of their immediate neighbors. Both overlap_voxels and blend_overlap_voxels are corrected independently.

Slices whose registration confidence (from confidence_per_slice) meets or exceeds confidence_protect_threshold are considered reliable and are not modified.

Parameters:
  • z_matches (list of dict) – Each dict must have keys overlap_voxels, blend_overlap_voxels and moving_id. Items are modified in-place.

  • confidence_per_slice (dict or None) – Mapping from moving_id (int) to confidence score in [0, 1]. Slices with confidence >= confidence_protect_threshold are skipped. If None, all slices are treated as having confidence 0.5.

  • outlier_threshold_frac (float) – Fractional deviation from median above which a value is an outlier. Default: 0.30 (30 %).

  • confidence_protect_threshold (float) – Minimum confidence to protect a slice from correction. Default: 0.6.

Returns:

  • z_matches (list of dict) – The corrected z_matches list (same objects, modified in-place).

  • corrections (list of dict) – Log of corrections: each entry has keys moving_id, field, old_value and new_value.

Return type:

tuple[list, list]

linumpy.mosaic.stacking.find_z_overlap(fixed_vol, moving_vol, slicing_interval_mm, search_range_mm, resolution_um)[source]#

Find optimal Z-overlap between consecutive slices using cross-correlation.

Searches around the expected overlap for the best normalized cross-correlation score, using the center XY region for speed.

Parameters:
  • fixed_vol (np.ndarray) – Bottom (fixed) slice volume (Z, Y, X).

  • moving_vol (np.ndarray) – Top (moving) slice volume (Z, Y, X).

  • slicing_interval_mm (float) – Expected physical slice thickness in mm.

  • search_range_mm (float) – Search range around expected position in mm.

  • resolution_um (float) – Z resolution in microns per voxel.

Returns:

  • best_overlap (int) – Optimal overlap in Z voxels.

  • best_corr (float) – Correlation score at optimal overlap.

Return type:

tuple[int, float]

linumpy.mosaic.stacking.apply_2d_transform(image_2d, transform, rotation_only=False, max_rotation_deg=1.0, override_rotation=None)[source]#

Apply a SimpleITK 2D/3D transform to a single 2D image (Z-slice).

Parameters:
  • image_2d (np.ndarray) – 2D image to transform.

  • transform (sitk.Transform) – SimpleITK transform (extracts 2D rotation/translation from 3D Euler).

  • rotation_only (bool) – If True, apply only rotation, ignore translation.

  • max_rotation_deg (float) – Maximum rotation in degrees; larger values are clamped. 0 = no clamping.

  • override_rotation (float or None) – Use this rotation angle (radians) instead of extracting from transform.

Returns:

Transformed 2D image.

Return type:

np.ndarray

linumpy.mosaic.stacking.apply_transform_to_volume(vol, transform, rotation_only=False, max_rotation_deg=1.0, override_rotation=None)[source]#

Apply a 2D transform to each Z-slice of a volume.

Parameters:
  • vol (np.ndarray) – 3D volume (Z, Y, X).

  • transform (sitk.Transform) – Transform to apply to each slice.

  • rotation_only (bool) – If True, apply only rotation.

  • max_rotation_deg (float) – Maximum rotation in degrees.

  • override_rotation (float or None) – If provided, use this rotation for all slices.

Returns:

Transformed volume.

Return type:

np.ndarray

linumpy.mosaic.stacking.apply_xy_shift(vol, dx_px, dy_px, output_shape)[source]#

Compute destination region for placing a shifted volume.

Returns the (possibly cropped) volume data and destination coordinates without allocating a full-size output array.

Parameters:
  • vol (np.ndarray) – 3D volume (Z, Y, X).

  • dx_px (float) – Shift in pixels (X and Y directions).

  • dy_px (float) – Shift in pixels (X and Y directions).

  • output_shape (tuple) – (out_ny, out_nx) output canvas size.

Returns:

  • cropped_vol (np.ndarray or None) – Cropped volume data to write.

  • dst_coords (tuple or None) – (y_start, y_end, x_start, x_end) in output coordinates.

Return type:

tuple

linumpy.mosaic.stacking.blend_overlap_z(fixed_region, moving_region)[source]#

Blend overlapping Z-region using a cosine (Hann) ramp along Z-axis.

The weight ramp has zero slope at both endpoints, so there is no abrupt intensity change at either boundary of the overlap zone. At tissue boundaries where only one slice has data the full intensity of that slice is used unchanged.

Parameters:
  • fixed_region (np.ndarray) – 3D array (Z, Y, X) from the existing stack (bottom portion).

  • moving_region (np.ndarray) – 3D array (Z, Y, X) from the new slice (top portion).

Returns:

Blended region with smooth Z-transition.

Return type:

np.ndarray

linumpy.mosaic.stacking.blend_overlap_xy(existing, new_data, method='none')[source]#

Blend overlapping XY regions for motor-only stacking.

Parameters:
  • existing (np.ndarray) – Existing data in the output region.

  • new_data (np.ndarray) – Incoming data to blend.

  • method (str) – ‘none’ (overwrite), ‘average’, ‘max’, or ‘feather’.

Returns:

Blended result.

Return type:

np.ndarray

linumpy.mosaic.stacking.refine_z_blend_overlap(existing, moving_overlap, max_refinement_px)[source]#

Find and apply a small XY shift to align moving_overlap with existing before blending.

Uses 2D phase correlation on Z-projected overlap regions to detect residual XY misalignment at slice boundaries.

Parameters:
  • existing (np.ndarray) – 3D array (Z, Y, X) from current stack at the overlap zone.

  • moving_overlap (np.ndarray) – 3D array (Z, Y, X) from incoming slice at the overlap zone.

  • max_refinement_px (float) – Maximum allowed shift magnitude in pixels.

Returns:

  • refined (np.ndarray) – Shifted moving_overlap with residual XY misalignment corrected.

  • magnitude (float) – Shift magnitude applied (pixels), or 0.0 if not applied.

Return type:

tuple[numpy.ndarray, float]