Skip to content

Commit 05ed09a

Browse files
committed
enh: replace ANTs' ResampleImageBySpacing with RegridToZooms
1 parent 647e428 commit 05ed09a

File tree

3 files changed

+25
-17
lines changed

3 files changed

+25
-17
lines changed

niworkflows/anat/ants.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@
1818
N4BiasFieldCorrection,
1919
ThresholdImage,
2020
)
21-
from nipype.interfaces.ants.utils import AI, ResampleImageBySpacing
21+
from nipype.interfaces.ants.utils import AI
2222

2323
from ..utils.misc import get_template_specs
2424
from ..utils.connections import pop_file as _pop
2525

2626
# niworkflows
27-
from ..interfaces.nibabel import ApplyMask
2827
from ..interfaces.ants import ImageMath
2928
from ..interfaces.fixes import (
3029
FixHeaderRegistration as Registration,
3130
FixHeaderApplyTransforms as ApplyTransforms,
3231
)
33-
from ..interfaces.nibabel import Binarize
32+
from ..interfaces.images import RegridToZooms
33+
from ..interfaces.nibabel import ApplyMask, Binarize
3434

3535

3636
ATROPOS_MODELS = {
@@ -221,15 +221,9 @@ def init_brain_extraction_wf(
221221
iterfield=["input_image"],
222222
)
223223

224-
res_tmpl = pe.Node(
225-
ResampleImageBySpacing(out_spacing=(4, 4, 4), apply_smoothing=True),
226-
name="res_tmpl",
227-
)
228-
res_tmpl.inputs.input_image = tpl_target_path
229-
res_target = pe.Node(
230-
ResampleImageBySpacing(out_spacing=(4, 4, 4), apply_smoothing=True),
231-
name="res_target",
232-
)
224+
res_tmpl = pe.Node(RegridToZooms(in_file=tpl_target_path, zooms=(4, 4, 4), smooth=True),
225+
name="res_tmpl")
226+
res_target = pe.Node(RegridToZooms(zooms=(4, 4, 4), smooth=True), name="res_target")
233227

234228
lap_tmpl = pe.Node(ImageMath(operation="Laplacian", op2="1.5 1"), name="lap_tmpl")
235229
lap_tmpl.inputs.op1 = tpl_target_path
@@ -337,9 +331,9 @@ def init_brain_extraction_wf(
337331
(inputnode, norm, [("in_mask", fixed_mask_trait)]),
338332
(inputnode, map_brainmask, [(("in_files", _pop), "reference_image")]),
339333
(trunc, inu_n4, [("output_image", "input_image")]),
340-
(inu_n4, res_target, [(("output_image", _pop), "input_image")]),
341-
(res_tmpl, init_aff, [("output_image", "fixed_image")]),
342-
(res_target, init_aff, [("output_image", "moving_image")]),
334+
(inu_n4, res_target, [(("output_image", _pop), "in_file")]),
335+
(res_tmpl, init_aff, [("out_file", "fixed_image")]),
336+
(res_target, init_aff, [("out_file", "moving_image")]),
343337
(init_aff, norm, [("output_transform", "initial_moving_transform")]),
344338
(norm, map_brainmask, [
345339
("reverse_transforms", "transforms"),

niworkflows/interfaces/images.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class _RegridToZoomsInputSpec(BaseInterfaceInputSpec):
4242
usedefault=True,
4343
desc="clip the data array within the original image's range",
4444
)
45+
smooth = traits.Either(
46+
False,
47+
traits.Bool(),
48+
traits.Float(),
49+
usedefault=True,
50+
desc="apply gaussian smoothing before resampling"
51+
)
4552

4653

4754
class _RegridToZoomsOutputSpec(TraitedSpec):
@@ -65,6 +72,7 @@ def _run_interface(self, runtime):
6572
self.inputs.zooms,
6673
order=self.inputs.order,
6774
clip=self.inputs.clip,
75+
smooth=self.inputs.smooth,
6876
).to_filename(self._results["out_file"])
6977
return runtime
7078

niworkflows/utils/images.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def dseg_label(in_seg, label, newpath=None):
127127
return out_file
128128

129129

130-
def resample_by_spacing(in_file, zooms, order=3, clip=True):
130+
def resample_by_spacing(in_file, zooms, order=3, clip=True, smooth=False):
131131
"""Regrid the input image to match the new zooms."""
132132
from pathlib import Path
133133
import numpy as np
@@ -143,7 +143,6 @@ def resample_by_spacing(in_file, zooms, order=3, clip=True):
143143

144144
hdr = in_file.header.copy()
145145
dtype = hdr.get_data_dtype()
146-
data = np.asanyarray(in_file.dataobj)
147146
zooms = np.array(zooms)
148147

149148
# Calculate the factors to normalize voxel size to the specific zooms
@@ -174,6 +173,13 @@ def resample_by_spacing(in_file, zooms, order=3, clip=True):
174173
new_card.dot(np.vstack((new_grid, np.ones((1, new_grid.shape[1])))))
175174
)
176175

176+
if smooth:
177+
from scipy.ndimage import gaussian_filter
178+
data = gaussian_filter(in_file.get_fdata(),
179+
2 if smooth is True else smooth).astype(dtype)
180+
else:
181+
data = np.asanyarray(in_file.dataobj)
182+
177183
# Resample data in the new grid
178184
resampled = map_coordinates(
179185
data,

0 commit comments

Comments
 (0)