Skip to content

Commit e3f2696

Browse files
MAIN: workflow tidying
1 parent a17b557 commit e3f2696

File tree

1 file changed

+104
-130
lines changed

1 file changed

+104
-130
lines changed

nirodents/workflows/brainextraction.py

Lines changed: 104 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def init_rodent_brain_extraction_wf(
5454
Run an extra step to refine the brain mask using a brain-tissue segmentation with Atropos.
5555
5656
"""
57-
wf = pe.Workflow(name)
57+
5858

5959
if omp_nthreads is None or omp_nthreads < 1:
6060
omp_nthreads = cpu_count()
@@ -113,6 +113,12 @@ def init_rodent_brain_extraction_wf(
113113
mrg_tmpl = pe.Node(niu.Merge(2), name='mrg_tmpl')
114114
# mrg_tmpl.inputs.in1 = tpl_target_path
115115

116+
#create integration nodes to allow compatability between pipelines
117+
integrate_1 = pe.Node(niu.Function(function=_integrate,
118+
input_names=['in_file'], output_names=['out_file']), name='integrate_1')
119+
integrate_2 = pe.Node(niu.Function(function=_integrate,
120+
input_names=['in_file'], output_names=['out_file']), name='integrate_2')
121+
116122
# Initialize transforms with antsAI
117123
init_aff = pe.Node(AI(
118124
metric=('Mattes', 32, 'Regular', 0.5), #0.25
@@ -131,8 +137,8 @@ def init_rodent_brain_extraction_wf(
131137
# init_aff.inputs.search_grid = (1, (1, 2, 2))
132138

133139
# Initial warping of template mask to subject space
134-
warp_mask = pe.Node(ApplyTransforms(
135-
interpolation='Linear', invert_transform_flags=True), name='warp_mask')
140+
warp_mask_1 = pe.Node(ApplyTransforms(
141+
interpolation='Linear', invert_transform_flags=True), name='warp_mask_1')
136142

137143
fixed_mask_trait = 'fixed_image_mask'
138144
moving_mask_trait = 'moving_image_mask'
@@ -168,9 +174,9 @@ def init_rodent_brain_extraction_wf(
168174
mrg_init_transforms = pe.Node(niu.Merge(2), name='mrg_init_transforms')
169175

170176
# Use more precise transforms to warp mask to subject space
171-
warp_mask_final = pe.Node(ApplyTransforms(
177+
warp_mask_2 = pe.Node(ApplyTransforms(
172178
interpolation='Linear', invert_transform_flags=[False, True]),
173-
name='warp_mask_final')
179+
name='warp_mask_2')
174180

175181
# morphological closing of warped mask
176182
close_mask = pe.Node(MaskTool(), name = 'close_mask')
@@ -186,21 +192,23 @@ def init_rodent_brain_extraction_wf(
186192

187193
# Normalise skull-stripped image to brain template
188194
final_settings_file = f'data/brainextraction_{final_normalization_quality}_{modality}.json'
189-
final_norm = pe.Node(Registration(from_file=pkgr_fn(
195+
refine_norm = pe.Node(Registration(from_file=pkgr_fn(
190196
'nirodents', final_settings_file)),
191-
name='final_norm',
197+
name='refine_norm',
192198
n_procs=omp_nthreads,
193199
mem_gb=mem_gb)
194-
final_norm.inputs.float = use_float
200+
refine_norm.inputs.float = use_float
195201

196202
split_final_transforms = pe.Node(niu.Split(splits=[1,1]), name='split_final_transforms')
197203
mrg_final_transforms = pe.Node(niu.Merge(2), name='mrg_final_transforms')
198204

199-
warp_seg_mask = pe.Node(ApplyTransforms(
205+
warp_mask_out = pe.Node(ApplyTransforms(
200206
interpolation='Linear', invert_transform_flags=[False, True]),
201-
name='warp_seg_mask')
207+
name='warp_mask_out')
202208
if tpl_brain_mask:
203-
warp_seg_mask.inputs.input_image = tpl_brain_mask
209+
warp_mask_out.inputs.input_image = tpl_brain_mask
210+
else:
211+
warp_mask_out.inputs.input_image = tpl_regmask_path
204212

205213
warp_seg_labels =pe.Node(ApplyTransforms(
206214
interpolation='Linear', invert_transform_flags=[False, True]),
@@ -216,153 +224,114 @@ def init_rodent_brain_extraction_wf(
216224

217225
sinker = pe.Node(DataSink(), name='sinker')
218226

227+
#workflow definitions
228+
#target image specific workflows
229+
tar_prep = pe.Workflow('tar_prep')
219230
if modality.lower() == 't2w':
220-
wf.connect([
221-
# resampling, truncation, initial N4, and creation of laplacian
231+
tar_prep.connect([
232+
# truncation, resampling, and initial N4
222233
(inputnode, trunc, [('in_files', 'op1')]),
223234
(trunc, res_target, [(('output_image', _pop), 'in_file')]),
224235
(res_target, inu_n4, [('out_file', 'input_image')]),
225-
226-
# dilation of input mask
227-
(inputnode, dil_mask, [('in_mask', 'in_file')]),
228-
229-
# ants AI inputs
230-
(inu_n4, init_aff, [(('output_image', _pop), 'moving_image')]),
231-
(dil_mask, init_aff, [('out_file', 'fixed_image_mask')]),
232-
(res_tmpl, init_aff, [('out_file', 'fixed_image')]),
233-
234-
# warp mask to individual space
235-
(dil_mask, warp_mask, [('out_file', 'input_image')]),
236-
(trunc, warp_mask, [(('output_image', _pop), 'reference_image')]),
237-
(init_aff, warp_mask, [('output_transform', 'transforms')]),
236+
(inu_n4, integrate_1, [(('output_image', _pop), 'in_file')]),
238237

239238
# masked N4 correction
240239
(trunc, inu_n4_final, [(('output_image', _pop), 'input_image')]),
241-
(warp_mask, inu_n4_final, [('output_image', 'weight_image')]),
240+
(inu_n4_final, integrate_2, [(('output_image', _pop), 'in_file')]),
242241

243242
# merge laplacian and original images
244243
(inu_n4_final, lap_target, [(('output_image', _pop), 'op1')]),
245244
(lap_target, norm_lap_target, [('output_image', 'op1')]),
246245
(norm_lap_target, mrg_target, [('output_image', 'in2')]),
247246
(inu_n4_final, res_target2, [(('output_image', _pop), 'in_file')]),
248247
(res_target2, mrg_target, [('out_file', 'in1')]),
249-
250-
(res_tmpl, mrg_tmpl, [('out_file', 'in1')]),
251-
(lap_tmpl, norm_lap_tmpl, [('output_image', 'op1')]),
252-
(norm_lap_tmpl, mrg_tmpl, [('output_image', 'in2')]),
253-
254-
# normalisation inputs
255-
(init_aff, init_norm, [('output_transform', 'initial_moving_transform')]),
256-
(warp_mask, init_norm, [('output_image', 'moving_image_masks')]),
257-
(dil_mask, init_norm, [('out_file', 'fixed_image_masks')]),
258-
(mrg_tmpl, init_norm, [('out', 'fixed_image')]),
259-
(mrg_target, init_norm, [('out', 'moving_image')]),
260-
261-
# organise normalisation outputs to warp mask
262-
(init_norm, split_init_transforms, [('reverse_transforms', 'inlist')]),
263-
(split_init_transforms, mrg_init_transforms, [('out2', 'in1')]),
264-
(split_init_transforms, mrg_init_transforms, [('out1', 'in2')]),
265-
266-
(mrg_init_transforms, warp_mask_final, [('out', 'transforms')]),
267-
(inu_n4_final, warp_mask_final, [(('output_image', _pop), 'reference_image')]),
268-
(dil_mask, warp_mask_final, [('out_file', 'input_image')]),
269-
(warp_mask_final, close_mask, [('output_image', 'in_file')]),
270-
(close_mask, sinker, [('out_file', 'derivatives.@out_mask')]),
271-
272-
# mask brains
273-
(inu_n4_final, skullstrip_tar, [(('output_image', _pop), 'in_file')]),
274-
(close_mask, skullstrip_tar, [('out_file', 'in_mask')]),
275-
(inputnode, skullstrip_tpl, [('in_mask', 'in_mask')]),
276-
277-
# final_normalisation
278-
(skullstrip_tpl, final_norm, [('out_file', 'fixed_image')]),
279-
(skullstrip_tar, final_norm, [('out_file', 'moving_image')]),
280-
281-
# Warp mask and labels to subject-space
282-
(final_norm, split_final_transforms, [('reverse_transforms', 'inlist')]),
283-
(split_final_transforms, mrg_final_transforms, [('out2', 'in1')]),
284-
(split_final_transforms, mrg_final_transforms, [('out1', 'in2')]),
285-
286-
(mrg_final_transforms, warp_seg_mask, [('out', 'transforms')]),
287-
(skullstrip_tar, warp_seg_mask, [('out_file', 'reference_image')]),
288-
(mrg_final_transforms, warp_seg_labels, [('out', 'transforms')]),
289-
(skullstrip_tar, warp_seg_labels, [('out_file', 'reference_image')]),
290-
291-
# Segmentation
292-
(skullstrip_tar, segment, [('out_file', 'intensity_images')]),
293-
(warp_seg_labels, segment, [('output_image', 'prior_image')]),
294-
(warp_seg_mask, segment, [('output_image', 'mask_image')])
295248
])
296-
return wf
297-
298249
elif modality == 'mp2rage':
299-
wf.connect([
300-
# resampling and creation of laplacians
250+
tar_prep.connect([
251+
# resampling and laplacian; no truncation or N4
301252
(inputnode, res_target, [('in_files', 'in_file')]),
302253
(inputnode, lap_target, [('in_files', 'op1')]),
303254
(lap_target, norm_lap_target, [('output_image', 'op1')]),
304255
(norm_lap_target, mrg_target, [('output_image', 'in2')]),
305256
(res_target, mrg_target, [('out_file', 'in1')]),
257+
(res_target, integrate_1, [('out_file', 'in_file')]),
258+
(inputnode, integrate_2, [('in_files', 'in_file')])
259+
])
306260

307-
(res_tmpl, mrg_tmpl, [('out_file', 'in1')]),
308-
(lap_tmpl, norm_lap_tmpl, [('output_image', 'op1')]),
309-
(norm_lap_tmpl, mrg_tmpl, [('output_image', 'in2')]),
310-
311-
#dilation of input mask
312-
(inputnode, dil_mask, [('in_mask', 'in_file')]),
313-
314-
# ants AI inputs
315-
(res_tmpl, init_aff, [('out_file', 'fixed_image')]),
316-
(res_target, init_aff, [('out_file', 'moving_image')]),
317-
(dil_mask, init_aff, [('out_file', 'fixed_image_mask')]),
318-
319-
# warp mask to individual space
320-
(dil_mask, warp_mask, [('out_file', 'input_image')]),
321-
(inputnode, warp_mask, [('in_files', 'reference_image')]),
322-
(init_aff, warp_mask, [('output_transform', 'transforms')]),
323-
324-
# normalisation inputs
325-
(mrg_tmpl, init_norm, [('out', 'fixed_image')]),
326-
(mrg_target, init_norm, [('out', 'moving_image')]),
327-
(dil_mask, init_norm, [('out_file', 'fixed_image_masks')]),
328-
(warp_mask, init_norm, [('output_image', 'moving_image_masks')]),
329-
(init_aff, init_norm, [('output_transform', 'initial_moving_transform')]),
330-
331-
#organise normalisation outputs to warp mask
332-
(init_norm, split_init_transforms, [('reverse_transforms', 'inlist')]),
333-
(split_init_transforms, mrg_init_transforms, [('out2', 'in1')]),
334-
(split_init_transforms, mrg_init_transforms, [('out1', 'in2')]),
335-
336-
(mrg_init_transforms, warp_mask_final, [('out', 'transforms')]),
337-
(inputnode, warp_mask_final, [('in_files', 'reference_image')]),
338-
(dil_mask, warp_mask_final, [('out_file', 'input_image')]),
339-
(warp_mask_final, close_mask, [('output_image', 'in_file')]),
340-
341-
# mask brains
342-
(inu_n4_final, skullstrip_tar, [(('output_image', _pop), 'in_file')]),
343-
(close_mask, skullstrip_tar, [('out_file', 'in_mask')]),
344-
(inputnode, skullstrip_tpl, [('in_mask', 'in_mask')]),
345-
346-
# final_normalisation
347-
(skullstrip_tpl, final_norm, [('out_file', 'fixed_image')]),
348-
(skullstrip_tar, final_norm, [('out_file', 'moving_image')]),
349-
350-
# Warp mask and labels to subject-space
351-
(final_norm, split_final_transforms, [('reverse_transforms', 'inlist')]),
352-
(split_final_transforms, mrg_final_transforms, [('out2', 'in1')]),
353-
(split_final_transforms, mrg_final_transforms, [('out1', 'in2')]),
354-
355-
(mrg_final_transforms, warp_seg_mask, [('out', 'transforms')]),
356-
(skullstrip_tar, warp_seg_mask, [('out_file', 'reference_image')]),
261+
#main workflow
262+
wf = pe.Workflow(name)
263+
wf.connect([
264+
# template prep: dilation of input mask, resampling template, laplacian creation
265+
(inputnode, dil_mask, [('in_mask', 'in_file')]),
266+
(res_tmpl, mrg_tmpl, [('out_file', 'in1')]),
267+
(lap_tmpl, norm_lap_tmpl, [('output_image', 'op1')]),
268+
(norm_lap_tmpl, mrg_tmpl, [('output_image', 'in2')]),
269+
270+
# ants AI inputs
271+
(tar_prep, init_aff, [('integrate_1.out_file', 'moving_image')]),
272+
(dil_mask, init_aff, [('out_file', 'fixed_image_mask')]),
273+
(res_tmpl, init_aff, [('out_file', 'fixed_image')]),
274+
275+
# warp mask to individual space
276+
(dil_mask, warp_mask_1, [('out_file', 'input_image')]),
277+
(init_aff, warp_mask_1, [('output_transform', 'transforms')]),
278+
(inputnode, warp_mask_1, [('in_files', 'reference_image')]),
279+
280+
# normalisation inputs
281+
(init_aff, init_norm, [('output_transform', 'initial_moving_transform')]),
282+
(warp_mask_1, init_norm, [('output_image', 'moving_image_masks')]),
283+
(dil_mask, init_norm, [('out_file', 'fixed_image_masks')]),
284+
(mrg_tmpl, init_norm, [('out', 'fixed_image')]),
285+
(tar_prep, init_norm, [('mrg_target.out', 'moving_image')]),
286+
287+
#organise initial normalisation transforms for warps
288+
(init_norm, split_init_transforms, [('reverse_transforms', 'inlist')]),
289+
(split_init_transforms, mrg_init_transforms, [('out2', 'in1')]),
290+
(split_init_transforms, mrg_init_transforms, [('out1', 'in2')]),
291+
292+
# warp mask with initial normalisation transforms
293+
(tar_prep, warp_mask_2, [('integrate_2.out_file', 'reference_image')]),
294+
(dil_mask, warp_mask_2, [('out_file', 'input_image')]),
295+
(mrg_init_transforms, warp_mask_2, [('out', 'transforms')]),
296+
(warp_mask_2, close_mask, [('output_image', 'in_file')]),
297+
298+
# mask brains for refined normalisation
299+
(tar_prep, skullstrip_tar, [('integrate_2.out_file', 'in_file')]),
300+
(close_mask, skullstrip_tar, [('out_file', 'in_mask')]),
301+
(inputnode, skullstrip_tpl, [('in_mask', 'in_mask')]),
302+
303+
# refined normalisation
304+
(skullstrip_tpl, refine_norm, [('out_file', 'fixed_image')]),
305+
(skullstrip_tar, refine_norm, [('out_file', 'moving_image')]),
306+
307+
#organise refined normalisation transforms for warps
308+
(refine_norm, split_final_transforms, [('reverse_transforms', 'inlist')]),
309+
(split_final_transforms, mrg_final_transforms, [('out2', 'in1')]),
310+
(split_final_transforms, mrg_final_transforms, [('out1', 'in2')]),
311+
312+
#warp mask to subject space and write out
313+
(mrg_final_transforms, warp_mask_out, [('out', 'transforms')]),
314+
(skullstrip_tar, warp_mask_out, [('out_file', 'reference_image')]),
315+
(warp_mask_out, sinker, [('output_image', 'derivatives.@out_mask')]),
316+
])
317+
# add second target prep stage if necessary
318+
if modality.lower == 't2w':
319+
wf.connect([(warp_mask_1, tar_prep, [('output_image', 'inu_n4_final.weight_image')])])
320+
321+
# add segmentation if necessary
322+
if atropos_model:
323+
wf.connect([
324+
# Warp labels to subject-space
357325
(mrg_final_transforms, warp_seg_labels, [('out', 'transforms')]),
358326
(skullstrip_tar, warp_seg_labels, [('out_file', 'reference_image')]),
359327

360328
# Segmentation
361329
(skullstrip_tar, segment, [('out_file', 'intensity_images')]),
362330
(warp_seg_labels, segment, [('output_image', 'prior_image')]),
363-
(warp_seg_mask, segment, [('output_image', 'mask_image')]),
364-
])
365-
return wf
331+
(warp_mask_out, segment, [('output_image', 'mask_image')])
332+
])
333+
334+
return wf
366335

367336
def _pop(in_files):
368337
if isinstance(in_files, (list, tuple)):
@@ -384,3 +353,8 @@ def res_by_spc(in_file, out_file = None):
384353

385354
nib.save(resampled, out_file)
386355
return out_file
356+
357+
def _integrate(in_file, out_file = None):
358+
import os.path as op
359+
out_file = op.abspath(in_file)
360+
return out_file

0 commit comments

Comments
 (0)