From 54db932c9f965182442a09d5d63468ad96fbd65f Mon Sep 17 00:00:00 2001 From: neuronflow Date: Wed, 15 Nov 2023 23:11:48 +0100 Subject: [PATCH] new: assd renaming Signed-off-by: neuronflow --- panoptica/result.py | 47 +++++++++++++++++++-------- unit_tests/test_panoptic_evaluator.py | 15 ++++----- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/panoptica/result.py b/panoptica/result.py index 23825ef..caf38c4 100644 --- a/panoptica/result.py +++ b/panoptica/result.py @@ -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): @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/unit_tests/test_panoptic_evaluator.py b/unit_tests/test_panoptic_evaluator.py index b183a3c..3992880 100644 --- a/unit_tests/test_panoptic_evaluator.py +++ b/unit_tests/test_panoptic_evaluator.py @@ -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): @@ -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) @@ -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) @@ -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))