Skip to content

Commit

Permalink
Merge pull request #52 from BrainLesion/38-rename-to-sq_assd
Browse files Browse the repository at this point in the history
new: assd renaming
  • Loading branch information
neuronflow authored Nov 15, 2023
2 parents 58a4e7f + 54db932 commit 520937a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 22 deletions.
47 changes: 33 additions & 14 deletions panoptica/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __str__(self):
f"Panoptic Quality (PQ): {self.pq}\n"
f"DSC-based Segmentation Quality (DQ_DSC): {self.sq_dsc} ± {self.sq_dsc_sd}\n"
f"DSC-based Panoptic Quality (PQ_DSC): {self.pq_dsc}\n"
f"Average symmetric surface distance (ASSD): {self.instance_assd} ± {self.instance_assd_sd}"
f"Average symmetric surface distance (ASSD): {self.sq_assd} ± {self.sq_assd_sd}"
)

def to_dict(self):
Expand All @@ -71,8 +71,8 @@ def to_dict(self):
"sq_dsc": self.sq_dsc,
"sq_dsc_sd": self.sq_dsc_sd,
"pq_dsc": self.pq_dsc,
"assd": self.instance_assd,
"assd_sd": self.instance_assd_sd,
"sq_assd": self.sq_assd,
"sq_assd_sd": self.sq_assd_sd,
}

@property
Expand Down Expand Up @@ -134,7 +134,9 @@ def rq(self) -> float:
float: Recognition Quality (RQ).
"""
if self.tp == 0:
return 0.0 if self.num_pred_instances + self.num_ref_instances > 0 else np.nan
return (
0.0 if self.num_pred_instances + self.num_ref_instances > 0 else np.nan
)
return self.tp / (self.tp + 0.5 * self.fp + 0.5 * self.fn)

@property
Expand All @@ -146,7 +148,9 @@ def sq(self) -> float:
float: Segmentation Quality (SQ).
"""
if self.tp == 0:
return 0.0 if self.num_pred_instances + self.num_ref_instances > 0 else np.nan
return (
0.0 if self.num_pred_instances + self.num_ref_instances > 0 else np.nan
)
return np.sum(self._iou_list) / self.tp

@property
Expand Down Expand Up @@ -178,7 +182,9 @@ def sq_dsc(self) -> float:
float: Average Dice coefficient.
"""
if self.tp == 0:
return 0.0 if self.num_pred_instances + self.num_ref_instances > 0 else np.nan
return (
0.0 if self.num_pred_instances + self.num_ref_instances > 0 else np.nan
)
return np.sum(self._dice_list) / self.tp

@property
Expand All @@ -202,23 +208,36 @@ def pq_dsc(self) -> float:
return self.sq_dsc * self.rq

@property
def instance_assd(self) -> float:
def sq_assd(self) -> float:
"""
Get the average symmetric surface distance averaged over instances
Calculate the average average symmetric surface distance (ASSD) for matched instances. Analogue to segmentation quality but based on ASSD.
Returns:
float: average symmetric surface distance.
float: average symmetric surface distance. (ASSD)
"""
if self.tp == 0:
return np.nan if self.num_pred_instances + self.num_ref_instances == 0 else np.inf
return (
np.nan
if self.num_pred_instances + self.num_ref_instances == 0
else np.inf
)
return np.sum(self._assd_list) / self.tp

@property
def instance_assd_sd(self) -> float:
def sq_assd_sd(self) -> float:
"""
Get the standard deviation of all assd calculations
Calculate the standard deviation of average symmetric surface distance (ASSD) for matched instances. Analogue to segmentation quality but based on ASSD.
Returns:
float: std of average symmetric surface distance.
float: Standard deviation of average symmetric surface distance (ASSD).
"""
return np.std(self._assd_list) if len(self._assd_list) > 0 else np.nan

@property
def pq_assd(self) -> float:
"""
Calculate the Panoptic Quality (PQ) based on ASSD-based SQ and RQ.
Returns:
float: Panoptic Quality (PQ).
"""
return self.sq_assd * self.rq
15 changes: 7 additions & 8 deletions unit_tests/test_panoptic_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
# coverage html
import unittest

from panoptica.instance_approximator import ConnectedComponentsInstanceApproximator, CCABackend
from panoptica.instance_matcher import NaiveThresholdMatching
from panoptica.instance_evaluator import evaluate_matched_instance
import numpy as np
from panoptica.result import PanopticaResult
from panoptica.utils.datatypes import SemanticPair, UnmatchedInstancePair, MatchedInstancePair, _ProcessingPair

from panoptica.evaluator import Panoptic_Evaluator
from panoptica.instance_approximator import ConnectedComponentsInstanceApproximator
from panoptica.instance_matcher import NaiveThresholdMatching
from panoptica.utils.datatypes import SemanticPair


class Test_Panoptic_Evaluator(unittest.TestCase):
Expand Down Expand Up @@ -56,7 +55,7 @@ def test_pred_empty(self):
self.assertEqual(result.fn, 1)
self.assertEqual(result.sq, 0.0)
self.assertEqual(result.pq, 0.0)
self.assertEqual(result.instance_assd, np.inf)
self.assertEqual(result.sq_assd, np.inf)

def test_ref_empty(self):
a = np.zeros([50, 50], np.uint16)
Expand All @@ -79,7 +78,7 @@ def test_ref_empty(self):
self.assertEqual(result.fn, 0)
self.assertEqual(result.sq, 0.0)
self.assertEqual(result.pq, 0.0)
self.assertEqual(result.instance_assd, np.inf)
self.assertEqual(result.sq_assd, np.inf)

def test_both_empty(self):
a = np.zeros([50, 50], np.uint16)
Expand All @@ -102,4 +101,4 @@ def test_both_empty(self):
self.assertEqual(result.fn, 0)
self.assertTrue(np.isnan(result.sq))
self.assertTrue(np.isnan(result.pq))
self.assertTrue(np.isnan(result.instance_assd))
self.assertTrue(np.isnan(result.sq_assd))

0 comments on commit 520937a

Please sign in to comment.