@@ -261,14 +261,8 @@ def init_brain_extraction_wf(
261261 )
262262 res_target = pe .Node (RegridToZooms (zooms = (4 , 4 , 4 ), smooth = True ), name = 'res_target' )
263263
264- lap_tmpl = pe .Node (
265- ImageMath (operation = 'Laplacian' , op2 = '1.5 1' , copy_header = True ), name = 'lap_tmpl'
266- )
267- lap_tmpl .inputs .op1 = tpl_target_path
268- lap_target = pe .Node (
269- ImageMath (operation = 'Laplacian' , op2 = '1.5 1' , copy_header = True ),
270- name = 'lap_target' ,
271- )
264+ # Template and target inputs contain anatomical images
265+ # If Laplacians are enabled, they will be concatenated
272266 mrg_tmpl = pe .Node (niu .Merge (2 ), name = 'mrg_tmpl' )
273267 mrg_tmpl .inputs .in1 = tpl_target_path
274268 mrg_target = pe .Node (niu .Merge (2 ), name = 'mrg_target' )
@@ -334,42 +328,15 @@ def init_brain_extraction_wf(
334328 name = 'thr_brainmask' ,
335329 )
336330
337- # Refine INU correction
338- inu_n4_final = pe .MapNode (
339- N4BiasFieldCorrection (
340- dimension = 3 ,
341- save_bias = True ,
342- copy_header = True ,
343- n_iterations = [50 ] * 5 ,
344- convergence_threshold = 1e-7 ,
345- shrink_factor = 4 ,
346- bspline_fitting_distance = bspline_fitting_distance ,
347- ),
348- n_procs = omp_nthreads ,
349- name = 'inu_n4_final' ,
350- iterfield = ['input_image' ],
351- )
352- try :
353- inu_n4_final .inputs .rescale_intensities = True
354- except ValueError :
355- warn (
356- "N4BiasFieldCorrection's --rescale-intensities option was added in ANTS 2.1.0 "
357- f'({ inu_n4_final .interface .version } found.) Please consider upgrading.' ,
358- UserWarning ,
359- stacklevel = 1 ,
360- )
361-
362- # Apply mask
363- apply_mask = pe .MapNode (ApplyMask (), iterfield = ['in_file' ], name = 'apply_mask' )
364-
365- # fmt: off
366331 wf .connect ([
367332 (inputnode , trunc , [('in_files' , 'op1' )]),
368- (inputnode , inu_n4_final , [('in_files' , 'input_image' )]),
369333 (inputnode , init_aff , [('in_mask' , 'fixed_image_mask' )]),
370334 (inputnode , norm , [('in_mask' , fixed_mask_trait )]),
371335 (inputnode , map_brainmask , [(('in_files' , _pop ), 'reference_image' )]),
372336 (trunc , inu_n4 , [('output_image' , 'input_image' )]),
337+ (inu_n4 , mrg_target , [('output_image' , 'in1' )]),
338+ (mrg_tmpl , norm , [('out' , 'fixed_image' )]),
339+ (mrg_target , norm , [('out' , 'moving_image' )]),
373340 (inu_n4 , res_target , [(('output_image' , _pop ), 'in_file' )]),
374341 (res_tmpl , init_aff , [('out_file' , 'fixed_image' )]),
375342 (res_target , init_aff , [('out_file' , 'moving_image' )]),
@@ -379,15 +346,7 @@ def init_brain_extraction_wf(
379346 ('reverse_invert_flags' , 'invert_transform_flags' ),
380347 ]),
381348 (map_brainmask , thr_brainmask , [('output_image' , 'input_image' )]),
382- (map_brainmask , inu_n4_final , [('output_image' , 'weight_image' )]),
383- (inu_n4_final , apply_mask , [('output_image' , 'in_file' )]),
384- (thr_brainmask , apply_mask , [('output_image' , 'in_mask' )]),
385- (thr_brainmask , outputnode , [('output_image' , 'out_mask' )]),
386- (inu_n4_final , outputnode , [('output_image' , 'bias_corrected' ),
387- ('bias_image' , 'bias_image' )]),
388- (apply_mask , outputnode , [('out_file' , 'out_file' )]),
389- ])
390- # fmt: on
349+ ]) # fmt:skip
391350
392351 wm_tpm = get_template (in_template , label = 'WM' , suffix = 'probseg' , ** common_spec ) or None
393352 if wm_tpm :
@@ -403,58 +362,33 @@ def init_brain_extraction_wf(
403362 full_wm = pe .Node (niu .Function (function = _imsum ), name = 'full_wm' )
404363 full_wm .inputs .op1 = str (wm_tpm )
405364 full_wm .inputs .op2 = str (bstem_tpm )
406- # fmt: off
407- wf .connect ([
408- (full_wm , map_wmmask , [('out' , 'input_image' )])
409- ])
410- # fmt: on
365+ wf .connect ([(full_wm , map_wmmask , [('out' , 'input_image' )])])
411366 else :
412367 map_wmmask .inputs .input_image = str (wm_tpm )
413- # fmt: off
414- wf .disconnect ([
415- (map_brainmask , inu_n4_final , [('output_image' , 'weight_image' )]),
416- ])
368+
417369 wf .connect ([
418370 (inputnode , map_wmmask , [(('in_files' , _pop ), 'reference_image' )]),
419371 (norm , map_wmmask , [
420372 ('reverse_transforms' , 'transforms' ),
421373 ('reverse_invert_flags' , 'invert_transform_flags' ),
422374 ]),
423- (map_wmmask , inu_n4_final , [('output_image' , 'weight_image' )]),
424- ])
425- # fmt: on
375+ ]) # fmt:skip
426376
427377 if use_laplacian :
428378 lap_tmpl = pe .Node (
429- ImageMath (operation = 'Laplacian' , op2 = '1.5 1' , copy_header = True ),
379+ ImageMath (operation = 'Laplacian' , op1 = tpl_target_path , op2 = '1.5 1' , copy_header = True ),
430380 name = 'lap_tmpl' ,
431381 )
432- lap_tmpl .inputs .op1 = tpl_target_path
433382 lap_target = pe .Node (
434383 ImageMath (operation = 'Laplacian' , op2 = '1.5 1' , copy_header = True ),
435384 name = 'lap_target' ,
436385 )
437- mrg_tmpl = pe .Node (niu .Merge (2 ), name = 'mrg_tmpl' )
438- mrg_tmpl .inputs .in1 = tpl_target_path
439- mrg_target = pe .Node (niu .Merge (2 ), name = 'mrg_target' )
440- # fmt: off
386+
441387 wf .connect ([
442388 (inu_n4 , lap_target , [(('output_image' , _pop ), 'op1' )]),
443389 (lap_tmpl , mrg_tmpl , [('output_image' , 'in2' )]),
444- (inu_n4 , mrg_target , [('output_image' , 'in1' )]),
445390 (lap_target , mrg_target , [('output_image' , 'in2' )]),
446- (mrg_tmpl , norm , [('out' , 'fixed_image' )]),
447- (mrg_target , norm , [('out' , 'moving_image' )]),
448- ])
449- # fmt: on
450-
451- else :
452- norm .inputs .fixed_image = tpl_target_path
453- # fmt: off
454- wf .connect ([
455- (inu_n4 , norm , [(('output_image' , _pop ), 'moving_image' )]),
456- ])
457- # fmt: on
391+ ]) # fmt:skip
458392
459393 if atropos_refine :
460394 atropos_model = atropos_model or list (ATROPOS_MODELS [bids_suffix ].values ())
@@ -467,16 +401,9 @@ def init_brain_extraction_wf(
467401 wm_prior = bool (wm_tpm ),
468402 )
469403
470- # fmt: off
471- wf .disconnect ([
472- (thr_brainmask , outputnode , [('output_image' , 'out_mask' )]),
473- (inu_n4_final , outputnode , [('output_image' , 'bias_corrected' ),
474- ('bias_image' , 'bias_image' )]),
475- (apply_mask , outputnode , [('out_file' , 'out_file' )]),
476- ])
477404 wf .connect ([
478405 (inputnode , atropos_wf , [('in_files' , 'inputnode.in_files' )]),
479- (inu_n4_final , atropos_wf , [('output_image' , 'inputnode.in_corrected' )]),
406+ (inu_n4 , atropos_wf , [('output_image' , 'inputnode.in_corrected' )]),
480407 (thr_brainmask , atropos_wf , [('output_image' , 'inputnode.in_mask' )]),
481408 (atropos_wf , outputnode , [
482409 ('outputnode.out_file' , 'out_file' ),
@@ -486,14 +413,53 @@ def init_brain_extraction_wf(
486413 ('outputnode.out_segm' , 'out_segm' ),
487414 ('outputnode.out_tpms' , 'out_tpms' ),
488415 ]),
489- ])
490- # fmt: on
416+ ]) # fmt:skip
491417 if wm_tpm :
492- # fmt: off
493- wf .connect ([
494- (map_wmmask , atropos_wf , [('output_image' , 'inputnode.wm_prior' )]),
495- ])
496- # fmt: on
418+ wf .connect ([(map_wmmask , atropos_wf , [('output_image' , 'inputnode.wm_prior' )])])
419+ else :
420+ # If no Atropos refinement, rerun N4 with the brain or white matter mask
421+ inu_n4_final = pe .MapNode (
422+ N4BiasFieldCorrection (
423+ dimension = 3 ,
424+ save_bias = True ,
425+ copy_header = True ,
426+ n_iterations = [50 ] * 5 ,
427+ convergence_threshold = 1e-7 ,
428+ shrink_factor = 4 ,
429+ bspline_fitting_distance = bspline_fitting_distance ,
430+ ),
431+ n_procs = omp_nthreads ,
432+ name = 'inu_n4_final' ,
433+ iterfield = ['input_image' ],
434+ )
435+
436+ # Check ANTs version
437+ try :
438+ inu_n4_final .inputs .rescale_intensities = True
439+ except ValueError :
440+ warn (
441+ "N4BiasFieldCorrection's --rescale-intensities option was added in ANTS 2.1.0 "
442+ f'({ inu_n4_final .interface .version } found.) Please consider upgrading.' ,
443+ UserWarning ,
444+ stacklevel = 1 ,
445+ )
446+
447+ # Apply mask
448+ apply_mask = pe .MapNode (ApplyMask (), iterfield = ['in_file' ], name = 'apply_mask' )
449+
450+ wf .connect ([
451+ (inputnode , inu_n4_final , [('in_files' , 'input_image' )]),
452+ (map_wmmask if wm_tpm else map_brainmask , inu_n4_final , [
453+ ('output_image' , 'weight_image' ),
454+ ]),
455+ (inu_n4_final , apply_mask , [('output_image' , 'in_file' )]),
456+ (thr_brainmask , apply_mask , [('output_image' , 'in_mask' )]),
457+ (thr_brainmask , outputnode , [('output_image' , 'out_mask' )]),
458+ (inu_n4_final , outputnode , [('output_image' , 'bias_corrected' ),
459+ ('bias_image' , 'bias_image' )]),
460+ (apply_mask , outputnode , [('out_file' , 'out_file' )]),
461+ ]) # fmt:skip
462+
497463 return wf
498464
499465
@@ -762,7 +728,6 @@ def init_atropos_wf(
762728 # Apply mask
763729 apply_mask = pe .MapNode (ApplyMask (), iterfield = ['in_file' ], name = 'apply_mask' )
764730
765- # fmt: off
766731 wf .connect ([
767732 (inputnode , dil_brainmask , [('in_mask' , 'op1' )]),
768733 (inputnode , copy_xform , [(('in_files' , _pop ), 'hdr_file' )]),
@@ -811,7 +776,6 @@ def init_atropos_wf(
811776 (merge_tpms , copy_xform , [('out' , 'out_tpms' )]),
812777 (atropos , sel_wm , [('posteriors' , 'inlist' )]),
813778 (sel_wm , copy_xform_wm , [('out' , 'wm_map' )]),
814- (copy_xform_wm , inu_n4_final , [('wm_map' , 'weight_image' )]),
815779 (inu_n4_final , copy_xform , [('output_image' , 'bias_corrected' ),
816780 ('bias_image' , 'bias_image' )]),
817781 (copy_xform , apply_mask , [('bias_corrected' , 'in_file' ),
@@ -824,8 +788,7 @@ def init_atropos_wf(
824788 ('out_segm' , 'out_segm' ),
825789 ('out_tpms' , 'out_tpms' ),
826790 ]),
827- ])
828- # fmt: on
791+ ]) # fmt:skip
829792
830793 if wm_prior :
831794 from nipype .algorithms .metrics import FuzzyOverlap
@@ -844,10 +807,6 @@ def _argmax(in_dice):
844807
845808 apply_wm_prior = pe .Node (niu .Function (function = _improd ), name = 'apply_wm_prior' )
846809
847- # fmt: off
848- wf .disconnect ([
849- (copy_xform_wm , inu_n4_final , [('wm_map' , 'weight_image' )]),
850- ])
851810 wf .connect ([
852811 (inputnode , apply_wm_prior , [('in_mask' , 'in_mask' ),
853812 ('wm_prior' , 'op2' )]),
@@ -858,8 +817,9 @@ def _argmax(in_dice):
858817 (overlap , sel_wm , [(('class_fdi' , _argmax ), 'index' )]),
859818 (copy_xform_wm , apply_wm_prior , [('wm_map' , 'op1' )]),
860819 (apply_wm_prior , inu_n4_final , [('out' , 'weight_image' )]),
861- ])
862- # fmt: on
820+ ]) # fmt:skip
821+ else :
822+ wf .connect ([(copy_xform_wm , inu_n4_final , [('wm_map' , 'weight_image' )])])
863823 return wf
864824
865825
@@ -963,7 +923,7 @@ def init_n4_only_wf(
963923 thr_brainmask = pe .Node (Binarize (thresh_low = 2 ), name = 'binarize' )
964924
965925 # INU correction
966- inu_n4_final = pe .MapNode (
926+ inu_n4 = pe .MapNode (
967927 N4BiasFieldCorrection (
968928 dimension = 3 ,
969929 save_bias = True ,
@@ -974,33 +934,28 @@ def init_n4_only_wf(
974934 bspline_fitting_distance = 200 ,
975935 ),
976936 n_procs = omp_nthreads ,
977- name = 'inu_n4_final ' ,
937+ name = 'inu_n4 ' ,
978938 iterfield = ['input_image' ],
979939 )
980940
981941 # Check ANTs version
982942 try :
983- inu_n4_final .inputs .rescale_intensities = True
943+ inu_n4 .inputs .rescale_intensities = True
984944 except ValueError :
985945 warn (
986946 "N4BiasFieldCorrection's --rescale-intensities option was added in ANTS 2.1.0 "
987- f'({ inu_n4_final .interface .version } found.) Please consider upgrading.' ,
947+ f'({ inu_n4 .interface .version } found.) Please consider upgrading.' ,
988948 UserWarning ,
989949 stacklevel = 1 ,
990950 )
991951
992- # fmt: off
993952 wf .connect ([
994- (inputnode , inu_n4_final , [('in_files' , 'input_image' )]),
953+ (inputnode , inu_n4 , [('in_files' , 'input_image' )]),
995954 (inputnode , thr_brainmask , [(('in_files' , _pop ), 'in_file' )]),
996955 (thr_brainmask , outputnode , [('out_mask' , 'out_mask' )]),
997- (inu_n4_final , outputnode , [('output_image' , 'out_file' ),
998- ('output_image' , 'bias_corrected' ),
999- ('bias_image' , 'bias_image' )]),
1000- ])
1001- # fmt: on
956+ ]) # fmt:skip
1002957
1003- # If atropos refine, do in4 twice
958+ # If atropos refine, n4 is run a second time
1004959 if atropos_refine :
1005960 atropos_model = atropos_model or list (ATROPOS_MODELS [bids_suffix ].values ())
1006961 atropos_wf = init_atropos_wf (
@@ -1010,15 +965,9 @@ def init_n4_only_wf(
1010965 in_segmentation_model = atropos_model ,
1011966 )
1012967
1013- # fmt: off
1014- wf .disconnect ([
1015- (inu_n4_final , outputnode , [('output_image' , 'out_file' ),
1016- ('output_image' , 'bias_corrected' ),
1017- ('bias_image' , 'bias_image' )]),
1018- ])
1019968 wf .connect ([
1020969 (inputnode , atropos_wf , [('in_files' , 'inputnode.in_files' )]),
1021- (inu_n4_final , atropos_wf , [('output_image' , 'inputnode.in_corrected' )]),
970+ (inu_n4 , atropos_wf , [('output_image' , 'inputnode.in_corrected' )]),
1022971 (thr_brainmask , atropos_wf , [('out_mask' , 'inputnode.in_mask' )]),
1023972 (atropos_wf , outputnode , [
1024973 ('outputnode.out_file' , 'out_file' ),
@@ -1027,8 +976,13 @@ def init_n4_only_wf(
1027976 ('outputnode.out_segm' , 'out_segm' ),
1028977 ('outputnode.out_tpms' , 'out_tpms' ),
1029978 ]),
1030- ])
1031- # fmt: on
979+ ]) # fmt:skip
980+ else :
981+ wf .connect ([
982+ (inu_n4 , outputnode , [('output_image' , 'out_file' ),
983+ ('output_image' , 'bias_corrected' ),
984+ ('bias_image' , 'bias_image' )]),
985+ ]) # fmt:skip
1032986
1033987 return wf
1034988
0 commit comments