Skip to content

Commit 2a1d07d

Browse files
committed
ENH: Add image.Rescale interface
1 parent a882e74 commit 2a1d07d

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

nipype/interfaces/image.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,84 @@
99
from .base import (SimpleInterface, TraitedSpec, BaseInterfaceInputSpec,
1010
traits, File)
1111

12+
13+
class RescaleInputSpec(BaseInterfaceInputSpec):
14+
in_file = File(exists=True, mandatory=True,
15+
desc='Skull-stripped image to rescale')
16+
ref_file = File(exists=True, mandatory=True,
17+
desc='Skull-stripped reference image')
18+
invert = traits.Bool(desc='Invert contrast of rescaled image')
19+
percentile = traits.Range(low=0., high=50., value=0., usedefault=True,
20+
desc='Percentile to use for reference to allow '
21+
'for outliers - 1 indicates the 1st and '
22+
'99th percentiles in the input file will '
23+
'be mapped to the 99th and 1st percentiles '
24+
'in the reference; 0 indicates minima and '
25+
'maxima will be mapped')
26+
27+
28+
class RescaleOutputSpec(TraitedSpec):
29+
out_file = File(exists=True, desc='Rescaled image')
30+
31+
32+
class Rescale(SimpleInterface):
33+
"""Rescale an image
34+
35+
Rescales the non-zero portion of ``in_file`` to match the bounds of the '
36+
non-zero portion of ``ref_file``.
37+
Reference values in the input and reference images are defined by the
38+
``percentile`` parameter, and the reference values in each image are
39+
identified and the remaining values are scaled accordingly.
40+
In the case of ``percentile == 0``, the reference values are the maxima
41+
and minima of each image.
42+
If the ``invert`` parameter is set, the input file is inverted prior to
43+
rescaling.
44+
45+
Examples
46+
--------
47+
48+
To use a high-resolution T1w image as a registration target for a T2\*
49+
image, it may be useful to invert the T1w image and rescale to the T2\*
50+
range.
51+
Using the 1st and 99th percentiles may reduce the impact of outlier
52+
voxels.
53+
54+
>>> from nipype.interfaces.image import Rescale
55+
>>> invert_t1w = Reorient(invert=True)
56+
>>> invert_t1w.inputs.in_file = 'structural.nii'
57+
>>> invert_t1w.inputs.ref_file = 'functional.nii'
58+
>>> invert_t1w.inputs.percentile = 1.
59+
>>> res = invert_t1w.run() # doctest: +SKIP
60+
61+
"""
62+
input_spec = RescaleInputSpec
63+
output_spec = RescaleOutputSpec
64+
65+
def _run_interface(self, runtime):
66+
img = nb.load(self.inputs.in_file)
67+
data = img.get_data()
68+
ref_data = nb.load(self.inputs.ref_file).get_data()
69+
70+
in_mask = data > 0
71+
ref_mask = ref_data > 0
72+
73+
q = [self.inputs.percentile, 100. - self.inputs.percentile]
74+
in_low, in_high = np.percentile(data[in_mask], q)
75+
ref_low, ref_high = np.percentile(ref_data[ref_mask], q)
76+
scale_factor = (ref_high - ref_low) / (in_high - in_low)
77+
78+
signal = in_high - data if self.inputs.invert else data - in_low
79+
out_data = in_mask * (signal * scale_factor + ref_low)
80+
81+
suffix = '_inv' if self.inputs.invert else '_rescaled'
82+
out_file = fname_presuffix(self.inputs.in_file, suffix=suffix,
83+
newpath=runtime.cwd)
84+
img.__class__(out_data, img.affine, img.header).to_filename(out_file)
85+
86+
self._results['out_file'] = out_file
87+
return runtime
88+
89+
1290
_axes = ('RL', 'AP', 'SI')
1391
_orientations = tuple(
1492
''.join((x[i], y[j], z[k]))

0 commit comments

Comments
 (0)