33"""Nipype translation of ANTs' workflows."""
44
55# general purpose
6- import os
76from multiprocessing import cpu_count
87from pkg_resources import resource_filename as pkgr_fn
9- from packaging .version import parse as parseversion , Version
10- from warnings import warn
118
129# nipype
1310from nipype .pipeline import engine as pe
1411from nipype .interfaces import utility as niu
1512from nipype .interfaces .ants import N4BiasFieldCorrection , Atropos
16- from nipype .interfaces .ants .utils import AI # , ImageMath, ResampleImageBySpacing,
13+ from nipype .interfaces .ants .utils import AI
1714from nipype .interfaces .afni import MaskTool
1815from nipype .interfaces .io import DataSink
1916
2017# niworkflows
2118from niworkflows .interfaces .ants import ImageMath
22- from niworkflows .utils .images import resample_by_spacing
19+ from niworkflows .interfaces .images import RegridToZooms
2320from niworkflows .interfaces .nibabel import ApplyMask
2421from niworkflows .interfaces .fixes import (
2522 FixHeaderRegistration as Registration ,
2623 FixHeaderApplyTransforms as ApplyTransforms )
2724
2825from templateflow .api import get as get_template
2926
27+ LOWRES_ZOOMS = (0.4 , 0.4 , 0.4 )
28+
29+
3030def init_rodent_brain_extraction_wf (
3131 atropos_model = None ,
3232 atropos_refine = True ,
@@ -71,25 +71,20 @@ def init_rodent_brain_extraction_wf(
7171 tpl_brain_mask = get_template (in_template , resolution = debug + 1 , desc = 'cerebrum' , suffix = 'mask' )
7272
7373 # resample template and target
74- res_tmpl = pe .Node (niu .Function (function = res_by_spc ,
75- input_names = ['in_file' ], output_names = ['out_file' ]), name = 'res_tmpl' )
76- if tpl_target_path :
77- res_tmpl .inputs .in_file = tpl_target_path
74+ res_tmpl = pe .Node (RegridToZooms (
75+ in_file = tpl_target_path , zooms = LOWRES_ZOOMS ), name = "res_tmpl" )
7876
79- res_target = pe .Node (niu .Function (function = res_by_spc ,
80- input_names = ['in_file' ], output_names = ['out_file' ]), name = 'res_target' )
81- res_target2 = pe .Node (niu .Function (function = res_by_spc ,
82- input_names = ['in_file' ], output_names = ['out_file' ]), name = 'res_target2' )
77+ res_target = pe .Node (RegridToZooms (zooms = LOWRES_ZOOMS ), name = "res_target" )
78+ res_target2 = pe .Node (RegridToZooms (zooms = LOWRES_ZOOMS ), name = "res_target2" )
8379
84- dil_mask = pe .Node (MaskTool (), name = 'dil_mask' )
85- dil_mask .inputs .outputtype = 'NIFTI_GZ'
86- dil_mask .inputs .dilate_inputs = '2'
87- dil_mask .inputs .fill_holes = True
80+ dil_mask = pe .Node (MaskTool (
81+ outputtype = 'NIFTI_GZ' , dilate_inputs = '2' , fill_holes = True ),
82+ name = 'dil_mask' )
8883
8984 # truncate target intensity for N4 correction
9085 trunc_opts = {"T1w" : "0.005 0.999 256" , "T2w" : "0.01 0.999 256" }
9186 trunc = pe .MapNode (ImageMath (operation = 'TruncateImageIntensity' , op2 = trunc_opts [bids_suffix ]),
92- name = 'truncate_images' , iterfield = ['op1' ])
87+ name = 'truncate_images' , iterfield = ['op1' ])
9388
9489 # Initial N4 correction
9590 inu_n4 = pe .MapNode (
@@ -104,7 +99,7 @@ def init_rodent_brain_extraction_wf(
10499 if tpl_target_path :
105100 lap_tmpl .inputs .op1 = tpl_target_path
106101 lap_target = pe .Node (ImageMath (operation = 'Laplacian' , op2 = '0.4' ), name = 'lap_target' )
107-
102+
108103 norm_lap_tmpl = pe .Node (ImageMath (operation = 'Normalize' ), name = 'norm_lap_tmpl' )
109104 norm_lap_target = pe .Node (ImageMath (operation = 'Normalize' ), name = 'norm_lap_target' )
110105
@@ -129,9 +124,6 @@ def init_rodent_brain_extraction_wf(
129124 warp_mask = pe .Node (ApplyTransforms (
130125 interpolation = 'Linear' , invert_transform_flags = True ), name = 'warp_mask' )
131126
132- fixed_mask_trait = 'fixed_image_masks'
133- moving_mask_trait = 'moving_image_masks'
134-
135127 # Set up initial spatial normalization
136128 init_settings_file = f'data/brainextraction_{ init_normalization_quality } _{ modality } .json'
137129 init_norm = pe .Node (Registration (from_file = pkgr_fn (
@@ -145,12 +137,12 @@ def init_rodent_brain_extraction_wf(
145137 inu_n4_final = pe .MapNode (
146138 N4BiasFieldCorrection (
147139 dimension = 3 , save_bias = True , copy_header = True ,
148- n_iterations = [50 ] * 5 , convergence_threshold = 1e-7 ,
140+ n_iterations = [50 ] * 5 , convergence_threshold = 1e-7 ,
149141 bspline_fitting_distance = bspline_fitting_distance ,
150- rescale_intensities = True , shrink_factor = 4 ),
142+ rescale_intensities = True , shrink_factor = 4 ),
151143 n_procs = omp_nthreads , name = 'inu_n4_final' , iterfield = ['input_image' ])
152144
153- split_init_transforms = pe .Node (niu .Split (splits = [1 ,1 ]), name = 'split_init_transforms' )
145+ split_init_transforms = pe .Node (niu .Split (splits = [1 , 1 ]), name = 'split_init_transforms' )
154146 mrg_init_transforms = pe .Node (niu .Merge (2 ), name = 'mrg_init_transforms' )
155147
156148 # Use more precise transforms to warp mask to subject space
@@ -159,10 +151,8 @@ def init_rodent_brain_extraction_wf(
159151 name = 'warp_mask_final' )
160152
161153 # morphological closing of warped mask
162- close_mask = pe .Node (MaskTool (), name = 'close_mask' )
163- close_mask .inputs .outputtype = 'NIFTI_GZ'
164- close_mask .inputs .dilate_inputs = '5 -5'
165- close_mask .inputs .fill_holes = True
154+ close_mask = pe .Node (MaskTool (outputtype = 'NIFTI_GZ' , dilate_inputs = '5 -5' , fill_holes = True ),
155+ name = 'close_mask' )
166156
167157 # Use subject-space mask to skull-strip subject
168158 skullstrip_tar = pe .Node (ApplyMask (), name = 'skullstrip_tar' )
@@ -179,7 +169,7 @@ def init_rodent_brain_extraction_wf(
179169 mem_gb = mem_gb )
180170 final_norm .inputs .float = use_float
181171
182- split_final_transforms = pe .Node (niu .Split (splits = [1 ,1 ]), name = 'split_final_transforms' )
172+ split_final_transforms = pe .Node (niu .Split (splits = [1 , 1 ]), name = 'split_final_transforms' )
183173 mrg_final_transforms = pe .Node (niu .Merge (2 ), name = 'mrg_final_transforms' )
184174
185175 warp_seg_mask = pe .Node (ApplyTransforms (
@@ -188,8 +178,8 @@ def init_rodent_brain_extraction_wf(
188178 if tpl_brain_mask :
189179 warp_seg_mask .inputs .input_image = tpl_brain_mask
190180
191- warp_seg_labels = pe .Node (ApplyTransforms (
192- interpolation = 'Linear' , invert_transform_flags = [False , True ]),
181+ warp_seg_labels = pe .Node (ApplyTransforms (
182+ interpolation = 'Linear' , invert_transform_flags = [False , True ]),
193183 name = 'warp_seg_labels' )
194184 if tpl_tissue_labels :
195185 warp_seg_labels .inputs .input_image = tpl_tissue_labels
@@ -287,7 +277,7 @@ def init_rodent_brain_extraction_wf(
287277 (inputnode , res_target , [('in_files' , 'in_file' )]),
288278 (inputnode , lap_target , [('in_files' , 'op1' )]),
289279 (lap_target , norm_lap_target , [('output_image' , 'op1' )]),
290- (norm_lap_target , mrg_target , [('output_image' , 'in2' )]),
280+ (norm_lap_target , mrg_target , [('output_image' , 'in2' )]),
291281 (res_target , mrg_target , [('out_file' , 'in1' )]),
292282
293283 (res_tmpl , mrg_tmpl , [('out_file' , 'in1' )]),
@@ -309,7 +299,7 @@ def init_rodent_brain_extraction_wf(
309299
310300 # normalisation inputs
311301 (mrg_tmpl , init_norm , [('out' , 'fixed_image' )]),
312- (mrg_target , init_norm , [('out' , 'moving_image' )]),
302+ (mrg_target , init_norm , [('out' , 'moving_image' )]),
313303 (dil_mask , init_norm , [('out_file' , 'fixed_image_masks' )]),
314304 (warp_mask , init_norm , [('output_image' , 'moving_image_masks' )]),
315305 (init_aff , init_norm , [('output_transform' , 'initial_moving_transform' )]),
@@ -347,26 +337,10 @@ def init_rodent_brain_extraction_wf(
347337 (skullstrip_tar , segment , [('out_file' , 'intensity_images' )]),
348338 (warp_seg_labels , segment , [('output_image' , 'prior_image' )]),
349339 (warp_seg_mask , segment , [('output_image' , 'mask_image' )]),
350- ])
340+ ])
351341 return wf
352342
353343def _pop (in_files ):
354344 if isinstance (in_files , (list , tuple )):
355345 return in_files [0 ]
356346 return in_files
357-
358- def res_by_spc (in_file , out_file = None ):
359- import os .path as op
360- from niworkflows .utils .images import resample_by_spacing
361- import nibabel as nib
362- resampled = resample_by_spacing (in_file , (0.4 , 0.4 , 0.4 ), clip = False )
363-
364- if out_file is None :
365- fname , ext = op .splitext (op .basename (in_file ))
366- if ext == '.gz' :
367- fname , ext2 = op .splitext (fname )
368- ext = ext2 + ext
369- out_file = op .abspath ('{}_resampled{}' .format (fname , ext ))
370-
371- nib .save (resampled , out_file )
372- return out_file
0 commit comments