Skip to content

fix: replace absolute intra-package imports with relative imports#67

Merged
aylward merged 3 commits into
Project-MONAI:mainfrom
aylward:import_and_ants
Jun 14, 2026
Merged

fix: replace absolute intra-package imports with relative imports#67
aylward merged 3 commits into
Project-MONAI:mainfrom
aylward:import_and_ants

Conversation

@aylward

@aylward aylward commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

All submodules imported from physiomotion4d.X import Y (or from physiomotion4d import Y), which causes a circular import error at package initialization time — __init__.py imports each submodule while the submodules try to reach back into the partially-initialized package. This fails consistently regardless of install method (pip install ., editable install, or PyPI wheel).

Replaced all 34 affected files with PEP 328 relative imports (from .X import Y for package submodules, from ..X import Y for the cli/ sub-package). Docstring examples left unchanged.

Summary by CodeRabbit

  • Documentation

    • Updated guides, experiment README, and tutorials to describe the registration pipeline as Greedy affine + ICON deformable; clarified ICON refinement applies to the mask-to-image stage, runtime expectations, requirements, and troubleshooting.
  • Refactor

    • Simplified registration-related interfaces and updated workflows to reflect the Greedy affine + ICON deformable pipeline while preserving user-facing behavior.

All submodules imported `from physiomotion4d.X import Y` (or
`from physiomotion4d import Y`), which causes a circular import error
at package initialization time — `__init__.py` imports each submodule
while the submodules try to reach back into the partially-initialized
package. This fails consistently regardless of install method (pip
install ., editable install, or PyPI wheel).

Replaced all 34 affected files with PEP 328 relative imports
(`from .X import Y` for package submodules, `from ..X import Y` for
the cli/ sub-package). Docstring examples left unchanged.
Copilot AI review requested due to automatic review settings June 12, 2026 19:46
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60f9afb7-3210-4ecf-a899-f424b0c23d87

📥 Commits

Reviewing files that changed from the base of the PR and between e85710d and da6ad14.

📒 Files selected for processing (1)
  • src/physiomotion4d/register_models_distance_maps.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/physiomotion4d/register_models_distance_maps.py

Walkthrough

Replaces ANTs/SyN distance-map registration with a Greedy affine + ICON deformable pipeline, updates RegisterModelsDistanceMaps API and compositions, removes Stage-3 ICON toggle from workflow calls, revises docs/notebooks/READMEs, and converts many absolute imports to package-relative imports.

Changes

Greedy + ICON Registration

Layer / File(s) Summary
RegisterModelsDistanceMaps core
src/physiomotion4d/register_models_distance_maps.py
Switches from ANTs to Greedy registrar, changes register() signature to transform_type/icon_iterations, runs Greedy then ICON for Deformable, composes transforms, and updates docstrings/examples.
Workflow integration
src/physiomotion4d/workflow_fit_statistical_model_to_patient.py, src/physiomotion4d/workflow_create_statistical_model.py, experiments/Heart-Statistical_Model_To_Patient/heart_model_to_patient.py
Removes mask-to-mask ICON toggle/parameter; Stage 3 now uses Greedy affine + ICON deformable and register() calls no longer pass use_ICON. run_workflow retains use_ICON_registration_refinement for Stage 4.
Docs and examples
docs/cli_scripts/fit_statistical_model_to_patient.rst, experiments/Heart-Create_Statistical_Model/*, tutorials/tutorial_04_fit_statistical_model_to_patient.py
Documentation, README, notebook text, runtime/requirements, citations, and troubleshooting updated to reference Greedy + ICON and clarify Stage 3 vs Stage 4 ICON usage.

Package Import Refactoring

Layer / File(s) Summary
CLI module imports
src/physiomotion4d/cli/*
CLI entry points converted from absolute physiomotion4d imports to relative .. imports for workflows and utilities.
Registration & related modules
src/physiomotion4d/register_*.py, src/physiomotion4d/register_models_*.py, src/physiomotion4d/register_time_series_images.py
Registration modules updated to use package-relative imports for ImageTools, TransformTools, LabelmapTools, and base classes.
Segmentation & workflows
src/physiomotion4d/segment_*, src/physiomotion4d/workflow_*.py
Segmentation and workflow modules updated to package-relative imports; workflow docstrings updated to Greedy + ICON where present.
Utilities & tools
src/physiomotion4d/*_tools.py, src/physiomotion4d/convert_*.py, src/physiomotion4d/test_tools.py
Utility modules converted to relative imports for shared dependencies; runtime behavior unchanged.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Project-MONAI/physiomotion4d#62: Modifies ICON behavior and wiring in WorkflowFitStatisticalModelToPatient’s mask-to-mask and labelmap-to-image registration steps.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: replacing absolute intra-package imports with relative imports across 34 files to fix circular import errors.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to eliminate circular imports during physiomotion4d package initialization by switching intra-package imports from absolute (from physiomotion4d...) to PEP 328 relative imports (from . ..., from .. ...). In addition, it updates the mask-based model registration pipeline and accompanying docs/experiments to reflect a Greedy+ICON workflow.

Changes:

  • Replace absolute intra-package imports with relative imports across modules and CLI subpackage.
  • Refactor RegisterModelsDistanceMaps to use Greedy (rigid/affine) + ICON (deformable) and update call sites accordingly.
  • Update documentation/experiments to reflect the new registration pipeline and changed workflow API.

Reviewed changes

Copilot reviewed 41 out of 41 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tutorials/tutorial_04_fit_statistical_model_to_patient.py Minor tutorial comment tweak around Windows multiprocessing guard.
src/physiomotion4d/workflow_reconstruct_highres_4d_ct.py Switch workflow imports to relative to avoid package init cycles.
src/physiomotion4d/workflow_fit_statistical_model_to_patient.py Relative imports + mask-to-mask stage API/call updates.
src/physiomotion4d/workflow_fine_tune_icon_registration.py Switch workflow imports to relative.
src/physiomotion4d/workflow_create_statistical_model.py Relative imports + update usage of distance-map registrar API.
src/physiomotion4d/workflow_convert_vtk_to_usd.py Switch workflow imports to relative.
src/physiomotion4d/workflow_convert_image_to_vtk.py Relative imports, including lazy-import segmenter paths.
src/physiomotion4d/workflow_convert_image_to_usd.py Replace from physiomotion4d import ... with local relative imports.
src/physiomotion4d/usd_tools.py Switch imports to relative.
src/physiomotion4d/usd_anatomy_tools.py Switch imports to relative.
src/physiomotion4d/transform_tools.py Switch imports to relative.
src/physiomotion4d/test_tools.py Switch imports to relative, including a local import inside helper.
src/physiomotion4d/segment_heart_simpleware.py Switch base-class import to relative.
src/physiomotion4d/segment_chest_total_segmentator.py Switch base-class import to relative.
src/physiomotion4d/segment_anatomy_base.py Switch internal imports to relative.
src/physiomotion4d/register_time_series_images.py Switch internal imports to relative.
src/physiomotion4d/register_models_pca.py Switch internal imports to relative.
src/physiomotion4d/register_models_icp.py Switch internal imports to relative.
src/physiomotion4d/register_models_icp_itk.py Switch internal imports to relative.
src/physiomotion4d/register_models_distance_maps.py Switch internal imports to relative; refactor implementation/docs to Greedy+ICON and update API.
src/physiomotion4d/register_images_icon.py Switch internal imports to relative.
src/physiomotion4d/register_images_greedy.py Switch internal imports to relative (including local imports).
src/physiomotion4d/register_images_base.py Switch internal imports to relative.
src/physiomotion4d/register_images_ants.py Switch internal imports to relative (including local imports).
src/physiomotion4d/landmark_tools.py Switch internal imports to relative.
src/physiomotion4d/labelmap_tools.py Switch internal imports to relative.
src/physiomotion4d/image_tools.py Switch internal imports to relative.
src/physiomotion4d/convert_image_4d_to_3d.py Switch internal imports to relative.
src/physiomotion4d/contour_tools.py Switch internal imports to relative.
src/physiomotion4d/cli/reconstruct_highres_4d_ct.py Change CLI import to relative-from-parent package.
src/physiomotion4d/cli/fit_statistical_model_to_patient.py Change CLI import to relative-from-parent package.
src/physiomotion4d/cli/download_data.py Change CLI import to relative-from-parent package module.
src/physiomotion4d/cli/create_statistical_model.py Change CLI import to relative-from-parent package.
src/physiomotion4d/cli/convert_vtk_to_usd.py Change CLI imports to relative-from-parent package.
src/physiomotion4d/cli/convert_image_to_vtk.py Change CLI import to relative-from-parent package.
src/physiomotion4d/cli/convert_image_to_usd.py Change CLI import to relative-from-parent package.
src/physiomotion4d/cli/convert_image_4d_to_3d.py Change CLI import to relative-from-parent package.
experiments/Heart-Statistical_Model_To_Patient/heart_model_to_patient.py Update call to mask-to-mask registration after API change.
experiments/Heart-Create_Statistical_Model/README.md Update narrative/docs from ANTs SyN to Greedy+ICON pipeline.
experiments/Heart-Create_Statistical_Model/3-registration_based_correspondence.py Update experiment steps and registrar call to new API.
docs/cli_scripts/fit_statistical_model_to_patient.rst Update CLI documentation for ICON refinement semantics and mask-to-mask stage description.
Comments suppressed due to low confidence (1)

src/physiomotion4d/register_models_distance_maps.py:255

  • The register() docstring says the return dict contains 'moving_model', but the method actually returns 'registered_model'. This makes the API documentation inaccurate for callers reading the docstring.
        Returns:
            Dictionary containing:
                - 'moving_model': Aligned moving model (PyVista PolyData)
                - 'forward_transform': Moving→fixed transform (ITK CompositeTransform)
                - 'inverse_transform': Fixed→moving transform (ITK CompositeTransform)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 314 to 330
# Pre-align moving mask with the Greedy affine result
moving_mask_affine_transformed = self.transform_tools.transform_image(
self.moving_mask_image,
forward_transform_ANTS,
forward_transform_Greedy,
self.reference_image,
interpolation_method="linear",
)

# Configure ICON
# Configure and run ICON
self.registrar_ICON.set_number_of_iterations(icon_iterations)
self.registrar_ICON.set_fixed_image(self.fixed_mask_image)
self.registrar_ICON.set_fixed_mask(self.fixed_mask_roi_image)

# ICON registration
result_ICON = self.registrar_ICON.register(
moving_image=moving_mask_ANTS_transformed,
moving_image=moving_mask_affine_transformed,
moving_mask=self.moving_mask_roi_image,
)
Comment on lines 1 to +10
"""Mask-based model-to-model registration for anatomical models.

This module provides the RegisterModelsDistanceMaps class for aligning anatomical
models using mask-based deformable registration. The workflow includes:
1. Generate binary masks from moving and fixed models
2. Generate ROI masks with dilation
4. Progressive registration stages:
- rigid: ANTs rigid registration
- affine: ANTs rigid → affine registration
- deformable: ANTs rigid → affine → deformable (SyN) registration
5. Optional ICON refinement at end
3. Progressive registration stages:
- rigid: Greedy rigid registration
- affine: Greedy affine registration
- deformable: Greedy affine → ICON deformable registration

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/physiomotion4d/register_models_distance_maps.py`:
- Around line 315-330: The moving ROI mask is still the untransformed mask
(moving_mask_roi_image) when calling registrar_ICON.register, causing a space
mismatch; transform the ROI mask with the same affine pre-alignment (use
transform_tools.transform_image with forward_transform_Greedy and the same
reference_image) — use a mask-appropriate interpolation (e.g., nearest) — and
pass that transformed ROI (instead of moving_mask_roi_image) into
registrar_ICON.register; update references around
moving_mask_affine_transformed, moving_mask_roi_image,
transform_tools.transform_image, forward_transform_Greedy, and
registrar_ICON.register.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f8685517-7da6-4a16-bc53-563718b44de2

📥 Commits

Reviewing files that changed from the base of the PR and between c792bb1 and d27decc.

📒 Files selected for processing (41)
  • docs/cli_scripts/fit_statistical_model_to_patient.rst
  • experiments/Heart-Create_Statistical_Model/3-registration_based_correspondence.py
  • experiments/Heart-Create_Statistical_Model/README.md
  • experiments/Heart-Statistical_Model_To_Patient/heart_model_to_patient.py
  • src/physiomotion4d/cli/convert_image_4d_to_3d.py
  • src/physiomotion4d/cli/convert_image_to_usd.py
  • src/physiomotion4d/cli/convert_image_to_vtk.py
  • src/physiomotion4d/cli/convert_vtk_to_usd.py
  • src/physiomotion4d/cli/create_statistical_model.py
  • src/physiomotion4d/cli/download_data.py
  • src/physiomotion4d/cli/fit_statistical_model_to_patient.py
  • src/physiomotion4d/cli/reconstruct_highres_4d_ct.py
  • src/physiomotion4d/contour_tools.py
  • src/physiomotion4d/convert_image_4d_to_3d.py
  • src/physiomotion4d/image_tools.py
  • src/physiomotion4d/labelmap_tools.py
  • src/physiomotion4d/landmark_tools.py
  • src/physiomotion4d/register_images_ants.py
  • src/physiomotion4d/register_images_base.py
  • src/physiomotion4d/register_images_greedy.py
  • src/physiomotion4d/register_images_icon.py
  • src/physiomotion4d/register_models_distance_maps.py
  • src/physiomotion4d/register_models_icp.py
  • src/physiomotion4d/register_models_icp_itk.py
  • src/physiomotion4d/register_models_pca.py
  • src/physiomotion4d/register_time_series_images.py
  • src/physiomotion4d/segment_anatomy_base.py
  • src/physiomotion4d/segment_chest_total_segmentator.py
  • src/physiomotion4d/segment_heart_simpleware.py
  • src/physiomotion4d/test_tools.py
  • src/physiomotion4d/transform_tools.py
  • src/physiomotion4d/usd_anatomy_tools.py
  • src/physiomotion4d/usd_tools.py
  • src/physiomotion4d/workflow_convert_image_to_usd.py
  • src/physiomotion4d/workflow_convert_image_to_vtk.py
  • src/physiomotion4d/workflow_convert_vtk_to_usd.py
  • src/physiomotion4d/workflow_create_statistical_model.py
  • src/physiomotion4d/workflow_fine_tune_icon_registration.py
  • src/physiomotion4d/workflow_fit_statistical_model_to_patient.py
  • src/physiomotion4d/workflow_reconstruct_highres_4d_ct.py
  • tutorials/tutorial_04_fit_statistical_model_to_patient.py

Comment thread src/physiomotion4d/register_models_distance_maps.py
@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.65354% with 36 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.92%. Comparing base (c792bb1) to head (da6ad14).

Files with missing lines Patch % Lines
...rc/physiomotion4d/register_models_distance_maps.py 20.00% 24 Missing ⚠️
src/physiomotion4d/register_images_greedy.py 50.00% 3 Missing ⚠️
src/physiomotion4d/cli/convert_image_4d_to_3d.py 0.00% 1 Missing ⚠️
src/physiomotion4d/cli/convert_image_to_vtk.py 0.00% 1 Missing ⚠️
src/physiomotion4d/cli/convert_vtk_to_usd.py 50.00% 1 Missing ⚠️
src/physiomotion4d/cli/create_statistical_model.py 0.00% 1 Missing ⚠️
...iomotion4d/cli/fit_statistical_model_to_patient.py 0.00% 1 Missing ⚠️
...rc/physiomotion4d/cli/reconstruct_highres_4d_ct.py 0.00% 1 Missing ⚠️
src/physiomotion4d/register_images_ants.py 66.66% 1 Missing ⚠️
...rc/physiomotion4d/workflow_convert_image_to_vtk.py 83.33% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #67      +/-   ##
==========================================
+ Coverage   32.90%   32.92%   +0.01%     
==========================================
  Files          53       53              
  Lines        7229     7229              
==========================================
+ Hits         2379     2380       +1     
+ Misses       4850     4849       -1     
Flag Coverage Δ
integration-tests 32.81% <71.65%> (?)
unittests 32.90% <71.65%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings June 13, 2026 01:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 41 out of 41 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/physiomotion4d/register_models_distance_maps.py:255

  • The register() docstring lists a 'moving_model' return key, but the implementation returns 'registered_model'. This is a public-facing API mismatch and can lead to KeyError in user code that follows the docs.
        Returns:
            Dictionary containing:
                - 'moving_model': Aligned moving model (PyVista PolyData)
                - 'forward_transform': Moving→fixed transform (ITK CompositeTransform)
                - 'inverse_transform': Fixed→moving transform (ITK CompositeTransform)

Comment on lines 3 to +7
This module provides the RegisterModelsDistanceMaps class for aligning anatomical
models using mask-based deformable registration. The workflow includes:
1. Generate binary masks from moving and fixed models
2. Generate ROI masks with dilation
4. Progressive registration stages:
- rigid: ANTs rigid registration
- affine: ANTs rigid → affine registration
- deformable: ANTs rigid → affine → deformable (SyN) registration
5. Optional ICON refinement at end
3. Progressive registration stages:
Comment on lines 225 to 229
def register(
self,
transform_type: str = "Deformable",
use_ICON: bool = False,
icon_iterations: int = 50,
) -> dict:
Comment on lines 83 to 87
**Advantages:**
- Fully automated (no manual parameter tuning)
- Handles complex topologies naturally
- Diffeomorphic guarantees smooth, invertible deformations
- Composed Greedy + ICON transforms provide smooth, invertible deformation fields
- Integrates seamlessly with medical imaging pipelines
Comment on lines +338 to +342
# - The `RegisterModelsDistanceMaps` class uses a two-stage pipeline:
# 1. **Greedy affine** registration (fast CPU-based alignment)
# 2. **ICON deformable** registration on the affine-pre-aligned masks (deep learning)
# - The `roi_dilation_mm` parameter controls the dilation of the ROI mask (default 20mm)
# - SyN registration provides smooth, invertible deformation fields for anatomical correspondence
# - Composed Greedy + ICON transforms provide smooth, invertible deformation fields for anatomical correspondence
@aylward aylward merged commit f3bf2f8 into Project-MONAI:main Jun 14, 2026
12 checks passed
@aylward aylward deleted the import_and_ants branch June 14, 2026 11:32
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.

2 participants