Skip to content

Commit 15b9fa5

Browse files
authored
Merge pull request #22 from poldracklab/fix/resample_bug
FIX: resampling bug
2 parents f039428 + b637860 commit 15b9fa5

File tree

1 file changed

+46
-41
lines changed

1 file changed

+46
-41
lines changed

nirodents/workflows/brainextraction.py

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
from nipype.pipeline import engine as pe
1414
from nipype.interfaces import utility as niu
1515
from 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,
1717
from nipype.interfaces.afni import MaskTool
18-
# from nipype.interfaces.fsl import ApplyMask
1918
from nipype.interfaces.io import DataSink
2019

2120
# niworkflows
2221
from niworkflows.interfaces.ants import ImageMath
22+
from niworkflows.utils.images import resample_by_spacing
2323
from niworkflows.interfaces.nibabel import ApplyMask
2424
from 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

Comments
 (0)