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
@@ -133,9 +128,6 @@ def init_rodent_brain_extraction_wf(
133128 warp_mask_1 = pe .Node (ApplyTransforms (
134129 interpolation = 'Linear' , invert_transform_flags = True ), name = 'warp_mask_1' )
135130
136- fixed_mask_trait = 'fixed_image_masks'
137- moving_mask_trait = 'moving_image_masks'
138-
139131 # Set up initial spatial normalization
140132 init_settings_file = f'data/brainextraction_{ init_normalization_quality } _{ modality } .json'
141133 init_norm = pe .Node (Registration (from_file = pkgr_fn (
@@ -149,12 +141,12 @@ def init_rodent_brain_extraction_wf(
149141 inu_n4_final = pe .MapNode (
150142 N4BiasFieldCorrection (
151143 dimension = 3 , save_bias = True , copy_header = True ,
152- n_iterations = [50 ] * 5 , convergence_threshold = 1e-7 ,
144+ n_iterations = [50 ] * 5 , convergence_threshold = 1e-7 ,
153145 bspline_fitting_distance = bspline_fitting_distance ,
154- rescale_intensities = True , shrink_factor = 4 ),
146+ rescale_intensities = True , shrink_factor = 4 ),
155147 n_procs = omp_nthreads , name = 'inu_n4_final' , iterfield = ['input_image' ])
156148
157- split_init_transforms = pe .Node (niu .Split (splits = [1 ,1 ]), name = 'split_init_transforms' )
149+ split_init_transforms = pe .Node (niu .Split (splits = [1 , 1 ]), name = 'split_init_transforms' )
158150 mrg_init_transforms = pe .Node (niu .Merge (2 ), name = 'mrg_init_transforms' )
159151
160152 # Use more precise transforms to warp mask to subject space
@@ -163,10 +155,8 @@ def init_rodent_brain_extraction_wf(
163155 name = 'warp_mask_2' )
164156
165157 # morphological closing of warped mask
166- close_mask = pe .Node (MaskTool (), name = 'close_mask' )
167- close_mask .inputs .outputtype = 'NIFTI_GZ'
168- close_mask .inputs .dilate_inputs = '5 -5'
169- close_mask .inputs .fill_holes = True
158+ close_mask = pe .Node (MaskTool (outputtype = 'NIFTI_GZ' , dilate_inputs = '5 -5' , fill_holes = True ),
159+ name = 'close_mask' )
170160
171161 # Use subject-space mask to skull-strip subject
172162 skullstrip_tar = pe .Node (ApplyMask (), name = 'skullstrip_tar' )
@@ -183,7 +173,7 @@ def init_rodent_brain_extraction_wf(
183173 mem_gb = mem_gb )
184174 refine_norm .inputs .float = use_float
185175
186- split_final_transforms = pe .Node (niu .Split (splits = [1 ,1 ]), name = 'split_final_transforms' )
176+ split_final_transforms = pe .Node (niu .Split (splits = [1 , 1 ]), name = 'split_final_transforms' )
187177 mrg_final_transforms = pe .Node (niu .Merge (2 ), name = 'mrg_final_transforms' )
188178
189179 warp_mask_out = pe .Node (ApplyTransforms (
@@ -194,8 +184,8 @@ def init_rodent_brain_extraction_wf(
194184 else :
195185 warp_mask_out .inputs .input_image = tpl_regmask_path
196186
197- warp_seg_labels = pe .Node (ApplyTransforms (
198- interpolation = 'Linear' , invert_transform_flags = [False , True ]),
187+ warp_seg_labels = pe .Node (ApplyTransforms (
188+ interpolation = 'Linear' , invert_transform_flags = [False , True ]),
199189 name = 'warp_seg_labels' )
200190 if tpl_tissue_labels :
201191 warp_seg_labels .inputs .input_image = tpl_tissue_labels
@@ -236,7 +226,7 @@ def init_rodent_brain_extraction_wf(
236226 (inputnode , res_target , [('in_files' , 'in_file' )]),
237227 (inputnode , lap_target , [('in_files' , 'op1' )]),
238228 (lap_target , norm_lap_target , [('output_image' , 'op1' )]),
239- (norm_lap_target , mrg_target , [('output_image' , 'in2' )]),
229+ (norm_lap_target , mrg_target , [('output_image' , 'in2' )]),
240230 (res_target , mrg_target , [('out_file' , 'in1' )]),
241231 (res_target , integrate_1 , [('out_file' , 'in_file' )]),
242232 (inputnode , integrate_2 , [('in_files' , 'in_file' )])
@@ -321,19 +311,3 @@ def _pop(in_files):
321311 if isinstance (in_files , (list , tuple )):
322312 return in_files [0 ]
323313 return in_files
324-
325- def res_by_spc (in_file , out_file = None ):
326- import os .path as op
327- from niworkflows .utils .images import resample_by_spacing
328- import nibabel as nib
329- resampled = resample_by_spacing (in_file , (0.4 , 0.4 , 0.4 ), clip = False )
330-
331- if out_file is None :
332- fname , ext = op .splitext (op .basename (in_file ))
333- if ext == '.gz' :
334- fname , ext2 = op .splitext (fname )
335- ext = ext2 + ext
336- out_file = op .abspath ('{}_resampled{}' .format (fname , ext ))
337-
338- nib .save (resampled , out_file )
339- return out_file
0 commit comments