coralnet-toolbox 0.0.72__py2.py3-none-any.whl → 0.0.73__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.
Files changed (35) hide show
  1. coralnet_toolbox/AutoDistill/QtDeployModel.py +23 -12
  2. coralnet_toolbox/Explorer/QtDataItem.py +1 -1
  3. coralnet_toolbox/Explorer/QtExplorer.py +143 -3
  4. coralnet_toolbox/Explorer/QtSettingsWidgets.py +46 -4
  5. coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py +22 -11
  6. coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py +22 -10
  7. coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +61 -24
  8. coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py +5 -1
  9. coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py +19 -6
  10. coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py +21 -8
  11. coralnet_toolbox/QtAnnotationWindow.py +42 -14
  12. coralnet_toolbox/QtEventFilter.py +8 -2
  13. coralnet_toolbox/QtImageWindow.py +17 -18
  14. coralnet_toolbox/QtLabelWindow.py +1 -1
  15. coralnet_toolbox/QtMainWindow.py +143 -8
  16. coralnet_toolbox/Rasters/QtRaster.py +59 -7
  17. coralnet_toolbox/Rasters/RasterTableModel.py +34 -6
  18. coralnet_toolbox/SAM/QtBatchInference.py +0 -2
  19. coralnet_toolbox/SAM/QtDeployGenerator.py +22 -11
  20. coralnet_toolbox/SeeAnything/QtBatchInference.py +19 -221
  21. coralnet_toolbox/SeeAnything/QtDeployGenerator.py +1016 -0
  22. coralnet_toolbox/SeeAnything/QtDeployPredictor.py +69 -53
  23. coralnet_toolbox/SeeAnything/QtTrainModel.py +115 -45
  24. coralnet_toolbox/SeeAnything/__init__.py +2 -0
  25. coralnet_toolbox/Tools/QtSAMTool.py +150 -7
  26. coralnet_toolbox/Tools/QtSeeAnythingTool.py +220 -55
  27. coralnet_toolbox/Tools/QtSelectSubTool.py +6 -4
  28. coralnet_toolbox/Tools/QtWorkAreaTool.py +25 -13
  29. coralnet_toolbox/__init__.py +1 -1
  30. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/METADATA +1 -1
  31. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/RECORD +35 -34
  32. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/WHEEL +0 -0
  33. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/entry_points.txt +0 -0
  34. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/licenses/LICENSE.txt +0 -0
  35. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/top_level.txt +0 -0
@@ -71,9 +71,17 @@ class SeeAnythingTool(Tool):
71
71
  self.current_rect_graphics = None # For the rectangle currently being drawn
72
72
  self.rectangles_processed = False # Track if rectangles have been processed
73
73
 
74
+ # Add state variables for custom working area creation
75
+ self.creating_working_area = False
76
+ self.working_area_start = None
77
+ self.working_area_temp_graphics = None
78
+
79
+ # Add hover position tracking
80
+ self.hover_pos = None
81
+
74
82
  self.annotations = []
75
83
  self.results = None
76
-
84
+
77
85
  def activate(self):
78
86
  """
79
87
  Activates the tool.
@@ -98,6 +106,9 @@ class SeeAnythingTool(Tool):
98
106
 
99
107
  # Clean up working area and shadow
100
108
  self.cancel_working_area()
109
+
110
+ # Cancel working area creation if in progress
111
+ self.cancel_working_area_creation()
101
112
 
102
113
  # Clear detection data
103
114
  self.results = None
@@ -165,6 +176,117 @@ class SeeAnythingTool(Tool):
165
176
 
166
177
  self.annotation_window.setCursor(Qt.CrossCursor)
167
178
  self.annotation_window.scene.update()
179
+
180
+ def set_custom_working_area(self, start_point, end_point):
181
+ """
182
+ Create a working area from custom points selected by the user.
183
+
184
+ Args:
185
+ start_point (QPointF): First corner of the working area
186
+ end_point (QPointF): Opposite corner of the working area
187
+ """
188
+ self.annotation_window.setCursor(Qt.WaitCursor)
189
+
190
+ # Cancel any existing working area
191
+ self.cancel_working_area()
192
+
193
+ # Calculate the rectangle bounds
194
+ left = max(0, int(min(start_point.x(), end_point.x())))
195
+ top = max(0, int(min(start_point.y(), end_point.y())))
196
+ right = min(int(self.annotation_window.pixmap_image.size().width()),
197
+ int(max(start_point.x(), end_point.x())))
198
+ bottom = min(int(self.annotation_window.pixmap_image.size().height()),
199
+ int(max(start_point.y(), end_point.y())))
200
+
201
+ # Ensure minimum size (at least 10x10 pixels)
202
+ if right - left < 10:
203
+ right = min(left + 10, int(self.annotation_window.pixmap_image.size().width()))
204
+ if bottom - top < 10:
205
+ bottom = min(top + 10, int(self.annotation_window.pixmap_image.size().height()))
206
+
207
+ # Original image information
208
+ self.image_path = self.annotation_window.current_image_path
209
+ self.original_image = pixmap_to_numpy(self.annotation_window.pixmap_image)
210
+ self.original_width = self.annotation_window.pixmap_image.size().width()
211
+ self.original_height = self.annotation_window.pixmap_image.size().height()
212
+
213
+ # Create the WorkArea instance
214
+ self.working_area = WorkArea(left, top, right - left, bottom - top, self.image_path)
215
+
216
+ # Get the thickness for the working area graphics
217
+ pen_width = self.graphics_utility.get_workarea_thickness(self.annotation_window)
218
+
219
+ # Create and add the working area graphics
220
+ self.working_area.create_graphics(self.annotation_window.scene, pen_width)
221
+ self.working_area.set_remove_button_visibility(False)
222
+ self.working_area.removed.connect(self.on_working_area_removed)
223
+
224
+ # Create shadow overlay
225
+ shadow_brush = QBrush(QColor(0, 0, 0, 150))
226
+ shadow_path = QPainterPath()
227
+ shadow_path.addRect(self.annotation_window.scene.sceneRect())
228
+ shadow_path.addRect(self.working_area.rect)
229
+ shadow_path = shadow_path.simplified()
230
+
231
+ self.shadow_area = QGraphicsPathItem(shadow_path)
232
+ self.shadow_area.setBrush(shadow_brush)
233
+ self.shadow_area.setPen(QPen(Qt.NoPen))
234
+ self.annotation_window.scene.addItem(self.shadow_area)
235
+
236
+ # Crop the image based on the working area
237
+ self.work_area_image = self.original_image[top:bottom, left:right]
238
+
239
+ # Set the image in the SeeAnything dialog
240
+ self.see_anything_dialog.set_image(self.work_area_image, self.image_path)
241
+
242
+ self.annotation_window.setCursor(Qt.CrossCursor)
243
+ self.annotation_window.scene.update()
244
+
245
+ def display_working_area_preview(self, current_pos):
246
+ """
247
+ Display a preview rectangle for the working area being created.
248
+
249
+ Args:
250
+ current_pos (QPointF): Current mouse position
251
+ """
252
+ if not self.working_area_start:
253
+ return
254
+
255
+ # Remove previous preview if it exists
256
+ if self.working_area_temp_graphics:
257
+ self.annotation_window.scene.removeItem(self.working_area_temp_graphics)
258
+ self.working_area_temp_graphics = None
259
+
260
+ # Create preview rectangle
261
+ rect = QRectF(
262
+ min(self.working_area_start.x(), current_pos.x()),
263
+ min(self.working_area_start.y(), current_pos.y()),
264
+ abs(current_pos.x() - self.working_area_start.x()),
265
+ abs(current_pos.y() - self.working_area_start.y())
266
+ )
267
+
268
+ # Create a dashed blue pen for the working area preview
269
+ pen = QPen(QColor(0, 120, 215))
270
+ pen.setStyle(Qt.DashLine)
271
+ pen.setWidth(2)
272
+
273
+ self.working_area_temp_graphics = QGraphicsRectItem(rect)
274
+ self.working_area_temp_graphics.setPen(pen)
275
+ self.working_area_temp_graphics.setBrush(QBrush(QColor(0, 120, 215, 30))) # Light blue transparent fill
276
+ self.annotation_window.scene.addItem(self.working_area_temp_graphics)
277
+
278
+ def cancel_working_area_creation(self):
279
+ """
280
+ Cancel the process of creating a working area.
281
+ """
282
+ self.creating_working_area = False
283
+ self.working_area_start = None
284
+
285
+ if self.working_area_temp_graphics:
286
+ self.annotation_window.scene.removeItem(self.working_area_temp_graphics)
287
+ self.working_area_temp_graphics = None
288
+
289
+ self.annotation_window.scene.update()
168
290
 
169
291
  def on_working_area_removed(self, work_area):
170
292
  """
@@ -277,12 +399,25 @@ class SeeAnythingTool(Tool):
277
399
  "A label must be selected before adding an annotation.")
278
400
  return None
279
401
 
402
+ # Get position in scene coordinates
403
+ scene_pos = self.annotation_window.mapToScene(event.pos())
404
+
405
+ # Handle working area creation mode
406
+ if not self.working_area and event.button() == Qt.LeftButton:
407
+ if not self.creating_working_area:
408
+ # Start working area creation
409
+ self.creating_working_area = True
410
+ self.working_area_start = scene_pos
411
+ return
412
+ elif self.creating_working_area and self.working_area_start:
413
+ # Finish working area creation
414
+ self.set_custom_working_area(self.working_area_start, scene_pos)
415
+ self.cancel_working_area_creation()
416
+ return
417
+
280
418
  if not self.working_area:
281
419
  return
282
420
 
283
- # Position in the scene
284
- scene_pos = self.annotation_window.mapToScene(event.pos())
285
-
286
421
  # Check if the position is within the working area
287
422
  if not self.working_area.contains_point(scene_pos):
288
423
  return
@@ -319,6 +454,14 @@ class SeeAnythingTool(Tool):
319
454
  Args:
320
455
  event (QMouseEvent): The mouse move event.
321
456
  """
457
+ scene_pos = self.annotation_window.mapToScene(event.pos())
458
+ self.hover_pos = scene_pos
459
+
460
+ # Update working area preview during creation
461
+ if self.creating_working_area and self.working_area_start:
462
+ self.display_working_area_preview(scene_pos)
463
+ return
464
+
322
465
  if self.working_area and self.drawing_rectangle:
323
466
  # Update the end point while drawing the rectangle
324
467
  self.end_point = self.annotation_window.mapToScene(event.pos())
@@ -334,6 +477,12 @@ class SeeAnythingTool(Tool):
334
477
  event (QKeyEvent): The key press event
335
478
  """
336
479
  if event.key() == Qt.Key_Space:
480
+ # If creating working area, confirm it
481
+ if self.creating_working_area and self.working_area_start and self.hover_pos:
482
+ self.set_custom_working_area(self.working_area_start, self.hover_pos)
483
+ self.cancel_working_area_creation()
484
+ return
485
+
337
486
  # If there is no working area, set it
338
487
  if not self.working_area:
339
488
  self.set_working_area()
@@ -359,6 +508,11 @@ class SeeAnythingTool(Tool):
359
508
  self.cancel_working_area()
360
509
 
361
510
  elif event.key() == Qt.Key_Backspace:
511
+ # If creating working area, cancel it
512
+ if self.creating_working_area:
513
+ self.cancel_working_area_creation()
514
+ return
515
+
362
516
  # Cancel current rectangle being drawn
363
517
  if self.drawing_rectangle:
364
518
  self.drawing_rectangle = False
@@ -398,8 +552,16 @@ class SeeAnythingTool(Tool):
398
552
  # Move the points back to the original image space
399
553
  working_area_top_left = self.working_area.rect.topLeft()
400
554
 
401
- # Predict the mask provided prompts (using only the current user-drawn rectangles)
402
- results = self.see_anything_dialog.predict_from_prompts(self.rectangles)[0]
555
+ task = self.see_anything_dialog.task_dropdown.currentText()
556
+ masks = None
557
+ if task == 'segment':
558
+ masks = []
559
+ for r in self.rectangles:
560
+ x1, y1, x2, y2 = r
561
+ masks.append(np.array([[x1, y1], [x2, y1], [x2, y2], [x1, y2]]))
562
+
563
+ # Predict from prompts, providing masks if the task is segmentation
564
+ results = self.see_anything_dialog.predict_from_prompts(self.rectangles, masks=masks)[0]
403
565
 
404
566
  if not results:
405
567
  # Make cursor normal
@@ -425,54 +587,58 @@ class SeeAnythingTool(Tool):
425
587
  # Clear previous annotations if any
426
588
  self.clear_annotations()
427
589
 
428
- # Loop through the results from the current prediction
429
- for result in self.results:
430
- # Extract values from result
431
- confidence = result.boxes.conf.item()
432
-
433
- if confidence < self.main_window.get_uncertainty_thresh():
434
- continue
435
-
436
- # Get the bounding box coordinates (x1, y1, x2, y2) in normalized format
437
- box = result.boxes.xyxyn.detach().cpu().numpy().squeeze()
438
-
439
- # Convert from normalized coordinates directly to absolute pixel coordinates in the whole image
440
- box_abs = box.copy() * np.array([self.work_area_image.shape[1],
441
- self.work_area_image.shape[0],
442
- self.work_area_image.shape[1],
443
- self.work_area_image.shape[0]])
444
-
445
- # Add working area offset to get coordinates in the whole image
446
- box_abs[0] += working_area_top_left.x()
447
- box_abs[1] += working_area_top_left.y()
448
- box_abs[2] += working_area_top_left.x()
449
- box_abs[3] += working_area_top_left.y()
450
-
451
- # Check box area relative to **work area view** area
452
- box_area = (box_abs[2] - box_abs[0]) * (box_abs[3] - box_abs[1])
453
-
454
- # self.main_window.get_area_thresh_min()
455
- if box_area < self.main_window.get_area_thresh_min() * image_area:
456
- continue
457
-
458
- if box_area > self.main_window.get_area_thresh_max() * image_area:
459
- continue
460
-
461
- if self.see_anything_dialog.task == "segment":
462
- # Use polygons from result.masks.data.xyn (list of polygons, each Nx2, normalized to crop)
463
- polygon = result.masks.xyn[0] # np.array of polygons, each as Nx2 array
464
-
465
- # Convert normalized polygon points directly to whole image coordinates
466
- polygon[:, 0] = polygon[:, 0] * self.work_area_image.shape[1] + working_area_top_left.x()
467
- polygon[:, 1] = polygon[:, 1] * self.work_area_image.shape[0] + working_area_top_left.y()
468
-
469
- polygon = simplify_polygon(polygon, 0.1)
470
-
471
- # Create the polygon annotation and add it to self.annotations
472
- self.create_polygon_annotation(polygon, confidence)
473
- else:
474
- # Create the rectangle annotation and add it to self.annotations
475
- self.create_rectangle_annotation(box_abs, confidence)
590
+ # Process results based on the task type
591
+ if self.see_anything_dialog.task == "segment":
592
+ if self.results.masks:
593
+ for i, polygon in enumerate(self.results.masks.xyn):
594
+ confidence = self.results.boxes.conf[i].item()
595
+ if confidence < self.main_window.get_uncertainty_thresh():
596
+ continue
597
+
598
+ # Get absolute bounding box for area check (relative to work area)
599
+ box_work_area = self.results.boxes.xyxy[i].detach().cpu().numpy()
600
+ box_area = (box_work_area[2] - box_work_area[0]) * (box_work_area[3] - box_work_area[1])
601
+
602
+ # Area filtering
603
+ min_area = self.main_window.get_area_thresh_min() * image_area
604
+ max_area = self.main_window.get_area_thresh_max() * image_area
605
+ if not (min_area <= box_area <= max_area):
606
+ continue
607
+
608
+ # Convert normalized polygon points to absolute coordinates in the whole image
609
+ polygon_abs = polygon.copy()
610
+ polygon_abs[:, 0] = polygon_abs[:, 0] * self.work_area_image.shape[1] + working_area_top_left.x()
611
+ polygon_abs[:, 1] = polygon_abs[:, 1] * self.work_area_image.shape[0] + working_area_top_left.y()
612
+
613
+ polygon_abs = simplify_polygon(polygon_abs, 0.1)
614
+ self.create_polygon_annotation(polygon_abs, confidence)
615
+
616
+ else: # Task is 'detect'
617
+ if self.results.boxes:
618
+ for i, box_norm in enumerate(self.results.boxes.xyxyn):
619
+ confidence = self.results.boxes.conf[i].item()
620
+ if confidence < self.main_window.get_uncertainty_thresh():
621
+ continue
622
+
623
+ # Convert normalized box to absolute coordinates in the work area
624
+ box_abs_work_area = box_norm.detach().cpu().numpy() * np.array(
625
+ [self.work_area_image.shape[1], self.work_area_image.shape[0],
626
+ self.work_area_image.shape[1], self.work_area_image.shape[0]])
627
+ box_area = (box_abs_work_area[2] - box_abs_work_area[0]) * (box_abs_work_area[3] - box_abs_work_area[1])
628
+
629
+ # Area filtering
630
+ min_area = self.main_window.get_area_thresh_min() * image_area
631
+ max_area = self.main_window.get_area_thresh_max() * image_area
632
+ if not (min_area <= box_area <= max_area):
633
+ continue
634
+
635
+ # Add working area offset to get coordinates in the whole image
636
+ box_abs_full = box_abs_work_area.copy()
637
+ box_abs_full[0] += working_area_top_left.x()
638
+ box_abs_full[1] += working_area_top_left.y()
639
+ box_abs_full[2] += working_area_top_left.x()
640
+ box_abs_full[3] += working_area_top_left.y()
641
+ self.create_rectangle_annotation(box_abs_full, confidence)
476
642
 
477
643
  self.annotation_window.scene.update()
478
644
 
@@ -750,4 +916,3 @@ class SeeAnythingTool(Tool):
750
916
 
751
917
  # Force update to ensure graphics are removed visually
752
918
  self.annotation_window.scene.update()
753
-
@@ -1,5 +1,5 @@
1
1
  from PyQt5.QtCore import Qt, QRectF
2
- from PyQt5.QtGui import QPen, QColor
2
+ from PyQt5.QtGui import QPen, QColor, QBrush
3
3
  from PyQt5.QtWidgets import QGraphicsRectItem
4
4
 
5
5
  from coralnet_toolbox.Tools.QtSubTool import SubTool
@@ -22,15 +22,17 @@ class SelectSubTool(SubTool):
22
22
  super().activate(event)
23
23
  self.selection_start_pos = self.annotation_window.mapToScene(event.pos())
24
24
 
25
- # Create and style the selection rectangle
25
+ # Create and style the selection rectangle (dashed blue, light blue fill)
26
26
  self.selection_rectangle = QGraphicsRectItem()
27
27
  width = self.parent_tool.graphics_utility.get_rectangle_graphic_thickness(self.annotation_window)
28
- pen = QPen(QColor(255, 255, 255), 2, Qt.DashLine)
28
+ pen = QPen(QColor(0, 120, 215))
29
+ pen.setStyle(Qt.DashLine)
29
30
  pen.setWidth(width)
30
31
  self.selection_rectangle.setPen(pen)
32
+ self.selection_rectangle.setBrush(QBrush(QColor(0, 120, 215, 30))) # Light blue transparent fill
31
33
  self.selection_rectangle.setRect(QRectF(self.selection_start_pos, self.selection_start_pos))
32
34
  self.annotation_window.scene.addItem(self.selection_rectangle)
33
-
35
+
34
36
  def deactivate(self):
35
37
  super().deactivate()
36
38
  if self.selection_rectangle:
@@ -1,7 +1,7 @@
1
1
  import warnings
2
2
 
3
- from PyQt5.QtCore import Qt, QPointF, QRectF
4
- from PyQt5.QtGui import QMouseEvent, QPen, QColor
3
+ from PyQt5.QtCore import Qt, QRectF
4
+ from PyQt5.QtGui import QMouseEvent, QPen, QColor, QBrush
5
5
  from PyQt5.QtWidgets import (QGraphicsRectItem, QMessageBox, QGraphicsPixmapItem)
6
6
 
7
7
  from coralnet_toolbox.Tools.QtTool import Tool
@@ -30,8 +30,8 @@ class WorkAreaTool(Tool):
30
30
  self.current_rect = None
31
31
  self.work_areas = [] # List to store WorkArea objects for the current image
32
32
 
33
- # Style settings for drawing the work area rectangle
34
- self.work_area_pen = QPen(QColor(255, 255, 255), 2, Qt.DashLine)
33
+ # Style settings for drawing the work area rectangle - update to use blue dashed line
34
+ self.work_area_pen = QPen(QColor(0, 120, 215), 2, Qt.DashLine)
35
35
 
36
36
  # Track if Ctrl key is pressed
37
37
  self.ctrl_pressed = False
@@ -43,6 +43,9 @@ class WorkAreaTool(Tool):
43
43
  # Track current image path to detect image changes
44
44
  self.current_image_path = None
45
45
 
46
+ # Add hover position tracking for preview
47
+ self.hover_pos = None
48
+
46
49
  def activate(self):
47
50
  """Activate the work area tool and set the appropriate cursor."""
48
51
  self.active = True
@@ -100,10 +103,12 @@ class WorkAreaTool(Tool):
100
103
 
101
104
  def mouseMoveEvent(self, event: QMouseEvent):
102
105
  """Handle mouse move events to update the work area while drawing."""
106
+ scene_pos = self.annotation_window.mapToScene(event.pos())
107
+ self.hover_pos = scene_pos # Track hover position for spacebar confirmation
108
+
103
109
  if not self.drawing or not self.annotation_window.active_image:
104
110
  return
105
111
 
106
- scene_pos = self.annotation_window.mapToScene(event.pos())
107
112
  self.update_drawing(scene_pos)
108
113
 
109
114
  def mouseReleaseEvent(self, event: QMouseEvent):
@@ -116,6 +121,11 @@ class WorkAreaTool(Tool):
116
121
  modifiers = event.modifiers()
117
122
  key = event.key()
118
123
 
124
+ # Confirm current drawing with spacebar
125
+ if key == Qt.Key_Space and self.drawing and self.hover_pos:
126
+ self.finish_drawing(self.hover_pos)
127
+ return
128
+
119
129
  # Ctrl+Alt for temporary work area
120
130
  if (modifiers & Qt.ControlModifier) and (modifiers & Qt.AltModifier):
121
131
  if not self.temporary_work_area:
@@ -139,12 +149,12 @@ class WorkAreaTool(Tool):
139
149
  return
140
150
 
141
151
  # Ctrl+Space to create a work area from current view
142
- if key == Qt.Key_Space and self.annotation_window.active_image:
152
+ if key == Qt.Key_Space and self.annotation_window.active_image and not self.drawing:
143
153
  self.create_work_area_from_current_view()
144
154
  return
145
155
 
146
- # Cancel current drawing (Backspace - without modifiers)
147
- if key == Qt.Key_Backspace and self.drawing and not (modifiers & Qt.ControlModifier):
156
+ # Cancel current drawing (Backspace or Escape - without modifiers)
157
+ if (key == Qt.Key_Backspace or key == Qt.Key_Escape) and self.drawing and not (modifiers & Qt.ControlModifier):
148
158
  self.cancel_drawing()
149
159
  return
150
160
 
@@ -207,12 +217,13 @@ class WorkAreaTool(Tool):
207
217
  # Create an initial rectangle item for visual feedback
208
218
  self.current_rect = QGraphicsRectItem(QRectF(pos.x(), pos.y(), 0, 0))
209
219
 
210
- # Get the width
211
- width = self.graphics_utility.get_rectangle_graphic_thickness(self.annotation_window)
220
+ # Create a dashed blue pen for the working area preview
221
+ pen = QPen(QColor(0, 120, 215))
222
+ pen.setStyle(Qt.DashLine)
223
+ pen.setWidth(2)
212
224
 
213
- # Set the pen properties
214
- self.work_area_pen.setWidth(width)
215
- self.current_rect.setPen(self.work_area_pen)
225
+ self.current_rect.setPen(pen)
226
+ self.current_rect.setBrush(QBrush(QColor(0, 120, 215, 30))) # Light blue transparent fill
216
227
  self.annotation_window.scene.addItem(self.current_rect)
217
228
 
218
229
  def update_drawing(self, pos):
@@ -227,6 +238,7 @@ class WorkAreaTool(Tool):
227
238
  constrained_rect = self.constrain_rect_to_image_bounds(rect)
228
239
 
229
240
  self.current_rect.setRect(constrained_rect)
241
+ self.hover_pos = pos # Update hover position for key events
230
242
 
231
243
  def finish_drawing(self, pos):
232
244
  """Finish drawing the work area and add it to the list."""
@@ -1,6 +1,6 @@
1
1
  """Top-level package for CoralNet-Toolbox."""
2
2
 
3
- __version__ = "0.0.72"
3
+ __version__ = "0.0.73"
4
4
  __author__ = "Jordan Pierce"
5
5
  __email__ = "jordan.pierce@noaa.gov"
6
6
  __credits__ = "National Center for Coastal and Ocean Sciences (NCCOS)"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coralnet-toolbox
3
- Version: 0.0.72
3
+ Version: 0.0.73
4
4
  Summary: Tools for annotating and developing ML models for benthic imagery
5
5
  Author-email: Jordan Pierce <jordan.pierce@noaa.gov>
6
6
  License: MIT License
@@ -1,13 +1,13 @@
1
- coralnet_toolbox/QtAnnotationWindow.py,sha256=ZlaYYAMNqu95SJhduQxH1K0YP7mOkMv3BzGQwemfByg,39518
1
+ coralnet_toolbox/QtAnnotationWindow.py,sha256=WOfi4BhXt3rtH0PnJZ0tDPpjn-wq66n8MoMqKFg-T2M,40727
2
2
  coralnet_toolbox/QtConfidenceWindow.py,sha256=L5hR23uW91GpqnsNS9R1XF3zCTe2aU7w0iDoQMV0oyE,16190
3
- coralnet_toolbox/QtEventFilter.py,sha256=KKC9de3e66PvGVgiML8P7MZ9-r7vvHidPJJYpcbTwyM,6696
4
- coralnet_toolbox/QtImageWindow.py,sha256=vLziMSEWFfVRSBN0nUNkosgk3LiNxZDqPwbinz9ZivQ,49356
5
- coralnet_toolbox/QtLabelWindow.py,sha256=-4GCk4pTY9g4ADH1iE__4xwqT-7UR_7VCT8v-bJzerk,50869
6
- coralnet_toolbox/QtMainWindow.py,sha256=z_Erak0fJC4x962rsFgK3IwjLQYVUe6rayzQzfJtkhw,114372
3
+ coralnet_toolbox/QtEventFilter.py,sha256=KOW8_AdXZJIVsnl7992sacIcexc0QUFlLQ864YIg4e8,7045
4
+ coralnet_toolbox/QtImageWindow.py,sha256=2xQpdrTQE8PfzflOupEi3u65nLAikeMMH3MUkzTQHU4,49296
5
+ coralnet_toolbox/QtLabelWindow.py,sha256=XHRSi_Pp6AFnaaEtf3GNzliNxoO_jmSmEVBqP5lqRsw,50884
6
+ coralnet_toolbox/QtMainWindow.py,sha256=6JxsDeWpPAe3BhIHGwtsfxQegaXhl3NnO4Nws6od92w,123287
7
7
  coralnet_toolbox/QtPatchSampling.py,sha256=Ehj06auBGfQwIruLNYQjF8eFOCpl8G72p42UXXb2mUo,29013
8
8
  coralnet_toolbox/QtProgressBar.py,sha256=pnozUOcVjfO_yTS9z8wOMPcrrrOtG_FeCknTcdI6eyk,6250
9
9
  coralnet_toolbox/QtWorkArea.py,sha256=YXRvHQKpWUtWyv_o9lZ8rmxfm28dUOG9pmMUeimDhQ4,13578
10
- coralnet_toolbox/__init__.py,sha256=-OIPFY1gy8COaSsB29_2bWyVd3ro4BAdKgI2eIvHhPY,207
10
+ coralnet_toolbox/__init__.py,sha256=W4260-tQetcUaQbpJgZ4EkAlh_TbssOeuntEq4jmtSQ,207
11
11
  coralnet_toolbox/main.py,sha256=6j2B_1reC_KDmqvq1C0fB-UeSEm8eeJOozp2f4XXMLQ,1573
12
12
  coralnet_toolbox/utilities.py,sha256=eUkxXuWaNFH83LSW-KniwujkXKJ2rK04czx3k3OPiAY,27115
13
13
  coralnet_toolbox/Annotations/QtAnnotation.py,sha256=-3ASbjl1dXw9U731vyCgwyiyZT9zOD5Mvp1jt-7bCnA,29242
@@ -17,7 +17,7 @@ coralnet_toolbox/Annotations/QtPolygonAnnotation.py,sha256=1EkZEJlO4VZ4so01Sat2T
17
17
  coralnet_toolbox/Annotations/QtRectangleAnnotation.py,sha256=TgeawekA3jNBlCmZBRqXYRHoZqch7pWM-NSBBPG6S60,21404
18
18
  coralnet_toolbox/Annotations/__init__.py,sha256=bpMldC70tT_lzMrOdBNDkEhG9dCX3tXEBd48IrcUg3E,419
19
19
  coralnet_toolbox/AutoDistill/QtBatchInference.py,sha256=k871aW3XRX8kc4BDaS1aipbPh9WOZxgmilF2c4KOdVA,5646
20
- coralnet_toolbox/AutoDistill/QtDeployModel.py,sha256=6alhzvA3KYEeLaQj-Qhs9GicjNQyVoQbnvgZ3lxGnCU,25162
20
+ coralnet_toolbox/AutoDistill/QtDeployModel.py,sha256=Fycm7wuydUfr1E2CUy00ridiI2JaNDZqAeoVB_HVydY,25923
21
21
  coralnet_toolbox/AutoDistill/__init__.py,sha256=-cJSCr3HSVcybbkvdSZY_zz9EDLESq9A3gisHu3gIgM,206
22
22
  coralnet_toolbox/AutoDistill/Models/GroundingDINO.py,sha256=xG20nLOrKjtzRhZznIIdwFXxBJ7RCeQ7h1z0V0J6trE,2781
23
23
  coralnet_toolbox/AutoDistill/Models/OWLViT.py,sha256=disVxSQ80sS4SVYdwrQocFP_LN6YDQQhzfeORWe4veU,2572
@@ -35,10 +35,10 @@ coralnet_toolbox/Common/QtUpdateImagePaths.py,sha256=_hJYx6hXdAOfH_m77f75AQduQ0W
35
35
  coralnet_toolbox/CoralNet/QtAuthenticate.py,sha256=Y__iY0Kcosz6AOV7dlJBwiB6Hte40wHahHe-OmRngZA,13267
36
36
  coralnet_toolbox/CoralNet/QtDownload.py,sha256=HBb8TpZRIEFirGIaIAV1v8qg3fL4cP6Bf-hUiqXoiLE,48516
37
37
  coralnet_toolbox/CoralNet/__init__.py,sha256=ILkAZh6mlAK1UaCCZjCB9JZxd-oY4cIgfnIC8UgjjIU,188
38
- coralnet_toolbox/Explorer/QtDataItem.py,sha256=fNpCHJSxMzHL2XpBXtPwKchSbmY7H0HWzL1Kbs4W1Ts,14920
39
- coralnet_toolbox/Explorer/QtExplorer.py,sha256=vAtGTNsEUcy14-_XJuOocH7xdAlesHm5faN9AINaEvg,131591
38
+ coralnet_toolbox/Explorer/QtDataItem.py,sha256=mRcQ0GlriEjhbFV_khbuFNMEJhIyFxD_uIC5v1L03cw,14885
39
+ coralnet_toolbox/Explorer/QtExplorer.py,sha256=jKybLHk7sD5C2TIzB5OLeSAkhSNKpGOOkvoNvz9M7NY,138362
40
40
  coralnet_toolbox/Explorer/QtFeatureStore.py,sha256=3VwGezs1stmu65Z4ZQpvY27rGEIJq_prERWkFwMATBo,7378
41
- coralnet_toolbox/Explorer/QtSettingsWidgets.py,sha256=unm23yP329cVL84aOvy20DBt3YBHVLU85rnfN9VUF8A,27649
41
+ coralnet_toolbox/Explorer/QtSettingsWidgets.py,sha256=ltdimQHY1igAOh7OP4gFVuM4SyPJKmA-77wiKYBZo5k,29230
42
42
  coralnet_toolbox/Explorer/__init__.py,sha256=wZPhf2oaUUyIQ2WK48Aj-4q1ENIZG2dGl1HF_mjhI6w,116
43
43
  coralnet_toolbox/IO/QtExportAnnotations.py,sha256=xeaS0BukC3cpkBIGT9DXRqHmvHhp-vOU47h6EoANpNg,4474
44
44
  coralnet_toolbox/IO/QtExportCoralNetAnnotations.py,sha256=4royhF63EmeOlSIBX389EUjjvE-SF44_maW6qm52mdA,2778
@@ -126,18 +126,18 @@ coralnet_toolbox/MachineLearning/Community/cfg/segment/yolo11-p2.yaml,sha256=H2P
126
126
  coralnet_toolbox/MachineLearning/Community/cfg/segment/yolo11-p6.yaml,sha256=jg2PDDeIPvBG_QXNOMyro7LYLy0HNZ5F4s7fiAg0xys,3283
127
127
  coralnet_toolbox/MachineLearning/DeployModel/QtBase.py,sha256=ZK2p9euv9AM2hhpAYWyVLcIk_8UwMVgeTAEYQbXWJBw,12609
128
128
  coralnet_toolbox/MachineLearning/DeployModel/QtClassify.py,sha256=4YSEENGY2pZpiFqt1tfr-m1oHhP9V4uID8gdOVkZwwI,6331
129
- coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py,sha256=RL_S88RxX0c7FBSy0Mmzeq7AErIyjRh-k0SjzTcjczU,14930
130
- coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py,sha256=jL2tdLzOixdJ9pwloqJH2Bq6FOew3yg1ebBrLFrr5_Q,14658
129
+ coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py,sha256=Ccocp-ZAZHnqCxsUYeqBcWgTR0LePKquGC83h8FEUSA,15691
130
+ coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py,sha256=uwgqvtcCRUSPiafc6_uNw-LDYioYWJwC95joRYl2Ems,15452
131
131
  coralnet_toolbox/MachineLearning/DeployModel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
132
132
  coralnet_toolbox/MachineLearning/EvaluateModel/QtBase.py,sha256=stOQlB9NP1kZLwfQipA8J8_EzcgKi-9rvxar_AyWwjc,11526
133
133
  coralnet_toolbox/MachineLearning/EvaluateModel/QtClassify.py,sha256=EsUBbSxcoOymO3ezPUI1X0M_g9x7Y2oVU5myflet7pw,2268
134
134
  coralnet_toolbox/MachineLearning/EvaluateModel/QtDetect.py,sha256=i9Xy6564ChWKvHga-VOmzKtbXybt8eq9E8pGgGU69qY,2253
135
135
  coralnet_toolbox/MachineLearning/EvaluateModel/QtSegment.py,sha256=4SYBwo8B83XgYeS29PFB95Lz5xANuBpu-4dWN17jeQA,2250
136
136
  coralnet_toolbox/MachineLearning/EvaluateModel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
- coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py,sha256=-BrgCRYaJvjz0SCIryYsZb-WNneOd99nTAST54toIGo,28046
138
- coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py,sha256=DoZyMxNOmE-wX4qlW1j1EJ2SjIT3X1kk5GIWBnjIRJE,9498
139
- coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py,sha256=b8I8eCbHFo1l0dJEF7Rqy2HCb76uqcb4UjaAXFsrIUY,6085
140
- coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py,sha256=dVMq2S6SHJpV9bi9f6Sp36KKBeTqONYYhpLj8iHjvik,6108
137
+ coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py,sha256=sS5FRSDYzBJOKHcOss3P_gGBKI4ufUDjararVuzhRhQ,29654
138
+ coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py,sha256=5LB8m2zJ24hjcvOL3uorGdqoZf2bpPxqB18THQlkh4Q,9669
139
+ coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py,sha256=ptZ0rUoZ1Tc0RGjKuXU15ZTM87m3gO8vLu6I7w5PVgs,6669
140
+ coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py,sha256=7sDczfciPPbGgMdb6D9pZn27DHs_Spg1bd-bc9_hI7Y,6696
141
141
  coralnet_toolbox/MachineLearning/ExportDataset/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
142
  coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py,sha256=xRYutV3GUHqMLFaw79_x_7ED6el8mzohwDd3L7_h2ao,23950
143
143
  coralnet_toolbox/MachineLearning/ImportDataset/QtDetect.py,sha256=1YQFAgfuPUUZ18fXbvs4GP9Mrp_-9kfeDdmJHEA5e7I,1121
@@ -174,9 +174,9 @@ coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/detection_model.py,sha256
174
174
  coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/load_camera_params.py,sha256=0eduzfUuT_C852D9LWykMN1tGf962lk6Q2qjiJyxcQA,4430
175
175
  coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/run.py,sha256=Aumo6RkwJ1wzAloCuhNjgyFnb4z5YeRlME8N_6IdfCU,23463
176
176
  coralnet_toolbox/Rasters/ImageFilter.py,sha256=EhH1YoVjC29ER4qU4t9xwybeX9E012fLq04iPFfbaz4,7928
177
- coralnet_toolbox/Rasters/QtRaster.py,sha256=acvlWojJctwYuT0rUBmL8gkp5vMdYpofK24suUUVZG0,16201
177
+ coralnet_toolbox/Rasters/QtRaster.py,sha256=qWqhKiZbBnv0JnCQvPXx6fQYENgSA7sp3vBUj4fdnhA,18435
178
178
  coralnet_toolbox/Rasters/RasterManager.py,sha256=GuTeuty3x4k8DWZ34FQ4BTNwRfjWu0lEhv3NfF2t5u4,6534
179
- coralnet_toolbox/Rasters/RasterTableModel.py,sha256=IMZXQMT3XTARuL8o5lKLqEdF059WWhWlg6TaTPSn7Fo,13087
179
+ coralnet_toolbox/Rasters/RasterTableModel.py,sha256=91ZVBbHdrer6EznmtT9fVRsof0nlfmATtLIaTB-DKgA,14531
180
180
  coralnet_toolbox/Rasters/__init__.py,sha256=Pi88uDQbtWxwHfJFdlsvbkwGNhtlyM_013l8bbJlFfw,428
181
181
  coralnet_toolbox/Results/CombineResults.py,sha256=QrHyKhMrjNDtQ98PQabUflHhyv_8KXTGqU30tw9amV8,4523
182
182
  coralnet_toolbox/Results/ConvertResults.py,sha256=uh7tfJxDiH_cJHxWsr8KQQOcsfzC59-k6PQDVtl3ZaY,6015
@@ -184,14 +184,15 @@ coralnet_toolbox/Results/MapResults.py,sha256=sDieekB93RVKvD-9mW1zRsHOs85shYVIQk
184
184
  coralnet_toolbox/Results/Masks.py,sha256=C-zoobRaWXP_QdGcL7ZgSxytHOBdHIBUbQuGnoMZthE,5183
185
185
  coralnet_toolbox/Results/ResultsProcessor.py,sha256=q_UZNYggpZyY4_P6RpDLbY1ygNH49GXlP1s9ZFI3yF0,17261
186
186
  coralnet_toolbox/Results/__init__.py,sha256=WPdlq8aXzjrdQo5T3UqFh7jxge33iNEHiSRAmm0eJuw,630
187
- coralnet_toolbox/SAM/QtBatchInference.py,sha256=zG0vVPBIozZQu043hwjI3_gjlwx-iWeikhu3QxMam4U,6931
188
- coralnet_toolbox/SAM/QtDeployGenerator.py,sha256=CcedOASyV_jLJyqsLRdkeGKBY8Y_AjwWt2-_xgLcdk4,25789
187
+ coralnet_toolbox/SAM/QtBatchInference.py,sha256=UyuYLfPF4JrOmmuMOzshbKDEEribV669d9LURmuu6gg,6866
188
+ coralnet_toolbox/SAM/QtDeployGenerator.py,sha256=1zzzLuN6Dqe0tVoc3KosaFfYh39HeJ1OCOH0GvqRZDg,26550
189
189
  coralnet_toolbox/SAM/QtDeployPredictor.py,sha256=D1DyqjLXQDTNiLp9OVgsiI97fMFftab_goEkQvDH1DU,23516
190
190
  coralnet_toolbox/SAM/__init__.py,sha256=Zxd75pFMrt5DfSmNNVSsQeCucIQ2rVaEiS0hT_OVIMM,293
191
- coralnet_toolbox/SeeAnything/QtBatchInference.py,sha256=1UMogdTWgO3eEwTquJpIYjILUbjkhLEHFDGsHSGzY-I,16200
192
- coralnet_toolbox/SeeAnything/QtDeployPredictor.py,sha256=Op-bK1VNppqGM3uoWH4y54YAfcohnlCEhgPXE5dnw9I,25936
193
- coralnet_toolbox/SeeAnything/QtTrainModel.py,sha256=s4bgraoHIqTtcHdbpMoYoZ9cpHpIP1Nfay1cFQPc3lY,25071
194
- coralnet_toolbox/SeeAnything/__init__.py,sha256=1fVjXVLpQQVw0JLzc6l3HiGVRNa6hztxAMrXc1pFbDI,284
191
+ coralnet_toolbox/SeeAnything/QtBatchInference.py,sha256=k3aftVzva84yATB4Su5DSI0lhkHDggUg3mVAx4AHmjw,7134
192
+ coralnet_toolbox/SeeAnything/QtDeployGenerator.py,sha256=uuJNf_qNXfJ2C5qBYEliOE1z6ZnXCGnVnxmXxUSgeCs,42537
193
+ coralnet_toolbox/SeeAnything/QtDeployPredictor.py,sha256=3lKgtm3Wv0ygFFpiyjhAD8tlxji6P8lNtBN_pJ02zV0,26875
194
+ coralnet_toolbox/SeeAnything/QtTrainModel.py,sha256=dQ6ZkeIr1migU-edGO-gQMENVP4o7WJsIANlSVhFK8k,28031
195
+ coralnet_toolbox/SeeAnything/__init__.py,sha256=4OgG9-aQ6_RZ942-Ift_q-kkp14kObMT4lDIIx9YSxQ,366
195
196
  coralnet_toolbox/Tile/QtTileBatchInference.py,sha256=chSo-TOwpnAgIQpTetZnbhWQIBzbDJO01xAQ3z0-ubk,10730
196
197
  coralnet_toolbox/Tile/QtTileCreation.py,sha256=Cw6q0ZVXx0hU4uMuXA3OZ3_5bKu6oQgnlMFwaXSZbS0,39963
197
198
  coralnet_toolbox/Tile/__init__.py,sha256=BlV-1bO9u-olfNAIvukUMPRzlw8dx-ayjrjMRQ-bSsk,463
@@ -207,18 +208,18 @@ coralnet_toolbox/Tools/QtPatchTool.py,sha256=57vFeR2jQ_VQRlMEIC_mH8NigUqOlVvmhaV
207
208
  coralnet_toolbox/Tools/QtPolygonTool.py,sha256=yxnkwK3rb52pWCq7a3iAABhHUSS_a3vkL7G7Ev0uLDA,9174
208
209
  coralnet_toolbox/Tools/QtRectangleTool.py,sha256=gYOOsn1WRHLG0YzkKmmM7OzLpuLNh8GWIZ4MloXoLDc,7218
209
210
  coralnet_toolbox/Tools/QtResizeSubTool.py,sha256=derPy4adRj758-xYtjL-_35yGBOjoSe_DRE48HpdQpA,5836
210
- coralnet_toolbox/Tools/QtSAMTool.py,sha256=TQ--xcR76lymFS0YVo5Gi4ay_tIsIEecYpLDMRBPLWQ,26174
211
- coralnet_toolbox/Tools/QtSeeAnythingTool.py,sha256=2uxyX_chOIXcmW6oBlb6XlgbRmSwSaQXmkmgOtFrqI4,30606
212
- coralnet_toolbox/Tools/QtSelectSubTool.py,sha256=xKtXYCwezLq3YZQLsSTG3mxs_ZRjLiPrYl-0ebgq-GA,3125
211
+ coralnet_toolbox/Tools/QtSAMTool.py,sha256=8jrHAhumOctmKRpJuw7v54Y6wemXnenRGw-5-F8-Kqg,32571
212
+ coralnet_toolbox/Tools/QtSeeAnythingTool.py,sha256=tIX_D7nOa6wPZeSBQq-qHE2DNKFl5H47wl4H2fHoI5s,38256
213
+ coralnet_toolbox/Tools/QtSelectSubTool.py,sha256=_FIjLhnEVY19Q87jhRKXGdghNfMBxxy_sECAIUo0BZA,3294
213
214
  coralnet_toolbox/Tools/QtSelectTool.py,sha256=rSzM9s7pMxrLqvcWgIcEnpEQhYHU6TbGUna8ZaamakA,19957
214
215
  coralnet_toolbox/Tools/QtSubTool.py,sha256=H25FoFqywdi6Bl35MfpEXGrr48ZTgdRRvHMxUy1tqN4,1601
215
216
  coralnet_toolbox/Tools/QtTool.py,sha256=2MCjT151gYBN8KbsK0GX4WOrEg1uw3oeSkp7Elw1AUA,2531
216
- coralnet_toolbox/Tools/QtWorkAreaTool.py,sha256=-CDrEPenOdSI3sf5wn19Cip4alE1ef7WsRDxQFDkHlc,22162
217
+ coralnet_toolbox/Tools/QtWorkAreaTool.py,sha256=ApsIiEbkyWFWKW6qnFPPnL_Wgs2xa_Edif5kZU5_n8M,22733
217
218
  coralnet_toolbox/Tools/QtZoomTool.py,sha256=F9CAoABv1jxcUS7dyIh1FYjgjOXYRI1xtBPNIR1g62o,4041
218
219
  coralnet_toolbox/Tools/__init__.py,sha256=218iQ8IFXIkKXiUDVYtXk9e08UY9-LhHjcryaJAanQ0,797
219
- coralnet_toolbox-0.0.72.dist-info/licenses/LICENSE.txt,sha256=AURacZ_G_PZKqqPQ9VB9Sqegblk67RNgWSGAYKwXXMY,521
220
- coralnet_toolbox-0.0.72.dist-info/METADATA,sha256=cOB6wtxUBZcPWkW0L9v3LCWIsI_NOaaiKo9RyQJl15M,18152
221
- coralnet_toolbox-0.0.72.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
222
- coralnet_toolbox-0.0.72.dist-info/entry_points.txt,sha256=oEeMoDlJ_2lq95quOeDHIx9hZpubUlSo80OLtgbcrbM,63
223
- coralnet_toolbox-0.0.72.dist-info/top_level.txt,sha256=SMWPh4_9JfB8zVpPOOvjucV2_B_hvWW7bNWmMjG0LsY,17
224
- coralnet_toolbox-0.0.72.dist-info/RECORD,,
220
+ coralnet_toolbox-0.0.73.dist-info/licenses/LICENSE.txt,sha256=AURacZ_G_PZKqqPQ9VB9Sqegblk67RNgWSGAYKwXXMY,521
221
+ coralnet_toolbox-0.0.73.dist-info/METADATA,sha256=X8IhSWb4kRb_cuC9AxyVn7XsOnZXgHB5kRkv2ca91V4,18152
222
+ coralnet_toolbox-0.0.73.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
223
+ coralnet_toolbox-0.0.73.dist-info/entry_points.txt,sha256=oEeMoDlJ_2lq95quOeDHIx9hZpubUlSo80OLtgbcrbM,63
224
+ coralnet_toolbox-0.0.73.dist-info/top_level.txt,sha256=SMWPh4_9JfB8zVpPOOvjucV2_B_hvWW7bNWmMjG0LsY,17
225
+ coralnet_toolbox-0.0.73.dist-info/RECORD,,