@@ -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
367336def _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