ANTsX / ANTsPy

A fast medical imaging analysis library in Python with algorithms for registration, segmentation, and more.
https://antspyx.readthedocs.io
Apache License 2.0
628 stars 161 forks source link

ants_transform.apply_to_image broken for displacement field transforms #686

Closed cookpa closed 1 month ago

cookpa commented 1 month ago

Describe the bug

Cannot call apply_to_image with displacement field transforms on master, works on 0.5.2.

To reproduce

Example from #684 (not related to the issue there)

import ants
import numpy as np

moving_ants = ants.image_read(ants.get_data("r16"))
fixed_ants = ants.image_read(ants.get_data("r27"))
registration = ants.registration(moving=moving_ants, fixed=fixed_ants, type_of_transform="SyN")

transformed_normal = ants.apply_transforms(
    fixed=fixed_ants,
    moving=moving_ants,
    transformlist=registration['fwdtransforms'],
    )

transformed_manual = moving_ants
transform = ants.transform_from_displacement_field(ants.image_read(registration['fwdtransforms'][0]))
transformed_manual = transform.apply_to_image(transformed_manual, reference=fixed_ants)

the last line produces the error

>>> transformed_manual = transform.apply_to_image(transformed_manual, reference=fixed_ants)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/miniconda3/envs/antspydevel/lib/python3.11/site-packages/ants/core/ants_transform.py", line 188, in apply_to_image
    img_ptr = tform_fn(self.pointer, image.pointer, reference.pointer, interpolation)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: transformImage(): incompatible function arguments. The following argument types are supported:
    1. transformImage(arg0: ants.lib.AntsTransformF22, arg1: ants.lib.AntsImageUC2, arg2: ants.lib.AntsImageUC2, arg3: str, /) -> ants.lib.AntsImageUC2
    2. transformImage(arg0: ants.lib.AntsTransformF33, arg1: ants.lib.AntsImageUC3, arg2: ants.lib.AntsImageUC3, arg3: str, /) -> ants.lib.AntsImageUC3
    3. transformImage(arg0: ants.lib.AntsTransformF44, arg1: ants.lib.AntsImageUC4, arg2: ants.lib.AntsImageUC4, arg3: str, /) -> ants.lib.AntsImageUC4
    4. transformImage(arg0: ants.lib.AntsTransformD22, arg1: ants.lib.AntsImageUC2, arg2: ants.lib.AntsImageUC2, arg3: str, /) -> ants.lib.AntsImageUC2
    5. transformImage(arg0: ants.lib.AntsTransformD33, arg1: ants.lib.AntsImageUC3, arg2: ants.lib.AntsImageUC3, arg3: str, /) -> ants.lib.AntsImageUC3
    6. transformImage(arg0: ants.lib.AntsTransformD44, arg1: ants.lib.AntsImageUC4, arg2: ants.lib.AntsImageUC4, arg3: str, /) -> ants.lib.AntsImageUC4
    7. transformImage(arg0: ants.lib.AntsTransformF22, arg1: ants.lib.AntsImageUI2, arg2: ants.lib.AntsImageUI2, arg3: str, /) -> ants.lib.AntsImageUI2
    8. transformImage(arg0: ants.lib.AntsTransformF33, arg1: ants.lib.AntsImageUI3, arg2: ants.lib.AntsImageUI3, arg3: str, /) -> ants.lib.AntsImageUI3
    9. transformImage(arg0: ants.lib.AntsTransformF44, arg1: ants.lib.AntsImageUI4, arg2: ants.lib.AntsImageUI4, arg3: str, /) -> ants.lib.AntsImageUI4
    10. transformImage(arg0: ants.lib.AntsTransformD22, arg1: ants.lib.AntsImageUI2, arg2: ants.lib.AntsImageUI2, arg3: str, /) -> ants.lib.AntsImageUI2
    11. transformImage(arg0: ants.lib.AntsTransformD33, arg1: ants.lib.AntsImageUI3, arg2: ants.lib.AntsImageUI3, arg3: str, /) -> ants.lib.AntsImageUI3
    12. transformImage(arg0: ants.lib.AntsTransformD44, arg1: ants.lib.AntsImageUI4, arg2: ants.lib.AntsImageUI4, arg3: str, /) -> ants.lib.AntsImageUI4
    13. transformImage(arg0: ants.lib.AntsTransformF22, arg1: ants.lib.AntsImageF2, arg2: ants.lib.AntsImageF2, arg3: str, /) -> ants.lib.AntsImageF2
    14. transformImage(arg0: ants.lib.AntsTransformF33, arg1: ants.lib.AntsImageF3, arg2: ants.lib.AntsImageF3, arg3: str, /) -> ants.lib.AntsImageF3
    15. transformImage(arg0: ants.lib.AntsTransformF44, arg1: ants.lib.AntsImageF4, arg2: ants.lib.AntsImageF4, arg3: str, /) -> ants.lib.AntsImageF4
    16. transformImage(arg0: ants.lib.AntsTransformD22, arg1: ants.lib.AntsImageF2, arg2: ants.lib.AntsImageF2, arg3: str, /) -> ants.lib.AntsImageF2
    17. transformImage(arg0: ants.lib.AntsTransformD33, arg1: ants.lib.AntsImageF3, arg2: ants.lib.AntsImageF3, arg3: str, /) -> ants.lib.AntsImageF3
    18. transformImage(arg0: ants.lib.AntsTransformD44, arg1: ants.lib.AntsImageF4, arg2: ants.lib.AntsImageF4, arg3: str, /) -> ants.lib.AntsImageF4
    19. transformImage(arg0: ants.lib.AntsTransformF22, arg1: ants.lib.AntsImageD2, arg2: ants.lib.AntsImageD2, arg3: str, /) -> ants.lib.AntsImageD2
    20. transformImage(arg0: ants.lib.AntsTransformF33, arg1: ants.lib.AntsImageD3, arg2: ants.lib.AntsImageD3, arg3: str, /) -> ants.lib.AntsImageD3
    21. transformImage(arg0: ants.lib.AntsTransformF44, arg1: ants.lib.AntsImageD4, arg2: ants.lib.AntsImageD4, arg3: str, /) -> ants.lib.AntsImageD4
    22. transformImage(arg0: ants.lib.AntsTransformD22, arg1: ants.lib.AntsImageD2, arg2: ants.lib.AntsImageD2, arg3: str, /) -> ants.lib.AntsImageD2
    23. transformImage(arg0: ants.lib.AntsTransformD33, arg1: ants.lib.AntsImageD3, arg2: ants.lib.AntsImageD3, arg3: str, /) -> ants.lib.AntsImageD3
    24. transformImage(arg0: ants.lib.AntsTransformD44, arg1: ants.lib.AntsImageD4, arg2: ants.lib.AntsImageD4, arg3: str, /) -> ants.lib.AntsImageD4

Invoked with types: ants.lib.AntsTransformDF2, ants.lib.AntsImageF2, ants.lib.AntsImageF2, str

Expected behavior

Apply the transform

Screenshots

ANTsPy installation (please complete the following information):

cookpa commented 1 month ago

@ncullen93 might you have time to take a look at this? I'm not sure what the best fix would be

cookpa commented 1 month ago

Actually I think I might have fixed it, by declaring the transform methods with displacement field transforms

+    // displacement field transforms
+    m.def("transformImage", &transformImage<itk::DisplacementFieldTransform<float,2>, itk::Image<double, 2>>);
+    m.def("transformImage", &transformImage<itk::DisplacementFieldTransform<float,2>, itk::Image<float, 2>>);
+    m.def("transformImage", &transformImage<itk::DisplacementFieldTransform<double,2>, itk::Image<double, 2>>);
+    m.def("transformImage", &transformImage<itk::DisplacementFieldTransform<double,2>, itk::Image<float, 2>>);

Will test more