Skip to content

Commit cf0af24

Browse files
committed
Moved the new Similarity in 4D to metrics
Close #802. Please merge #830 before this PR
1 parent dc24afc commit cf0af24

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

nipype/algorithms/metrics.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,3 +495,95 @@ def _list_outputs(self):
495495
outputs['out_map'] = self._out_file
496496

497497
return outputs
498+
499+
500+
class SimilarityInputSpec(BaseInterfaceInputSpec):
501+
502+
volume1 = File(exists=True, desc="3D/4D volume", mandatory=True)
503+
volume2 = File(exists=True, desc="3D/4D volume", mandatory=True)
504+
mask1 = File(exists=True, desc="3D volume")
505+
mask2 = File(exists=True, desc="3D volume")
506+
metric = traits.Either(traits.Enum('cc', 'cr', 'crl1', 'mi', 'nmi', 'slr'),
507+
traits.Callable(),
508+
desc="""str or callable
509+
Cost-function for assessing image similarity. If a string,
510+
one of 'cc': correlation coefficient, 'cr': correlation
511+
ratio, 'crl1': L1-norm based correlation ratio, 'mi': mutual
512+
information, 'nmi': normalized mutual information, 'slr':
513+
supervised log-likelihood ratio. If a callable, it should
514+
take a two-dimensional array representing the image joint
515+
histogram as an input and return a float.""", usedefault=True)
516+
517+
518+
class SimilarityOutputSpec(TraitedSpec):
519+
similarity = traits.List( traits.Float(desc="Similarity between volume 1 and 2, frame by frame"))
520+
521+
522+
class Similarity(BaseInterface):
523+
"""Calculates similarity between two 3D or 4D volumes. Both volumes have to be in
524+
the same coordinate system, same space within that coordinate system and
525+
with the same voxel dimensions.
526+
527+
.. note::
528+
529+
This interface is an extension of nipype.interfaces.nipy.utils.Similarity
530+
to support 4D files.
531+
532+
Example
533+
-------
534+
>>> from nipype.interfaces.nipy.utils import Similarity
535+
>>> similarity = Similarity()
536+
>>> similarity.inputs.volume1 = 'rc1s1.nii'
537+
>>> similarity.inputs.volume2 = 'rc1s2.nii'
538+
>>> similarity.inputs.mask1 = 'mask.nii'
539+
>>> similarity.inputs.mask2 = 'mask.nii'
540+
>>> similarity.inputs.metric = 'cr'
541+
>>> res = similarity.run() # doctest: +SKIP
542+
"""
543+
544+
input_spec = SimilarityInputSpec
545+
output_spec = SimilarityOutputSpec
546+
547+
def _run_interface(self, runtime):
548+
549+
vol1_nii = nb.load(self.inputs.volume1)
550+
vol2_nii = nb.load(self.inputs.volume2)
551+
552+
dims = vol1_nii.get_data().ndim
553+
554+
if dims==3 or dims==2:
555+
vols1 = [ vol1_nii ]
556+
vols2 = [ vol2_nii ]
557+
if dims==4:
558+
vols1 = nb.four_to_three( vol1_nii )
559+
vols2 = nb.four_to_three( vol2_nii )
560+
561+
if dims<2 or dims>4:
562+
raise RuntimeError( 'Image dimensions not supported (detected %dD file)' % dims )
563+
564+
if isdefined(self.inputs.mask1):
565+
mask1 = nb.load(self.inputs.mask1).get_data() == 1
566+
else:
567+
mask1 = None
568+
569+
if isdefined(self.inputs.mask2):
570+
mask2 = nb.load(self.inputs.mask2).get_data() == 1
571+
else:
572+
mask2 = None
573+
574+
self._similarity = []
575+
576+
for ts1,ts2 in zip( vols1, vols2 ):
577+
histreg = HistogramRegistration(from_img = ts1,
578+
to_img = ts2,
579+
similarity=self.inputs.metric,
580+
from_mask = mask1,
581+
to_mask = mask2)
582+
self._similarity.append( histreg.eval(Affine()) )
583+
584+
return runtime
585+
586+
def _list_outputs(self):
587+
outputs = self._outputs().get()
588+
outputs['similarity'] = self._similarity
589+
return outputs

nipype/interfaces/nipy/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ class Similarity(BaseInterface):
6868
input_spec = SimilarityInputSpec
6969
output_spec = SimilarityOutputSpec
7070

71+
def __init__(self, **inputs):
72+
warnings.warn("This interface is deprecated. Please use nipy.algorithms.metrics.Similarity",
73+
DeprecationWarning)
74+
super(BaseInterface,self).__init__(**inputs)
75+
7176
def _run_interface(self, runtime):
7277

7378
vol1_nii = nb.load(self.inputs.volume1)

0 commit comments

Comments
 (0)