Skip to content

Commit 34e00ba

Browse files
dPysarokem
authored andcommitted
[ENH] Add affine registration tools for EMC
1 parent 6b95611 commit 34e00ba

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

dmriprep/utils/register.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"""
2+
Linear affine registration tools for motion correction.
3+
"""
4+
import numpy as np
5+
import nibabel as nb
6+
from dipy.align.metrics import CCMetric, EMMetric, SSDMetric
7+
from dipy.align.imaffine import (
8+
transform_centers_of_mass,
9+
AffineMap,
10+
MutualInformationMetric,
11+
AffineRegistration,
12+
)
13+
from dipy.align.transforms import (
14+
TranslationTransform3D,
15+
RigidTransform3D,
16+
AffineTransform3D,
17+
)
18+
from nipype.utils.filemanip import fname_presuffix
19+
20+
syn_metric_dict = {"CC": CCMetric, "EM": EMMetric, "SSD": SSDMetric}
21+
22+
__all__ = [
23+
"c_of_mass",
24+
"translation",
25+
"rigid",
26+
"affine",
27+
"affine_registration",
28+
]
29+
30+
31+
def apply_affine(moving, static, transform_affine, invert=False):
32+
"""Apply an affine to transform an image from one space to another.
33+
34+
Parameters
35+
----------
36+
moving : array
37+
The image to be resampled
38+
39+
static : array
40+
41+
Returns
42+
-------
43+
warped_img : the moving array warped into the static array's space.
44+
45+
"""
46+
affine_map = AffineMap(
47+
transform_affine, static.shape, static.affine, moving.shape, moving.affine
48+
)
49+
if invert is True:
50+
warped_arr = affine_map.transform_inverse(np.asarray(moving.dataobj))
51+
else:
52+
warped_arr = affine_map.transform(np.asarray(moving.dataobj))
53+
54+
return nb.Nifti1Image(warped_arr, static.affine)
55+
56+
57+
def average_affines(transforms):
58+
affine_list = [np.load(aff) for aff in transforms]
59+
average_affine_file = fname_presuffix(
60+
transforms[0], use_ext=False, suffix="_average.npy"
61+
)
62+
np.save(average_affine_file, np.mean(affine_list, axis=0))
63+
return average_affine_file
64+
65+
66+
# Affine registration pipeline:
67+
affine_metric_dict = {"MI": MutualInformationMetric, "CC": CCMetric}
68+
69+
70+
def c_of_mass(
71+
moving, static, static_affine, moving_affine, reg, starting_affine, params0=None
72+
):
73+
transform = transform_centers_of_mass(static, static_affine, moving, moving_affine)
74+
transformed = transform.transform(moving)
75+
return transformed, transform.affine
76+
77+
78+
def translation(
79+
moving, static, static_affine, moving_affine, reg, starting_affine, params0=None
80+
):
81+
transform = TranslationTransform3D()
82+
translation = reg.optimize(
83+
static,
84+
moving,
85+
transform,
86+
params0,
87+
static_affine,
88+
moving_affine,
89+
starting_affine=starting_affine,
90+
)
91+
92+
return translation.transform(moving), translation.affine
93+
94+
95+
def rigid(
96+
moving, static, static_affine, moving_affine, reg, starting_affine, params0=None
97+
):
98+
transform = RigidTransform3D()
99+
rigid = reg.optimize(
100+
static,
101+
moving,
102+
transform,
103+
params0,
104+
static_affine,
105+
moving_affine,
106+
starting_affine=starting_affine,
107+
)
108+
return rigid.transform(moving), rigid.affine
109+
110+
111+
def affine(
112+
moving, static, static_affine, moving_affine, reg, starting_affine, params0=None
113+
):
114+
transform = AffineTransform3D()
115+
affine = reg.optimize(
116+
static,
117+
moving,
118+
transform,
119+
params0,
120+
static_affine,
121+
moving_affine,
122+
starting_affine=starting_affine,
123+
)
124+
125+
return affine.transform(moving), affine.affine
126+
127+
128+
def affine_registration(
129+
moving,
130+
static,
131+
nbins,
132+
sampling_prop,
133+
metric,
134+
pipeline,
135+
level_iters,
136+
sigmas,
137+
factors,
138+
params0,
139+
):
140+
141+
"""
142+
Find the affine transformation between two 3D images.
143+
144+
Parameters
145+
----------
146+
147+
"""
148+
# Define the Affine registration object we'll use with the chosen metric:
149+
use_metric = affine_metric_dict[metric](nbins, sampling_prop)
150+
affreg = AffineRegistration(
151+
metric=use_metric, level_iters=level_iters, sigmas=sigmas, factors=factors
152+
)
153+
154+
if not params0:
155+
starting_affine = np.eye(4)
156+
else:
157+
starting_affine = params0
158+
159+
# Go through the selected transformation:
160+
for func in pipeline:
161+
transformed, starting_affine = func(
162+
np.asarray(moving.dataobj),
163+
np.asarray(static.dataobj),
164+
static.affine,
165+
moving.affine,
166+
affreg,
167+
starting_affine,
168+
params0,
169+
)
170+
return nb.Nifti1Image(np.array(transformed), static.affine), starting_affine

0 commit comments

Comments
 (0)