Skip to content

Commit 52721c2

Browse files
committed
Working version
1 parent ea176bc commit 52721c2

File tree

1 file changed

+46
-27
lines changed

1 file changed

+46
-27
lines changed

nipype/algorithms/misc.py

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -442,16 +442,18 @@ class FuzzyOverlapInputSpec(BaseInterfaceInputSpec):
442442
desc="Reference image. Requires the same dimensions as in_tst.")
443443
in_tst = InputMultiPath( File(exists=True), mandatory=True,
444444
desc="Test image. Requires the same dimensions as in_ref.")
445-
mask_volume = File( exists=True, desc="calculate overlap only within this mask.")
446-
weighting = traits.Enum("none", "volume", desc='""none": no class-overlap weighting is performed\
447-
"volume": computed class-overlaps are weighted by class volume',usedefault=True)
445+
weighting = traits.Enum("none", "volume", "squared_vol", desc='""none": no class-overlap weighting is performed\
446+
"volume": computed class-overlaps are weighted by class volume\
447+
"squared_vol": computed class-overlaps are weighted by the squared volume of the class',usedefault=True)
448448
out_file = File("diff.nii", usedefault=True)
449449

450450

451451
class FuzzyOverlapOutputSpec(TraitedSpec):
452452
jaccard = traits.Float()
453453
dice = traits.Float()
454454
diff_file = File(exists=True)
455+
class_ji = traits.List( traits.Float() )
456+
class_dsc = traits.List( traits.Float() )
455457

456458

457459
class FuzzyOverlap(BaseInterface):
@@ -476,44 +478,59 @@ class FuzzyOverlap(BaseInterface):
476478
input_spec = FuzzyOverlapInputSpec
477479
output_spec = FuzzyOverlapOutputSpec
478480

479-
def _bool_vec_dissimilarity(self, booldata1, booldata2, method):
480-
methods = {"dice": dice, "jaccard": jaccard}
481-
if not (np.any(booldata1) or np.any(booldata2)):
482-
return 0
483-
return 1 - methods[method](booldata1.flat, booldata2.flat)
484-
485481
def _run_interface(self, runtime):
486482
ncomp = len(self.inputs.in_ref)
487483
assert( ncomp == len(self.inputs.in_tst) )
488484
weights = np.ones( shape=ncomp )
489485

490-
img_ref = np.array( [ nib.load( fname ).get_data() for fname in self.inputs.in_ref ] )
491-
img_tst = np.array( [ nib.load( fname ).get_data() for fname in self.inputs.in_tst ] )
486+
img_ref = np.array( [ nb.load( fname ).get_data() for fname in self.inputs.in_ref ] )
487+
img_tst = np.array( [ nb.load( fname ).get_data() for fname in self.inputs.in_tst ] )
488+
489+
490+
msk = np.sum(img_ref, axis=0)
491+
msk[msk>0] = 1.0
492+
tst_msk = np.sum(img_tst, axis=0)
493+
tst_msk[tst_msk>0] = 1.0
492494

493495
#check that volumes are normalized
494-
img_ref = img_ref / np.sum( img_ref, axis=0 )
495-
img_tst = img_tst / np.sum( img_tst, axis=0 )
496+
#img_ref[:][msk>0] = img_ref[:][msk>0] / (np.sum( img_ref, axis=0 ))[msk>0]
497+
#img_tst[tst_msk>0] = img_tst[tst_msk>0] / np.sum( img_tst, axis=0 )[tst_msk>0]
496498

497-
num = float( np.minimum( img_ref, img_test ) )
498-
ddr = float( np.maximum( img_ref, img_test ) )
499-
both_data = num/ddr
500-
501-
jaccards = np.sum( num, axis=0 ) / np.sum( ddr, axis=0 )
502-
dices = 2.0*jaccards / (1.0+jaccards )
499+
self._jaccards = []
500+
volumes = []
501+
502+
diff_im = np.zeros( img_ref.shape )
503+
504+
for ref_comp, tst_comp, diff_comp in zip( img_ref, img_tst, diff_im ):
505+
num = np.minimum( ref_comp, tst_comp )
506+
ddr = np.maximum( ref_comp, tst_comp )
507+
diff_comp[ddr>0]+= 1.0-(num[ddr>0]/ddr[ddr>0])
508+
self._jaccards.append( np.sum( num ) / np.sum( ddr ) )
509+
volumes.append( np.sum( ref_comp ) )
510+
511+
self._dices = 2.0*np.array(self._jaccards) / (np.array(self._jaccards) +1.0 )
503512

504513
if self.inputs.weighting != "none":
505-
weights = 1.0 / np.sum( img_ref, axis= 0 )
514+
weights = 1.0 / np.array(volumes)
515+
if self.inputs.weighting == "squared_vol":
516+
weights = weights**2
517+
518+
weights = weights / np.sum( weights )
506519

507-
if self.inputs.weighting == "squared_vol":
508-
weights = weights**2
520+
setattr( self, '_jaccard', np.sum( weights * self._jaccards ) )
521+
setattr( self, '_dice', np.sum( weights * self._dices ) )
509522

510-
setattr( self, '_jaccard', np.sum( weights * jaccards ) / np.sum( weights ) )
511-
setattr( self, '_dice', np.sum( weights * dices ) / np.sum( weights ) )
523+
524+
diff = np.zeros( diff_im[0].shape )
525+
526+
for w,ch in zip(weights,diff_im):
527+
ch[msk==0] = 0
528+
diff+= w* ch
512529

513-
# todo, this is a N+1 dimensional file, update header and affine.
514-
nb.save(nb.Nifti1Image(both_data, nii1.get_affine(),
515-
nii1.get_header()), self.inputs.out_file)
530+
nb.save(nb.Nifti1Image(diff, nb.load( self.inputs.in_ref[0]).get_affine(),
531+
nb.load( self.inputs.in_ref[0]).get_header()), self.inputs.out_file )
516532

533+
517534
return runtime
518535

519536
def _list_outputs(self):
@@ -522,6 +539,8 @@ def _list_outputs(self):
522539
outputs[method] = getattr(self, '_' + method)
523540
#outputs['volume_difference'] = self._volume
524541
outputs['diff_file'] = os.path.abspath(self.inputs.out_file)
542+
outputs['class_ji'] = np.array(self._jaccards).astype(float).tolist();
543+
outputs['class_dsc']= self._dices.astype(float).tolist();
525544
return outputs
526545

527546

0 commit comments

Comments
 (0)