Skip to content

Commit 9fc9575

Browse files
committed
ENH: Add new derivatives coregistration workflow, make probmask option for t1-t2 coreg
1 parent ec29954 commit 9fc9575

File tree

1 file changed

+82
-10
lines changed

1 file changed

+82
-10
lines changed

nibabies/workflows/anatomical/registration.py

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
33
"""Within-baby registration of a T1w into a T2w image."""
4-
from typing import Optional
4+
from __future__ import annotations
55

66
from nipype.interfaces import utility as niu
77
from nipype.pipeline import engine as pe
8-
from pkg_resources import resource_filename as pkgr_fn
8+
from niworkflows.interfaces.fixes import FixHeaderApplyTransforms as ApplyTransforms
99

1010

1111
def init_coregistration_wf(
1212
*,
1313
bspline_fitting_distance: int = 200,
1414
mem_gb: float = 3.0,
15-
omp_nthreads: Optional[int] = None,
15+
omp_nthreads: int | None = None,
1616
sloppy: bool = False,
1717
debug: bool = False,
18-
precomputed_mask: bool = False,
18+
t1w_mask: bool = False,
19+
probmap: bool = False,
1920
name: str = "coregistration_wf",
2021
):
2122
"""
@@ -52,11 +53,12 @@ def init_coregistration_wf(
5253
Run in *sloppy* mode.
5354
debug : :obj:`bool`
5455
Produce intermediate registration files
55-
precomputed_mask : :obj:`bool`
56+
t1w_mask : :obj:`bool`
5657
A precomputed mask for the T1w is available. In this case, generate a
5758
quick mask to assist in coregistration, but use the precomputed mask
5859
as the final output.
59-
60+
probmap: :obj:`bool`
61+
A probabilistic brainmask is present in T2w space.
6062
6163
Inputs
6264
------
@@ -66,8 +68,8 @@ def init_coregistration_wf(
6668
The preprocessed input T2w image (Denoising/INU/Clipping)
6769
in_mask : :obj:`str`
6870
The brainmask.
69-
If `precomputed_mask` is False, will be in T2w space.
70-
If `precomputed_mask` is True, will be in T1w space.
71+
If `t1w_mask` is False, will be in T2w space.
72+
If `t1w_mask` is True, will be in T1w space.
7173
in_probmap : :obj:`str`
7274
The probabilistic brainmask, as obtained in T2w space.
7375
@@ -172,7 +174,7 @@ def init_coregistration_wf(
172174
])
173175
# fmt: on
174176

175-
if precomputed_mask:
177+
if t1w_mask:
176178
# The input mask is already in T1w space.
177179
# Generate a quick, rough mask of the T2w to be used to facilitate co-registration.
178180
from sdcflows.interfaces.brainmask import BrainExtraction
@@ -187,7 +189,9 @@ def init_coregistration_wf(
187189
(inputnode, outputnode, [("in_mask", "t1w_mask")]),
188190
])
189191
# fmt:on
190-
else:
192+
return workflow
193+
194+
if probmap:
191195
# The T2w mask from the brain extraction workflow will be mapped to T1w space
192196
map_mask = pe.Node(ApplyTransforms(interpolation="Gaussian"), name="map_mask", mem_gb=1)
193197
thr_mask = pe.Node(Binarize(thresh_low=0.80), name="thr_mask")
@@ -207,4 +211,72 @@ def init_coregistration_wf(
207211
(thr_mask, apply_mask, [("out_mask", "in_mask")]),
208212
])
209213
# fmt:on
214+
return workflow
215+
216+
# A precomputed T2w mask was provided
217+
map_precomp_mask = pe.Node(
218+
ApplyTransforms(interpolation="MultiLabel"), name='map_precomp_mask'
219+
)
220+
# fmt:off
221+
workflow.connect([
222+
(inputnode, map_precomp_mask, [
223+
('in_t1w', 'reference_image'),
224+
('in_mask', 'input_image')]),
225+
(coreg, map_precomp_mask, [
226+
("reverse_transforms", "transforms"),
227+
("reverse_invert_flags", "invert_transform_flags")]),
228+
(map_precomp_mask, final_n4, [('output_image', 'weight_image')]),
229+
(map_precomp_mask, outputnode, [('output_image', 't1w_mask')]),
230+
(map_precomp_mask, apply_mask, [('output_image', 'in_mask')]),
231+
])
232+
# fmt:on
233+
return workflow
234+
235+
236+
def init_coregister_derivatives_wf(
237+
*, t1w_mask: bool, t1w_aseg: bool, t2w_aseg: bool, name: str = 'coregister_derivatives_wf'
238+
):
239+
"""Move derivatives from T1w / T2w space."""
240+
workflow = pe.Workflow(name=name)
241+
inputnode = pe.Node(
242+
niu.IdentityInterface(
243+
fields=['t1w_ref', 't2w_ref', 't1w_mask', 't1w_aseg', 't2w_aseg', 't1w2t2w_xfm']
244+
),
245+
name='inputnode',
246+
)
247+
outputnode = pe.Node(niu.IdentityInterface(fields=['t2w_mask', 't1w_aseg']), name='outputnode')
248+
249+
if t1w_mask:
250+
t1wmask2t2w = pe.Node(ApplyTransforms(interpolation="MultiLabel"), name='t1wmask2t2w')
251+
# fmt:off
252+
workflow.connect([
253+
(inputnode, t1wmask2t2w, [
254+
('t1w_mask', 'input_image'),
255+
('t1w2t2w_xfm', 'transforms'),
256+
('t2w_ref', 'reference_image')]),
257+
(t1wmask2t2w, outputnode, [('output_image', 't2w_mask')])
258+
])
259+
# fmt:on
260+
if t1w_aseg:
261+
# fmt:off
262+
t1waseg2t2w = pe.Node(ApplyTransforms(interpolation="MultiLabel"), name='t2wmask2t1w')
263+
workflow.connect([
264+
(inputnode, t1waseg2t2w, [
265+
('t2w_aseg', 'input_image'),
266+
('t1w2t2w_xfm', 'transforms'),
267+
('t1w_ref', 'reference_image')]),
268+
(t1waseg2t2w, outputnode, [('output_image', 't1w_aseg')])
269+
])
270+
# fmt:on
271+
if t2w_aseg:
272+
# fmt:off
273+
t2waseg2t1w = pe.Node(ApplyTransforms(interpolation="MultiLabel"), name='t2wmask2t1w')
274+
workflow.connect([
275+
(inputnode, t2waseg2t1w, [
276+
('t2w_aseg', 'input_image'),
277+
('t1w2t2w_xfm', 'reverse_transforms'),
278+
('t1w_ref', 'reference_image')]),
279+
(t2waseg2t1w, outputnode, [('output_image', 't1w_aseg')])
280+
])
281+
# fmt:on
210282
return workflow

0 commit comments

Comments
 (0)