Skip to content

Commit 96c50f2

Browse files
authored
Merge pull request #3435 from dmartindeblas/enh/ants-imagemath
[ENH] Include several operations to ANTs's ImageMath interface, including ReplicateImage and ReplicateDisplacement
2 parents 87cc1b5 + f482310 commit 96c50f2

File tree

2 files changed

+77
-12
lines changed

2 files changed

+77
-12
lines changed

nipype/interfaces/ants/tests/test_auto_ImageMath.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ def test_ImageMath_inputs():
66
input_map = dict(
77
args=dict(
88
argstr="%s",
9+
position=-1,
910
),
1011
copy_header=dict(
1112
usedefault=True,
@@ -27,11 +28,11 @@ def test_ImageMath_inputs():
2728
argstr="%s",
2829
extensions=None,
2930
mandatory=True,
30-
position=-2,
31+
position=-3,
3132
),
3233
op2=dict(
3334
argstr="%s",
34-
position=-1,
35+
position=-2,
3536
),
3637
operation=dict(
3738
argstr="%s",

nipype/interfaces/ants/utils.py

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class ImageMathInputSpec(ANTSCommandInputSpec):
1919
keep_extension=True,
2020
)
2121
operation = traits.Enum(
22+
# Mathematical Operations
2223
"m",
2324
"vm",
2425
"+",
@@ -37,6 +38,7 @@ class ImageMathInputSpec(ANTSCommandInputSpec):
3738
"vtotal",
3839
"Decision",
3940
"Neg",
41+
# Spatial Filtering Operations
4042
"Project",
4143
"G",
4244
"MD",
@@ -47,22 +49,72 @@ class ImageMathInputSpec(ANTSCommandInputSpec):
4749
"GE",
4850
"GO",
4951
"GC",
50-
"TruncateImageIntensity",
51-
"Laplacian",
52-
"GetLargestComponent",
52+
"ExtractContours",
53+
# Transform Image Operations
54+
"Translate",
55+
# Tensor Operations
56+
"4DTensorTo3DTensor",
57+
"ExtractVectorComponent",
58+
"TensorColor",
59+
"TensorFA",
60+
"TensorFADenominator",
61+
"TensorFANumerator",
62+
"TensorMeanDiffusion",
63+
"TensorRadialDiffusion",
64+
"TensorAxialDiffusion",
65+
"TensorEigenvalue",
66+
"TensorToVector",
67+
"TensorToVectorComponent",
68+
"TensorMask",
69+
# Unclassified Operators
70+
"Byte",
71+
"CorruptImage",
72+
"D",
73+
"MaurerDistance",
74+
"ExtractSlice",
5375
"FillHoles",
76+
"Convolve",
77+
"Finite",
78+
"FlattenImage",
79+
"GetLargestComponent",
80+
"Grad",
81+
"RescaleImage",
82+
"WindowImage",
83+
"NeighborhoodStats",
84+
"ReplicateDisplacement",
85+
"ReplicateImage",
86+
"LabelStats",
87+
"Laplacian",
88+
"Canny",
89+
"Lipschitz",
90+
"MTR",
91+
"Normalize",
5492
"PadImage",
93+
"SigmoidImage",
94+
"Sharpen",
95+
"UnsharpMask",
96+
"PValueImage",
97+
"ReplaceVoxelValue",
98+
"SetTimeSpacing",
99+
"SetTimeSpacingWarp",
100+
"stack",
101+
"ThresholdAtMean",
102+
"TriPlanarView",
103+
"TruncateImageIntensity",
55104
mandatory=True,
56105
position=3,
57106
argstr="%s",
58107
desc="mathematical operations",
59108
)
60109
op1 = File(
61-
exists=True, mandatory=True, position=-2, argstr="%s", desc="first operator"
110+
exists=True, mandatory=True, position=-3, argstr="%s", desc="first operator"
62111
)
63112
op2 = traits.Either(
64-
File(exists=True), Str, position=-1, argstr="%s", desc="second operator"
113+
File(exists=True), Str, position=-2, argstr="%s", desc="second operator"
65114
)
115+
116+
args = Str(position=-1, argstr="%s", desc="Additional parameters to the command")
117+
66118
copy_header = traits.Bool(
67119
True,
68120
usedefault=True,
@@ -106,7 +158,7 @@ class ImageMath(ANTSCommand, CopyHeaderInterface):
106158
107159
By default, Nipype copies headers from the first input image (``op1``)
108160
to the output image.
109-
For the ``PadImage`` operation, the header cannot be copied from inputs to
161+
For some operations, as the ``PadImage`` operation, the header cannot be copied from inputs to
110162
outputs, and so ``copy_header`` option is automatically set to ``False``.
111163
112164
>>> pad = ImageMath(
@@ -135,22 +187,34 @@ class ImageMath(ANTSCommand, CopyHeaderInterface):
135187
input_spec = ImageMathInputSpec
136188
output_spec = ImageMathOuputSpec
137189
_copy_header_map = {"output_image": "op1"}
190+
_no_copy_header_operation = (
191+
"PadImage",
192+
"LabelStats",
193+
"SetTimeSpacing",
194+
"SetTimeSpacingWarp",
195+
"TriPlanarView",
196+
)
138197

139198
def __init__(self, **inputs):
140199
super(ImageMath, self).__init__(**inputs)
141-
if self.inputs.operation in ("PadImage",):
200+
if self.inputs.operation in self._no_copy_header_operation:
142201
self.inputs.copy_header = False
143202

144203
self.inputs.on_trait_change(self._operation_update, "operation")
145204
self.inputs.on_trait_change(self._copyheader_update, "copy_header")
146205

147206
def _operation_update(self):
148-
if self.inputs.operation in ("PadImage",):
207+
if self.inputs.operation in self._no_copy_header_operation:
149208
self.inputs.copy_header = False
150209

151210
def _copyheader_update(self):
152-
if self.inputs.copy_header and self.inputs.operation in ("PadImage",):
153-
warn("copy_header cannot be updated to True with PadImage as operation.")
211+
if (
212+
self.inputs.copy_header
213+
and self.inputs.operation in self._no_copy_header_operation
214+
):
215+
warn(
216+
f"copy_header cannot be updated to True with {self.inputs.operation} as operation."
217+
)
154218
self.inputs.copy_header = False
155219

156220

0 commit comments

Comments
 (0)