ENHANCE-PET / FALCON

FALCON is a Python-based software application designed to facilitate PET motion correction, both for head and total-body scans. Our program is built around the fast 'greedy' registration toolkit, which serves as the registration engine. With FALCON, users can enjoy a streamlined experience for implementing motion correction.
GNU General Public License v3.0
36 stars 6 forks source link

Analysis: Find a way to apply motion and recover the applied motion (systematically) #29

Closed LalithShiyam closed 2 years ago

LalithShiyam commented 2 years ago

To prove falcon actually works it is crucial to show that the artificially applied motion (via simpleITK) can be recovered as well. I think the motion parameters will not be the same if the rotation/translation is applied together. Might be wise to just validate both the aspects individually. Further analysis needed!

LalithShiyam commented 2 years ago

Imposed motion can actually be recovered as long as the radians imposed are less than 0.1 in all three axes. Workflow:

import SimpleITK as sitk
image = sitk.ReadImage('./Flipped-Zubal-028.nii')
transform = sitk.Euler3DTransform()
transform.SetCenter(image.TransformContinuousIndexToPhysicalPoint([(sz-1)/2 for sz in image.GetSize()]))
transform.SetTranslation([10,5,8]) # in mm, can go till 20.
transform.SetRotation(0.09,0.08,0.08); # make sure they don't exceed 0.1

resampled_image = sitk.Resample(image, transform)
sitk.WriteImage(resampled_image, './transformed_image_028.nii')

In the meantime, I will pass this on to @Keyn34!

LalithShiyam commented 2 years ago

In case, we cannot make a script to decompose the matrix accurately or if paul doesn't respond in a day or two. I would suggest doing the analysis manually using itksnap GUI. I understand it is boring, but if we put our heads together, we should be able to get it done in 3 days max. We need to get this manuscript out. @DariaFerrara @josefyu would you guys help @Keyn34?

LalithShiyam commented 2 years ago

@Keyn34 found a way to make the imposed motion (via simpleITK) and recovered motion (rigid.mat after registration) comparable.

[1] Apply transform

import SimpleITK as sitk
image = sitk.ReadImage('./Flipped-Zubal-028.nii')
transform = sitk.Euler3DTransform()
transform.SetCenter(image.TransformContinuousIndexToPhysicalPoint([(sz-1)/2 for sz in image.GetSize()]))
transform.SetTranslation([10,5,8]) # mm
transform.SetRotation(0.09,0.08,0.08); # 1.145916,0.5729578,1.718873 in deg

resampled_image = sitk.Resample(image, transform)
sitk.WriteImage(resampled_image, './transformed_image_028.nii')

# [2] Write the inverse transform 

sitk.WriteTransform(transform.GetInverse(),'sitk_inv_tfm.mat')

# [3] Run registration 

# [4] Use c3d_affine_tool to convert the spit out 'rigid.mat' to itk format.

cmd_to_run = 'c3d_affine_tool rigid.mat -oitk greedy_tfm.mat'
os.system(cmd_to_run)

# [5] Use c3d_affine to load the sitk_inv_tfm.mat and convert it to 'greedy' based 'itk' format

cmd_to_run = 'c3d_affine_tool -itk sitk_inv_tfm.mat -oitk sitk_inv_tfm.mat'
os.system(cmd_to_run)

# [6] load both the transforms

greedy_tfm = sitk.ReadTransform('greedy_tfm.mat')
sitk_tfm = sitk.ReadTransform('sitk_inv_tfm.mat')

# [7] Use get parameters to look at the transformation matrix (last three translation, the remaining rotation matrix)

greedy_tfm.GetParameters()
sitk_tfm.GetParameters()
LalithShiyam commented 2 years ago

I wrote a script to parse the rotation and translation parameters directly from the transform.txt file

# Get the simpleITK transform parameters 

cmd_to_run = 'c3d_affine_tool -itk sit_inv_tfm.mat -info-full > sitk_inv_tfm.txt'
os.system(cmd_to_run)

# Get the registration transform parameters 

cmd_to_run = 'c3d_affine_tool -itk greedy_tfm.mat -info-full > greedy_tfm.txt'
os.system(cmd_to_run)

# function for getting motion parameters from transform.txt file

import re 

def get_motion_parameters(path_transform_txt: str): 
    transform_file = open(path_transform_txt, "r")
    content = transform_file.read()
    content_list = content.split("\n")
    parameters_txt = str(content_list[9])
    parameters = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?",parameters_txt)
    translation = parameters[0:3]
    rotation = parameters[3:6]
    return translation, rotation

# load translation, rotation parameters for each of the transform files 

trans_greedy, rotation_greedy = get_motion_parameters('/greedy_tfm.txt')
trans_sitk, rotation_sitk = get_motion_parameters('/sitk_inv_tfm.txt')
LalithShiyam commented 2 years ago

@josefyu @DariaFerrara I don't think we need your help with this task now ;)! Everything should be automated. @Keyn34 when you create your evaluation scripts. Kindly add them to a folder called ./FALCON/eval.

Keyn34 commented 2 years ago

Currently doing a test run.

Keyn34 commented 2 years ago

Additional tasks:

LalithShiyam commented 2 years ago

Can we close this? @Keyn34 n

Keyn34 commented 2 years ago

Yep!

Keyn34 commented 2 years ago

Reopened issue for keeping track of manual motion extraction via ITK-Snap

Keyn34 commented 2 years ago

Data extracted and send to Otto. Closing it again!