Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Descrepancy in performance of AntsPy Behaviour when running in a loop for a long time. #552

Open
tushaarkataria opened this issue Feb 21, 2024 · 7 comments
Assignees

Comments

@tushaarkataria
Copy link

I am trying to register patches of size 12000x12000 that are sampled from a bigger image. I am observing inconsistent performance of AntsPy.

Let's say i have 20 patches of the above mentioned size. Ants framework when executed with a python scripts works for 18 of them and doesn't for the other 2. By doesn't i mean, it gives bad performance on registration. If I rerun it still works for 18 of them, but the 2 for which it doesn't work, are different patches. AntsPy is performing inconsistently while in a loop.

Then I tested running ants on those 2 patches using a Notebook, and it registered them well. So Ants is working but AntsPy while in a loop is not.

I am not sure how to debug this issue ? Can it be a memory flushing issue ?? But i see in the AntsPy Code that it's calling a binary, which i think gets flushed on it own.

Has anyone else come across this issue ?? Any help would be appreciated.

@cookpa
Copy link
Member

cookpa commented Feb 21, 2024

We can help more if you can share code and example data.

There is variation in registration due to random sampling, which you can disable by using one of the "repro" methods in antsRegistration.

It is suspicious if it works for exactly 18 and fails for 2 every time. What if you run the same patch 20 times?

@tushaarkataria
Copy link
Author

I tried the "repro" setting and flushing all the variables related to the registration but i still see the same issue.

And i just want to clarify, it's kind of like 2-3 out the 20 patches, but similar in percentage when compared to the total number of patches like approximately 10-20% of the patches are not registered. But I can chalk that upto optimization issue and feature issue that i used for registration.

It's when i try to register the same un-registered image from the previous run in a notebook or another script, it registers well. I am not sure how to debug that behavior.

@cookpa
Copy link
Member

cookpa commented Feb 23, 2024

I made a 2D example experiment here

https://github.com/cookpa/antsPyRegistrationStability

Basically, I took a slice from two 0.5mm T1w images, then ran registration 500 times, using

  1. antsRegistrationSyN.sh on the command line
  2. ants.registration in a for loop
  3. ants.registration outside of a for loop

Here's a plot of the CC metric (radius = 4) after registration. These are negative values as used in ANTs optimizers so a more negative number is greater similarity

image

I did notice a few outliers in both the CLI and the python output, but I don't see strong evidence that using a for loop makes things worse.

The failure rate is subjective but to my eye it was less than 10-20%. If your registrations are more unstable, here's a few things you could try:

  1. Pad the images. Having images extend all the way to the boundary of the FOV can lead to stability issues. ImageMath PadImage can be used to add (say 20 voxels of) empty space around the borders before registration. This doesn't change the physical space so you can still apply the transforms to the original images.

  2. Change the default downsampling and smoothing. The default parameters have been somewhat optimized for 3D anatomical images. It might be downsampling or smoothing too much.

  3. Check initialization. The default is to align the center of mass of the two images, if this is likely to go wrong (eg, there are negative intensities), an alternative strategy may be required.

  4. Check affine registration. This is faster and its worth optimizing this a bit because a poor affine stage will often lead to bad deformable results.

  5. Impose regularization eg using a transform like SyN[0.2, 3,1] rather than the default SyN[0.2, 3,0]. If the problem is unreasonably large deformations in the syn stage.

@cookpa
Copy link
Member

cookpa commented Mar 16, 2024

@tushaarkataria it looks like you were definitely on to something! #579

@cookpa cookpa self-assigned this Mar 21, 2024
@cookpa
Copy link
Member

cookpa commented Mar 22, 2024

OK we've tried our best to eliminate any uninitialized memory being accessed in images. I'm not certain that this was affecting antsRegistration, but it was affecting cortical thickness in a similar way. Anyway, wheels available here if anyone wants to try them out

https://github.com/ANTsX/ANTsPy/actions/runs/8392167991

@cookpa
Copy link
Member

cookpa commented Mar 28, 2024

I updated the scripts here

https://github.com/cookpa/antsPyRegistrationStability

to use the "repro" mode options. I get 100% reproducible results over 100 runs even before the recent fixes, so maybe registration wasn't affected? Though other functions definitely were. Running more iterations now to confirm

@cookpa
Copy link
Member

cookpa commented Mar 28, 2024

Confirmed after 500 iterations - registration of the same data is 100% deterministic with this call

import ants
import sys

fi = ants.image_read('data/fixed_slice_2d.nii.gz')
mi = ants.image_read('data/moving_slice_2d.nii.gz')

iterations = int(sys.argv[1])

for i in range(iterations):
    reg = ants.registration(fixed=fi, moving=mi, type_of_transform='antsRegistrationSyNQuickRepro[s]')

    deformed_mi = ants.apply_transforms(fixed=fi, moving=mi, transformlist=reg['fwdtransforms'])

    ants.image_write(deformed_mi, 'output/antspy_loop/moving_deformed_iteration_{:04d}.nii.gz'.format(i))

    if (i + 1) % int(iterations / 10) == 0:
        print(f"Iteration {i + 1}/{iterations} completed.")

On Mac OS 12 (Intel) with ANTsPy 0.4.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants