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 MultiStep Registration and Apply Transform Example #43

Closed dgutman closed 5 years ago

dgutman commented 5 years ago

I am analyzing some DTI data, and want to use ANTS (instead of FSL) to warp my results to MNI space. I am trying to find some reference code to make sure I am applying the transforms in the right order.

From what I've read and experimented with, I have done the following.

I used antsRegistrationSynQuick.sh

B0 --> StructT1 (transform_type=r/Rigid) (Generated Single Affine Matrix) StructT1-->MNI152_T1_1mm (transform_type=s)
(Generated matrix, Warp and InverseWarp)

I have then been using WarpImageMultiTransform to convert results in B0 Space --> MNI and also tried to warp ROI's in MNI Space --> B0 Space

Bash Examples

WarpImageMultiTransform 3 $nodifMask nodifMask_to_MNI.nii.gz -R $mni1mm --use-NN $dtiToStructAff $structToMNIAff $structoToMNIwarp

Also looking to do the reverse (i.e. warp the MNI brain to the nodif brain).

WarpImageMultiTransform 3 $mni1mm mni_to_nodif -R $nodif_brain --use-NN $structoToMNIInverseWarp -i $structToMNIAff -i $dtiToStructAff

Are there any examples on how to do this using AntsPy?

stnava commented 5 years ago

here is an example, as you requested, as a jupyter notebook

https://github.com/ANTsX/ANTsPy/blob/master/tutorials/concatenateRegistrations.ipynb

dgutman commented 5 years ago

Thank you very much! I appreciate your effort. ANTS is quite an amazing toolkit.

On Fri, Nov 2, 2018 at 5:15 PM stnava notifications@github.com wrote:

here is an example, as you requested, as a jupyter notebook

https://github.com/ANTsX/ANTsPy/blob/master/tutorials/concatenateRegistrations.ipynb

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ANTsX/ANTsPy/issues/43#issuecomment-435510021, or mute the thread https://github.com/notifications/unsubscribe-auth/AArhzmhQHS2rnF2wtJY8fJOMgGckcmtuks5urLXUgaJpZM4XHU37 .

-- David A Gutman MD PhD Assistant Professor of Neurology, Psychiatry & Biomedical Informatics Emory University School of Medicine Staff Physician, Mental Health Service Line Atlanta VA Medical Center

pietroastolfi commented 3 years ago

Hi, I'm having problem in replicating in ANTsPy the results obtained using WarpImageMultiTransforms. Given the same transformation (computed with ants as well) I obtain two very different output images.

ANTsPy Version: 0.2.6 ANTs Version: 2.3.4.dev187-gb37e8

Here the code I'm using:

fixed = ants.image_read(fixed_fn)
moving = ants.image_read(moving_fn)
warped = ants.apply_transforms(fixed=fixed,
                                     moving=moving,
                                     transformlist=[f'{tmp_dir}/tract2mni0GenericAffine.mat', f'{tmp_dir}/tract2mni1InverseWarp.nii.gz'],
                                     whichtoinvert=[True, False]
                                    )
ants.image_write(warped, f'{tmp_dir}/warped.nii.gz')

os.system(f'WarpImageMultiTransform 3 {moving_fn} {tmp_dir}/warped_cli.nii.gz -R {fixed_fn} -i {tmp_dir}/tract2mni0GenericAffine.mat {tmp_dir}/tract2mni1InverseWarp.nii.gz')

Then if I load and compare the two output images I obtain very different results:

warped_py = ants.image_read(f'{tmp_dir}/warped.nii.gz')
warped_cli = ants.image_read(f'{tmp_dir}/warped_cli.nii.gz')

np.array_equal(warped_py.view(), warped_cli.view()) 
>>> False

warped_py.view().mean() 
>>> -0.3322511
warped_cli.view().mean() 
>>> 27.890787

warped_py.view()[:2]
array([[[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]],

       [[0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        ...,
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.],
        [0., 0., 0., ..., 0., 0., 0.]]], dtype=float32)
warped_cli.view()[:2]
>>> array([[[90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.],
        ...,
        [90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.]],

       [[90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.],
        ...,
        [90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.],
        [90., 90., 90., ..., 90., 90., 90.]]], dtype=float32)

From the last print it seemed the difference could have been the default value =90. in one case versus =0. in the other case, but even after changing the defaultvalue=90. in ants.apply_transforms the two warped images result different.

ntustison commented 3 years ago

Please repost as a new issue. Also, please compare with antsApplyTransforms and not WarpImageMultiTransform as the latter is quasi-deprecated.

pietroastolfi commented 3 years ago

I answer right here because I've found a solution for my use-case, which is a particular case. (after you read this answer let me know if you still prefer I move all this discussion to a new issue).

First of all, just as a sanity check, I did the comparison you requested and it was successful i.e., antsApplyTransforms and ants.apply_transforms returned the same results.

Then, to clarify my use-case, I did the comparison considering as moving image an "identity" warp created using mrtrix, which is not a standard scalar positive image since it contains both negative and positive values. The apply transformation step is part of the conversion of an ants warp to a warp compatible with mrtrix. Here's the official mrtrix guide of the conversion [https://community.mrtrix.org/t/registration-using-transformations-generated-from-other-packages/2259].

The aforementioned guide contains also the answer to my problem, because it states how to substitute WarpImageMultiTransforms with antsApplyTransforms in this use-case. The gist is that mrtrix requires a marker value different from plausible values (after warpImageMultiTransform was 90.), that they transforms to NaN in a step warpcorrect that modifies the warp according to mrtrix requirements.

ntustison commented 3 years ago

Yes, please post as a new issue. This issue is closed. If it's related, you can always provide a link back to this issue.