1313from nipype .pipeline import engine as pe
1414from nipype .interfaces import utility as niu
1515from nipype .interfaces .ants import N4BiasFieldCorrection , Atropos
16- from nipype .interfaces .ants .utils import ResampleImageBySpacing , AI # , ImageMath,
16+ from nipype .interfaces .ants .utils import AI # , ImageMath, ResampleImageBySpacing ,
1717from nipype .interfaces .afni import MaskTool
18- # from nipype.interfaces.fsl import ApplyMask
1918from nipype .interfaces .io import DataSink
2019
2120# niworkflows
2221from niworkflows .interfaces .ants import ImageMath
22+ from niworkflows .utils .images import resample_by_spacing
2323from niworkflows .interfaces .nibabel import ApplyMask
2424from niworkflows .interfaces .fixes import (
2525 FixHeaderRegistration as Registration ,
@@ -70,6 +70,17 @@ def init_rodent_brain_extraction_wf(
7070 tpl_tissue_labels = get_template (in_template ,resolution = debug + 1 , desc = 'cerebrum' , suffix = 'dseg' )
7171 tpl_brain_mask = get_template (in_template , resolution = debug + 1 , desc = 'cerebrum' , suffix = 'mask' )
7272
73+ # 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
78+
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' )
83+
7384 dil_mask = pe .Node (MaskTool (), name = 'dil_mask' )
7485 dil_mask .inputs .outputtype = 'NIFTI_GZ'
7586 dil_mask .inputs .dilate_inputs = '2'
@@ -88,15 +99,6 @@ def init_rodent_brain_extraction_wf(
8899 bspline_fitting_distance = bspline_fitting_distance ),
89100 n_procs = omp_nthreads , name = 'inu_n4' , iterfield = ['input_image' ])
90101
91- # resample template and target
92- res_tmpl = pe .Node (ResampleImageBySpacing (
93- out_spacing = (0.4 , 0.4 , 0.4 ), apply_smoothing = False ), name = 'res_tmpl' )
94- if tpl_target_path :
95- res_tmpl .inputs .input_image = str (tpl_target_path )
96- res_target = pe .Node (ResampleImageBySpacing (
97- out_spacing = (0.4 , 0.4 , 0.4 ), apply_smoothing = False ), name = 'res_target' )
98- res_target2 = pe .Node (ResampleImageBySpacing (
99- out_spacing = (0.4 , 0.4 , 0.4 ), apply_smoothing = False ), name = 'res_target2' )
100102
101103 lap_tmpl = pe .Node (ImageMath (operation = 'Laplacian' , op2 = '0.4' ), name = 'lap_tmpl' )
102104 if tpl_target_path :
@@ -118,6 +120,7 @@ def init_rodent_brain_extraction_wf(
118120 search_factor = (2 , 0.015 ),
119121 principal_axes = False ,
120122 convergence = (10 , 1e-6 , 10 ),
123+ search_grid = (1 , (1 , 2 , 2 )),
121124 verbose = True ),
122125 name = 'init_aff' ,
123126 n_procs = omp_nthreads )
@@ -126,16 +129,8 @@ def init_rodent_brain_extraction_wf(
126129 warp_mask = pe .Node (ApplyTransforms (
127130 interpolation = 'Linear' , invert_transform_flags = True ), name = 'warp_mask' )
128131
129- # Tolerate missing ANTs at construction time
130- _ants_version = Registration ().version
131- if _ants_version and parseversion (_ants_version ) >= Version ('2.3.0' ):
132- init_aff .inputs .search_grid = (1 , (1 , 2 , 2 ))
133-
134- fixed_mask_trait = 'fixed_image_mask'
135- moving_mask_trait = 'moving_image_mask'
136- if _ants_version and parseversion (_ants_version ) >= Version ('2.2.0' ):
137- fixed_mask_trait += 's'
138- moving_mask_trait += 's'
132+ fixed_mask_trait = 'fixed_image_masks'
133+ moving_mask_trait = 'moving_image_masks'
139134
140135 # Set up initial spatial normalization
141136 init_settings_file = f'data/brainextraction_{ init_normalization_quality } _{ modality } .json'
@@ -150,16 +145,10 @@ def init_rodent_brain_extraction_wf(
150145 inu_n4_final = pe .MapNode (
151146 N4BiasFieldCorrection (
152147 dimension = 3 , save_bias = True , copy_header = True ,
153- n_iterations = [50 ] * 5 , convergence_threshold = 1e-7 , shrink_factor = 4 ,
154- bspline_fitting_distance = bspline_fitting_distance ),
148+ n_iterations = [50 ] * 5 , convergence_threshold = 1e-7 ,
149+ bspline_fitting_distance = bspline_fitting_distance ,
150+ rescale_intensities = True , shrink_factor = 4 ),
155151 n_procs = omp_nthreads , name = 'inu_n4_final' , iterfield = ['input_image' ])
156- if _ants_version and parseversion (_ants_version ) >= Version ('2.1.0' ):
157- inu_n4_final .inputs .rescale_intensities = True
158- else :
159- warn ("""\
160- Found ANTs version %s, which is too old. Please consider upgrading to 2.1.0 or \
161- greater so that the --rescale-intensities option is available with \
162- N4BiasFieldCorrection.""" % _ants_version , DeprecationWarning )
163152
164153 split_init_transforms = pe .Node (niu .Split (splits = [1 ,1 ]), name = 'split_init_transforms' )
165154 mrg_init_transforms = pe .Node (niu .Merge (2 ), name = 'mrg_init_transforms' )
@@ -217,16 +206,16 @@ def init_rodent_brain_extraction_wf(
217206 wf .connect ([
218207 # resampling, truncation, initial N4, and creation of laplacian
219208 (inputnode , trunc , [('in_files' , 'op1' )]),
220- (trunc , res_target , [(('output_image' , _pop ), 'input_image ' )]),
221- (res_target , inu_n4 , [('output_image ' , 'input_image' )]),
209+ (trunc , res_target , [(('output_image' , _pop ), 'in_file ' )]),
210+ (res_target , inu_n4 , [('out_file ' , 'input_image' )]),
222211
223212 # dilation of input mask
224213 (inputnode , dil_mask , [('in_mask' , 'in_file' )]),
225214
226215 # ants AI inputs
227216 (inu_n4 , init_aff , [(('output_image' , _pop ), 'moving_image' )]),
228217 (dil_mask , init_aff , [('out_file' , 'fixed_image_mask' )]),
229- (res_tmpl , init_aff , [('output_image ' , 'fixed_image' )]),
218+ (res_tmpl , init_aff , [('out_file ' , 'fixed_image' )]),
230219
231220 # warp mask to individual space
232221 (dil_mask , warp_mask , [('out_file' , 'input_image' )]),
@@ -241,10 +230,10 @@ def init_rodent_brain_extraction_wf(
241230 (inu_n4_final , lap_target , [(('output_image' , _pop ), 'op1' )]),
242231 (lap_target , norm_lap_target , [('output_image' , 'op1' )]),
243232 (norm_lap_target , mrg_target , [('output_image' , 'in2' )]),
244- (inu_n4_final , res_target2 , [(('output_image' , _pop ), 'input_image ' )]),
245- (res_target2 , mrg_target , [('output_image ' , 'in1' )]),
233+ (inu_n4_final , res_target2 , [(('output_image' , _pop ), 'in_file ' )]),
234+ (res_target2 , mrg_target , [('out_file ' , 'in1' )]),
246235
247- (res_tmpl , mrg_tmpl , [('output_image ' , 'in1' )]),
236+ (res_tmpl , mrg_tmpl , [('out_file ' , 'in1' )]),
248237 (lap_tmpl , norm_lap_tmpl , [('output_image' , 'op1' )]),
249238 (norm_lap_tmpl , mrg_tmpl , [('output_image' , 'in2' )]),
250239
@@ -295,22 +284,22 @@ def init_rodent_brain_extraction_wf(
295284 elif modality == 'mp2rage' :
296285 wf .connect ([
297286 # resampling and creation of laplacians
298- (inputnode , res_target , [('in_files' , 'input_image ' )]),
287+ (inputnode , res_target , [('in_files' , 'in_file ' )]),
299288 (inputnode , lap_target , [('in_files' , 'op1' )]),
300289 (lap_target , norm_lap_target , [('output_image' , 'op1' )]),
301290 (norm_lap_target , mrg_target , [('output_image' , 'in2' )]),
302- (res_target , mrg_target , [('output_image ' , 'in1' )]),
291+ (res_target , mrg_target , [('out_file ' , 'in1' )]),
303292
304- (res_tmpl , mrg_tmpl , [('output_image ' , 'in1' )]),
293+ (res_tmpl , mrg_tmpl , [('out_file ' , 'in1' )]),
305294 (lap_tmpl , norm_lap_tmpl , [('output_image' , 'op1' )]),
306295 (norm_lap_tmpl , mrg_tmpl , [('output_image' , 'in2' )]),
307296
308297 #dilation of input mask
309298 (inputnode , dil_mask , [('in_mask' , 'in_file' )]),
310299
311300 # ants AI inputs
312- (res_tmpl , init_aff , [('output_image ' , 'fixed_image' )]),
313- (res_target , init_aff , [('output_image ' , 'moving_image' )]),
301+ (res_tmpl , init_aff , [('out_file ' , 'fixed_image' )]),
302+ (res_target , init_aff , [('out_file ' , 'moving_image' )]),
314303 (dil_mask , init_aff , [('out_file' , 'fixed_image_mask' )]),
315304
316305 # warp mask to individual space
@@ -365,3 +354,19 @@ def _pop(in_files):
365354 if isinstance (in_files , (list , tuple )):
366355 return in_files [0 ]
367356 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