Skip to content

Commit 4353b25

Browse files
committed
fix: calculation of determination score
1 parent bddcbde commit 4353b25

File tree

3 files changed

+20
-18
lines changed

3 files changed

+20
-18
lines changed

ami/main/management/commands/import_taxa.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ def create_taxon(self, taxon_data: dict, root_taxon_parent: Taxon) -> tuple[set[
359359
parent = None
360360
if taxon.parent != parent:
361361
if not created:
362-
logger.warn(f"Changing parent of {taxon} from {taxon.parent} to more specific {parent}")
362+
logger.warning(f"Changing parent of {taxon} from {taxon.parent} to more specific {parent}")
363363
taxon.parent = parent
364364
taxon.save(update_calculated_fields=False)
365365
if not created:

ami/main/models.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,9 @@ def get_best_prediction(self, filters: dict = {}) -> Classification | None:
24882488
# If no terminal classification exists, fall back to non-terminal
24892489
return all_classifications.filter(terminal=False).order_by("-score").first()
24902490

2491+
def get_best_ood_prediction(self) -> Classification | None:
2492+
return self.get_best_prediction(filters={"ood_score__isnull": False})
2493+
24912494
def get_best_identification(self) -> Identification | None:
24922495
"""
24932496
The most recent human identification is used as the best identification.
@@ -2500,13 +2503,11 @@ def get_determination_score(self, prediction: Classification | None = None) -> f
25002503
"""
25012504
Always return a score from an algorithm, even if a human has identified the occurrence.
25022505
"""
2503-
if not self.determination:
2504-
return None
25052506
best_prediction = prediction or self.get_best_prediction()
2506-
if best_prediction:
2507-
return best_prediction.score
2508-
else:
2507+
if not best_prediction:
25092508
return None
2509+
else:
2510+
return best_prediction.score
25102511

25112512
def get_determination_ood_score(self, prediction: Classification | None = None) -> float | None:
25122513
"""
@@ -2517,16 +2518,16 @@ def get_determination_ood_score(self, prediction: Classification | None = None)
25172518
"""
25182519
# Get the best prediction that has an OOD score
25192520
# this should be the last classification before the clustering algorithm
2520-
# @TODO copy the OOD score from the best classification to the clustering classification during clustering
2521-
best_prediction = prediction or self.get_best_prediction(filters={"ood_score__isnull": False})
2521+
best_prediction = prediction or self.get_best_ood_prediction()
25222522
if not best_prediction:
25232523
return None
2524-
mean_ood_score = Classification.objects.filter(
2525-
detection__occurrence=self,
2526-
ood_score__isnull=False,
2527-
algorithm=best_prediction.algorithm,
2528-
).aggregate(models.Avg("ood_score"),)["ood_score__avg"]
2529-
return mean_ood_score
2524+
else:
2525+
mean_ood_score = Classification.objects.filter(
2526+
detection__occurrence=self,
2527+
ood_score__isnull=False,
2528+
algorithm=best_prediction.algorithm,
2529+
).aggregate(models.Avg("ood_score"),)["ood_score__avg"]
2530+
return mean_ood_score
25302531

25312532
def context_url(self):
25322533
detection = self.best_detection
@@ -2583,7 +2584,8 @@ def update_occurrence_determination(
25832584

25842585
# Collect all necessary values first
25852586
best_identification = occurrence.get_best_identification()
2586-
best_prediction = occurrence.get_best_prediction() if not best_identification else None
2587+
best_prediction = occurrence.get_best_prediction()
2588+
best_ood_prediction = occurrence.get_best_ood_prediction()
25872589

25882590
# Best detection is used as the representative image for the occurrence in either case
25892591
best_detection = occurrence.get_best_detection()
@@ -2598,8 +2600,8 @@ def update_occurrence_determination(
25982600
new_determination = best_prediction.taxon
25992601

26002602
# Update scores, which may or may not come from the same source as the determination
2601-
new_determination_score = occurrence.get_determination_score()
2602-
new_determination_ood_score = occurrence.get_determination_ood_score()
2603+
new_determination_score = occurrence.get_determination_score(prediction=best_prediction)
2604+
new_determination_ood_score = occurrence.get_determination_ood_score(prediction=best_ood_prediction)
26032605

26042606
# Prepare fields that need to be updated (using a dictionary for bulk update)
26052607
update_fields = {}

ami/main/tests/test_occurrence_determination.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def test_update_with_identification(self):
9696

9797
# Check that the determination is set to the identification's taxon
9898
self.assertEqual(self.occurrence.determination, self.taxon2)
99-
self.assertEqual(self.occurrence.determination_score, 1.0) # Human identifications have score 1.0
99+
self.assertEqual(self.occurrence.determination_score, None) # Human identifications have no score
100100
self.assertEqual(self.occurrence.best_identification, identification)
101101

102102
def test_identification_overrides_classification(self):

0 commit comments

Comments
 (0)