Skip to content

Improve pairwise registration: multi-scale ITK, shift filtering, motor-position mode#86

Merged
FIrgolitsch merged 10 commits intomainfrom
pr-2-pairwise-registration
Mar 25, 2026
Merged

Improve pairwise registration: multi-scale ITK, shift filtering, motor-position mode#86
FIrgolitsch merged 10 commits intomainfrom
pr-2-pairwise-registration

Conversation

@FIrgolitsch
Copy link
Copy Markdown
Contributor

Summary

Closes #79

Addresses issue #79 by substantially improving the robustness of pairwise slice registration.

Key Changes

linumpy/stitching/registration.py — new functions:

  • register_2d_images_sitk: multi-scale 2D ITK registration (Euler/affine/translation) with mask support and optional 3D transform output
  • apply_transform: resample a moving image with a SimpleITK transform
  • find_best_z: cross-correlation search for best matching Z-index across slices
  • register_refinement: gradient-descent rotation + translation refinement
  • create_transform: builds a 3D Euler transform from 2D parameters

New linumpy/utils/shifts.py — XY shift utilities:

  • load_shifts_csv, compute_cumulative_shifts, filter_outlier_shifts (IQR-based), interpolate_missing_shifts

New linumpy/utils/metrics.py — pipeline metrics collection for registration, mosaic, and stacking steps

New scripts/linum_register_pairwise.py — simplified pairwise registration CLI based on motor positions; outputs transform.tfm, offsets.txt, metrics.json

scripts/linum_estimate_transform.py — gains:

  • --use_motor_positions flag
  • IQR outlier filtering for shifts
  • Fallback identity transforms for failed registrations
  • Metrics collection

Deleted scripts/linum_estimate_transform_pairwise.py and its test (replaced by the new scripts above)

New linumpy/tests/test_utils_shifts.py

Dependencies

Depends on PR #85 (thread config module).


Merge order: Merge after PR #85.

Closes #79. Adds robust multi-scale 2D ITK registration functions
(register_2d_images_sitk, apply_transform, find_best_z) to
stitching/registration.py. Introduces utils/shifts.py for XY shift
management (load/filter/interpolate) and utils/metrics.py for pipeline
metrics collection. Replaces linum_estimate_transform_pairwise.py with
improved linum_register_pairwise.py and extends linum_estimate_transform.py
with motor-position mode, IQR outlier filtering, and fallback transforms.
Copy link
Copy Markdown
Contributor

@CHrlS98 CHrlS98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First round of comments

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it like before, i.e. fixed and moving volumes are expected to already be roughly aligned and with lateral dimensions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! This script is executed after all slices are brought to the common space.

Comment on lines +60 to +64
p.add_argument("--use_motor_positions", action="store_true",
help="Use motor positions (expected tile spacing) instead of image registration.\n"
"This creates a transform based purely on the overlap fraction,\n"
"corresponding to the precise motor/stage positions from acquisition.\n"
"Recommended when motor positions are reliable.")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it ever the case ?

Copy link
Copy Markdown
Contributor Author

@FIrgolitsch FIrgolitsch Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually use this most of the time these days. I found that using the motor positions and using a heavily restricted registration afterwards to refine was more reliable.

@@ -0,0 +1,386 @@
# -*- coding: utf-8 -*-
"""
XY shift utilities for serial-section alignment.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything can be a utility so I'd suggest having this file under linumpy/shifts/utils.py instead of linumpy/utils/shifts.py

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, fair enough. The distinction is not really useful to make.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved that and some other code around based on their functionality.

…tinguish genuine re-homing events from encoder glitch spikes, improving robustness of shift correction.
…and align_images_sitk functions for cleaner implementation.
- Moved `data_io` from `linumpy.utils` to `linumpy.io`.
- Introduced `mosaic_grid.py` in `linumpy.stitching` for managing mosaic grid images.
- Updated imports in various scripts and test files to reflect the new module structure.
- Removed unused imports from `linumpy.utils.__init__.py`.
- Adjusted references to `MosaicGrid` and related functions in scripts for illumination compensation, cropping, and stitching.
- Ensured consistency in the import paths across the codebase.
… script to handle mosaic grid expansion artifacts
…act step handling, adding unreliable transition refinement via image registration, and improving inter-slice shift estimation from tile stage positions.
@FIrgolitsch FIrgolitsch requested a review from CHrlS98 March 23, 2026 16:24
@FIrgolitsch FIrgolitsch merged commit e14ae39 into main Mar 25, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Pairwise Registration

2 participants