coralnet-toolbox 0.0.68__py2.py3-none-any.whl → 0.0.69__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,8 @@ import warnings
2
2
 
3
3
  import os
4
4
 
5
+ import numpy as np
6
+
5
7
  from PyQt5.QtCore import Qt, QTimer
6
8
  from PyQt5.QtGui import QPen, QColor, QPainter
7
9
  from PyQt5.QtWidgets import QGraphicsEllipseItem, QStyle, QVBoxLayout, QLabel, QWidget, QGraphicsItem
@@ -54,6 +56,12 @@ class EmbeddingPointItem(QGraphicsEllipseItem):
54
56
 
55
57
  # Set the position of the point based on the data item's embedding coordinates
56
58
  self.setPos(self.data_item.embedding_x, self.data_item.embedding_y)
59
+ # Set the tooltip with detailed information
60
+ self.setToolTip(self.data_item.get_tooltip_text())
61
+
62
+ def update_tooltip(self):
63
+ """Updates the tooltip by fetching the latest text from the data item."""
64
+ self.setToolTip(self.data_item.get_tooltip_text())
57
65
 
58
66
  def paint(self, painter, option, widget):
59
67
  """
@@ -104,6 +112,10 @@ class AnnotationImageWidget(QWidget):
104
112
  self.image_label.setScaledContents(True)
105
113
  self.image_label.setStyleSheet("border: none;")
106
114
  layout.addWidget(self.image_label)
115
+
116
+ def update_tooltip(self):
117
+ """Updates the tooltip by fetching the latest text from the data item."""
118
+ self.setToolTip(self.data_item.get_tooltip_text())
107
119
 
108
120
  def load_and_set_image(self):
109
121
  """Load image, calculate its aspect ratio, and set the widget's initial size."""
@@ -124,7 +136,10 @@ class AnnotationImageWidget(QWidget):
124
136
  self.image_label.setText("Error\nLoading Image")
125
137
  self.pixmap = None
126
138
  self.aspect_ratio = 1.0
139
+
127
140
  self.update_height(self.widget_height)
141
+ # Set the initial tooltip
142
+ self.update_tooltip()
128
143
 
129
144
  def update_height(self, new_height):
130
145
  """Updates the widget's height and rescales its width and content accordingly."""
@@ -204,8 +219,12 @@ class AnnotationImageWidget(QWidget):
204
219
  # The viewer is the controller and will decide how to change the selection state
205
220
  self.annotation_viewer.handle_annotation_selection(self, event)
206
221
  elif event.button() == Qt.RightButton:
207
- event.ignore()
208
- return
222
+ if self.annotation_viewer and hasattr(self.annotation_viewer, 'handle_annotation_context_menu'):
223
+ self.annotation_viewer.handle_annotation_context_menu(self, event)
224
+ event.accept()
225
+ return
226
+ else:
227
+ event.ignore()
209
228
  super().mousePressEvent(event)
210
229
 
211
230
 
@@ -218,14 +237,20 @@ class AnnotationDataItem:
218
237
 
219
238
  def __init__(self, annotation, embedding_x=None, embedding_y=None, embedding_id=None):
220
239
  self.annotation = annotation
240
+
221
241
  self.embedding_x = embedding_x if embedding_x is not None else 0.0
222
242
  self.embedding_y = embedding_y if embedding_y is not None else 0.0
223
243
  self.embedding_id = embedding_id if embedding_id is not None else 0
244
+
224
245
  self._is_selected = False
225
246
  self._preview_label = None
226
247
  self._original_label = annotation.label
227
- self._marked_for_deletion = False
228
-
248
+
249
+ # To store pre-formatted top-k prediction details
250
+ self.prediction_details = None
251
+ # To store prediction probabilities for sorting
252
+ self.prediction_probabilities = None
253
+
229
254
  @property
230
255
  def effective_label(self):
231
256
  """Get the current effective label (preview if it exists, otherwise original)."""
@@ -257,18 +282,6 @@ class AnnotationDataItem:
257
282
  """Check if this annotation has a temporary preview label assigned."""
258
283
  return self._preview_label is not None
259
284
 
260
- def mark_for_deletion(self):
261
- """Mark this annotation for deletion."""
262
- self._marked_for_deletion = True
263
-
264
- def unmark_for_deletion(self):
265
- """Unmark this annotation for deletion."""
266
- self._marked_for_deletion = False
267
-
268
- def is_marked_for_deletion(self):
269
- """Check if this annotation is marked for deletion."""
270
- return self._marked_for_deletion
271
-
272
285
  def apply_preview_permanently(self):
273
286
  """Apply the preview label permanently to the underlying annotation object."""
274
287
  if self._preview_label:
@@ -290,9 +303,35 @@ class AnnotationDataItem:
290
303
  'embedding_id': self.embedding_id,
291
304
  'color': self.effective_color
292
305
  }
306
+
307
+ def get_tooltip_text(self):
308
+ """
309
+ Generates a rich HTML-formatted tooltip with all relevant information.
310
+ """
311
+ info = self.get_display_info()
312
+
313
+ tooltip_parts = [
314
+ f"<b>ID:</b> {info['id']}",
315
+ f"<b>Image:</b> {info['image']}",
316
+ f"<b>Label:</b> {info['label']}",
317
+ f"<b>Type:</b> {info['type']}"
318
+ ]
319
+
320
+ # Add prediction details if they exist
321
+ if self.prediction_details:
322
+ tooltip_parts.append(f"<hr>{self.prediction_details}")
323
+
324
+ return "<br>".join(tooltip_parts)
293
325
 
294
326
  def get_effective_confidence(self):
295
327
  """Get the effective confidence value."""
328
+ # First check if prediction probabilities are available from model predictions
329
+ if hasattr(self, 'prediction_probabilities') and self.prediction_probabilities is not None:
330
+ if len(self.prediction_probabilities) > 0:
331
+ # Use the maximum probability for confidence sorting
332
+ return float(np.max(self.prediction_probabilities))
333
+
334
+ # Fallback to existing confidence values
296
335
  if self.annotation.verified and hasattr(self.annotation, 'user_confidence') and self.annotation.user_confidence:
297
336
  return list(self.annotation.user_confidence.values())[0]
298
337
  elif hasattr(self.annotation, 'machine_confidence') and self.annotation.machine_confidence: