Skip to content

Commit 053d1ca

Browse files
committed
added interface for MeasureImageSimilarity
1 parent 2ee584b commit 053d1ca

File tree

3 files changed

+184
-1
lines changed

3 files changed

+184
-1
lines changed

nipype/interfaces/ants/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""Top-level namespace for ants."""
66

77
# Registraiton programs
8-
from .registration import ANTS, Registration
8+
from .registration import ANTS, Registration, MeasureImageSimilarity
99

1010
# Resampling Programs
1111
from .resampling import (ApplyTransforms, ApplyTransformsToPoints, WarpImageMultiTransform,

nipype/interfaces/ants/registration.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,3 +1034,125 @@ def _list_outputs(self):
10341034
if len(self.inputs.save_state):
10351035
outputs['save_state'] = os.path.abspath(self.inputs.save_state)
10361036
return outputs
1037+
1038+
1039+
class MeasureImageSimilarityInputSpec(ANTSCommandInputSpec):
1040+
dimension = traits.Enum(
1041+
2, 3, 4,
1042+
argstr='--dimensionality %d', position=1,
1043+
desc='Dimensionality of the fixed/moving image pair',
1044+
)
1045+
fixed_image = File(
1046+
exists=True, mandatory=True,
1047+
desc='Image to which the moving image is warped',
1048+
)
1049+
moving_image = File(
1050+
exists=True, mandatory=True,
1051+
desc='Image to apply transformation to (generally a coregistered functional)',
1052+
)
1053+
metric = traits.Enum(
1054+
"CC", "MI", "Mattes", "MeanSquares", "Demons", "GC",
1055+
argstr="%s", mandatory=True,
1056+
)
1057+
metric_weight = traits.Float(
1058+
requires=['metric'], default=1.0, usedefault=True,
1059+
desc='The "metricWeight" variable is not used.',
1060+
)
1061+
radius_or_number_of_bins = traits.Int(
1062+
requires=['metric'], mandatory=True,
1063+
desc='The number of bins in each stage for the MI and Mattes metric, '
1064+
'or the radius for other metrics',
1065+
)
1066+
sampling_strategy = traits.Enum(
1067+
"None", "Regular", "Random",
1068+
requires=['metric'], default="None", usedefault=True,
1069+
desc='Manner of choosing point set over which to optimize the metric. '
1070+
'Defaults to "None" (i.e. a dense sampling of one sample per voxel).'
1071+
)
1072+
sampling_percentage = traits.Either(
1073+
traits.Range(low=0.0, high=1.0),
1074+
requires=['metric'], mandatory=True,
1075+
desc='Percentage of points accessible to the sampling strategy over which '
1076+
'to optimize the metric.'
1077+
)
1078+
fixed_image_mask = File(
1079+
exists=True, argstr='%s',
1080+
desc='mask used to limit metric sampling region of the fixed image',
1081+
)
1082+
moving_image_mask = File(
1083+
exists=True, requires=['fixed_image_mask'],
1084+
desc='mask used to limit metric sampling region of the moving image',
1085+
)
1086+
1087+
1088+
class MeasureImageSimilarityOutputSpec(TraitedSpec):
1089+
similarity = traits.Float()
1090+
1091+
1092+
class MeasureImageSimilarity(ANTSCommand):
1093+
"""
1094+
1095+
1096+
Examples
1097+
--------
1098+
1099+
>>> from nipype.interfaces.ants import MeasureImageSimilarity
1100+
>>> sim = MeasureImageSimilarity()
1101+
>>> sim.inputs.dimension = 3
1102+
>>> sim.inputs.metric = 'MI'
1103+
>>> sim.inputs.fixed_image = 'T1.nii'
1104+
>>> sim.inputs.moving_image = 'resting.nii'
1105+
>>> sim.inputs.metric_weight = 1.0
1106+
>>> sim.inputs.radius_or_number_of_bins = 5
1107+
>>> sim.inputs.sampling_strategy = 'Regular'
1108+
>>> sim.inputs.sampling_percentage = 1.0
1109+
>>> sim.inputs.fixed_image_mask = 'mask.nii'
1110+
>>> sim.inputs.moving_image_mask = 'mask.nii.gz'
1111+
>>> sim.cmdline # doctest: +ALLOW_UNICODE
1112+
u'MeasureImageSimilarity --dimensionality 3 --masks ["mask.nii","mask.nii.gz"] \
1113+
--metric MI["T1.nii","resting.nii",1.0,5,Regular,1.0]'
1114+
"""
1115+
_cmd = 'MeasureImageSimilarity'
1116+
input_spec = MeasureImageSimilarityInputSpec
1117+
output_spec = MeasureImageSimilarityOutputSpec
1118+
1119+
def _metric_constructor(self):
1120+
retval = '--metric {metric}["{fixed_image}","{moving_image}",{metric_weight},'\
1121+
'{radius_or_number_of_bins},{sampling_strategy},{sampling_percentage}]'\
1122+
.format(
1123+
metric=self.inputs.metric,
1124+
fixed_image=self.inputs.fixed_image,
1125+
moving_image=self.inputs.moving_image,
1126+
metric_weight=self.inputs.metric_weight,
1127+
radius_or_number_of_bins=self.inputs.radius_or_number_of_bins,
1128+
sampling_strategy=self.inputs.sampling_strategy,
1129+
sampling_percentage=self.inputs.sampling_percentage,
1130+
)
1131+
return retval
1132+
1133+
def _mask_constructor(self):
1134+
if self.inputs.moving_image_mask:
1135+
retval = '--masks ["{fixed_image_mask}","{moving_image_mask}"]'\
1136+
.format(
1137+
fixed_image_mask=self.inputs.fixed_image_mask,
1138+
moving_image_mask=self.inputs.moving_image_mask,
1139+
)
1140+
else:
1141+
retval = '--masks "{fixed_image_mask}"'\
1142+
.format(
1143+
fixed_image_mask=self.inputs.fixed_image_mask,
1144+
)
1145+
return retval
1146+
1147+
def _format_arg(self, opt, spec, val):
1148+
if opt == 'metric':
1149+
return self._metric_constructor()
1150+
elif opt == 'fixed_image_mask':
1151+
return self._mask_constructor()
1152+
return super(MeasureImageSimilarity, self)._format_arg(opt, spec, val)
1153+
1154+
def aggregate_outputs(self, runtime=None, needed_outputs=None):
1155+
outputs = self._outputs()
1156+
stdout = runtime.stdout.split('\n')
1157+
outputs.similarity = float(stdout[0])
1158+
return outputs
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..registration import MeasureImageSimilarity
4+
5+
6+
def test_MeasureImageSimilarity_inputs():
7+
input_map = dict(args=dict(argstr='%s',
8+
),
9+
dimension=dict(argstr='--dimensionality %d',
10+
position=1,
11+
),
12+
environ=dict(nohash=True,
13+
usedefault=True,
14+
),
15+
fixed_image=dict(mandatory=True,
16+
),
17+
fixed_image_mask=dict(argstr='%s',
18+
),
19+
ignore_exception=dict(nohash=True,
20+
usedefault=True,
21+
),
22+
metric=dict(argstr='%s',
23+
mandatory=True,
24+
),
25+
metric_weight=dict(requires=['metric'],
26+
usedefault=True,
27+
),
28+
moving_image=dict(mandatory=True,
29+
),
30+
moving_image_mask=dict(requires=['fixed_image_mask'],
31+
),
32+
num_threads=dict(nohash=True,
33+
usedefault=True,
34+
),
35+
radius_or_number_of_bins=dict(mandatory=True,
36+
requires=['metric'],
37+
),
38+
sampling_percentage=dict(mandatory=True,
39+
requires=['metric'],
40+
),
41+
sampling_strategy=dict(requires=['metric'],
42+
usedefault=True,
43+
),
44+
terminal_output=dict(nohash=True,
45+
),
46+
)
47+
inputs = MeasureImageSimilarity.input_spec()
48+
49+
for key, metadata in list(input_map.items()):
50+
for metakey, value in list(metadata.items()):
51+
assert getattr(inputs.traits()[key], metakey) == value
52+
53+
54+
def test_MeasureImageSimilarity_outputs():
55+
output_map = dict(similarity=dict(),
56+
)
57+
outputs = MeasureImageSimilarity.output_spec()
58+
59+
for key, metadata in list(output_map.items()):
60+
for metakey, value in list(metadata.items()):
61+
assert getattr(outputs.traits()[key], metakey) == value

0 commit comments

Comments
 (0)