Image taken from http://cnl.web.arizona.edu/imageprops.htm
For a voxel \(v\), the rigid transformation can be written as:
\[T_{\rm rigid}(v) = Rv + t\] where \(R =\) \[\left[\begin{array}{ccc} \cos\beta\cos\gamma& \cos\alpha\sin\gamma + \sin\alpha\sin\beta\cos\gamma & \sin\alpha\sin\gamma - \cos\alpha\sin\beta\cos\gamma \\ -\cos\beta\sin\gamma & \cos\alpha\cos\gamma - \sin\alpha\sin\beta\sin\gamma & \sin\alpha\cos\gamma + \cos\alpha\sin\beta\sin\gamma \\ \sin\beta & -\sin\alpha\cos\beta & \cos\alpha\cos\beta \end{array}\right]\]
l = list() l[[1]] = c(1, 2, 4, 5) l[[2]] = matrix(1:10, nrow = 2) print(l)
[[1]]
[1] 1 2 4 5
[[2]]
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
print(l[[1]])
[1] 1 2 4 5
If a vector has names, you can also put the - Initialize an empty list and add two elements to it
x = c(one = 1, three = 14, two = 5) print(x)
one three two
1 14 5
x[c("three")]
three 14
If a list has names, you can subset with the $
names(l) = c("V", "m"); l[["V"]]
[1] 1 2 4 5
If a list has names, you can also subset with the $
l$V
[1] 1 2 4 5
ms.lesion packageget_image_filenames_list_by_subject - returns a list, each element is a subject, and each subject has a vector of filenames, named for each modalitylibrary(ms.lesion) all_files = get_image_filenames_list_by_subject() class(all_files); names(all_files)
[1] "list"
[1] "test01" "test02" "test03" "training01" "training02" [6] "training03" "training04" "training05"
files = all_files$training01; class(files); names(files)
[1] "character"
[1] "T1" "T2" "FLAIR"
t1_fname = files["T1"] t1 = readnii(t1_fname) rt1 = robust_window(t1, probs = c(0, 0.975))
The registration function from extrantsr can register 2 images. The main arguments are:
filename - either nifti object or filename of image to be registered (moving)template.file - either nifti object or filename of target image (fixed)typeofTransform - transformation of moving to fixed image (Rigid/Affine/SyN)interpolator - how are voxels averaged in fixed space (Linear/NearestNeighbor/LanczosWindowedSinc)It can also perform bias correction if correct = TRUE.
For example, if we wanted to register the FLAIR to the T1 image, we would run:
library(extrantsr) reg = registration( filename = files["FLAIR"], template.file = files["T1"], typeofTransform = "Rigid", interpolator = "Linear", verbose = FALSE) names(reg)
[1] "outfile" "fwdtransforms" "invtransforms" [4] "interpolator" "other_interpolator" "invert_interpolator" [7] "typeofTransform" "retimg"
The output in reg would contain the transformed image and paths to the estimated transformations.
double_ortho(rt1, reg$outfile)
We would like to perform registration within a visit for all modalities. The extrantsr function within_visit_registration will do the following steps:
The function within_visit_registration arguments take in:
fixed image - the image to be registered tomoving images - images to register to the fixedtypeofTransform - transformation of moving to fixed image (Rigid/Affine)interpolator - how are voxels averaged in fixed spacecorrect - should correction be done, if so, specify correction = "N4"and outputs a list of transformations (fwdtransforms) and output filenames (outfile)
lapplyWith lists and vectors, there are apply functions. These apply a function to every element of the list. In this course, we will use:
lapply - apply function and return the elements as a list
lapply(LIST, FUNCTION, OTHER_ARGUMENTS_TO_FUNCTION)sapply - apply function and return a “simplified” version
vectorlist res = within_visit_registration(
fixed = files["T1"], moving = files[c("T2", "FLAIR")],
correct = TRUE, correction = "N4",
typeofTransform = "Rigid", interpolator = "Linear")
output_imgs = lapply(res, function(x) x$outfile)
out = c(T1 = list(t1), output_imgs)
# Running Bias-Field Correction on file
# Running Registration of file to template
# Applying Registration output is
$fwdtransforms [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc91f0b4b400GenericAffine.mat" $invtransforms [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc91f0b4b400GenericAffine.mat" $prev_transforms character(0)
# Applying Transformations to file
[1] "-d" [2] "3" [3] "-i" [4] "<pointer: 0x7fdb04b572c0>" [5] "-o" [6] "<pointer: 0x7fdb04a70fa0>" [7] "-r" [8] "<pointer: 0x7fdb04b61880>" [9] "-n" [10] "linear" [11] "-t" [12] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc91f0b4b400GenericAffine.mat"
# Writing out file
[1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc910bbbbfa.nii.gz"
# Removing Warping images
# Reading data back into R
# Running Bias-Field Correction on file
# Running Registration of file to template
# Applying Registration output is
$fwdtransforms [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc961de5f840GenericAffine.mat" $invtransforms [1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc961de5f840GenericAffine.mat" $prev_transforms character(0)
# Applying Transformations to file
[1] "-d" [2] "3" [3] "-i" [4] "<pointer: 0x7fdb04959bc0>" [5] "-o" [6] "<pointer: 0x7fdb04b4b650>" [7] "-r" [8] "<pointer: 0x7fdb0493e220>" [9] "-n" [10] "linear" [11] "-t" [12] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc961de5f840GenericAffine.mat"
# Writing out file
[1] "/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T//RtmpN4MXsP/file12bc9153222ab.nii.gz"
# Removing Warping images
# Reading data back into R
$T2 NULL $FLAIR NULL
double_ortho(out$T1, out$T2 )
The multi_overlay function takes in a list of images and then plots one slice across modalities (assumes center slice):
multi_overlay(out)
correct = TRUE or pass in the bias-corrected imagesApplying a Brain mask to all registered images
Now that the images are in the same space as the T1, if we skull-strip the T1 image (we did with MALF), we can apply this mask to those images to extract brain tissues using the neurobase::mask_img command:
mask = readnii("../output/training01_01_t1_mask.nii.gz") # MALF mask
masked_imgs = lapply(out, mask_img, mask)
ortho2(masked_imgs$FLAIR)
ortho2(masked_imgs$T2)
registration wraps around the reading/writing of images and applying transformations (uses ANTsR functions)double_ortho, ortho2, and multi_overlay can provide some basic visual checks to assess registration qualitywithin_visit_registration is a registration wrapper functionpreprocess_mri_within - wraps multiple steps above (inhomo, reg, extract)We have only done registration within a subject, but many times you want to perform a population-level analysis. This requries registration to a template:
registration can be done for this as well, just the template.file is now the template image and filename is the subject image.
other.files and other.outfiles arguments. Or:ants_apply_transforms can be used to apply this transformations to the other files