@@ -495,3 +495,95 @@ def _list_outputs(self):
495
495
outputs ['out_map' ] = self ._out_file
496
496
497
497
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
0 commit comments