coralnet-toolbox 0.0.73__py2.py3-none-any.whl → 0.0.74__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 (41) hide show
  1. coralnet_toolbox/Annotations/QtAnnotation.py +28 -69
  2. coralnet_toolbox/Annotations/QtMaskAnnotation.py +408 -0
  3. coralnet_toolbox/Annotations/QtMultiPolygonAnnotation.py +72 -56
  4. coralnet_toolbox/Annotations/QtPatchAnnotation.py +165 -216
  5. coralnet_toolbox/Annotations/QtPolygonAnnotation.py +497 -353
  6. coralnet_toolbox/Annotations/QtRectangleAnnotation.py +126 -116
  7. coralnet_toolbox/CoralNet/QtDownload.py +2 -1
  8. coralnet_toolbox/Explorer/QtExplorer.py +16 -14
  9. coralnet_toolbox/Explorer/QtSettingsWidgets.py +114 -82
  10. coralnet_toolbox/IO/QtExportTagLabAnnotations.py +30 -10
  11. coralnet_toolbox/IO/QtImportTagLabAnnotations.py +21 -15
  12. coralnet_toolbox/IO/QtOpenProject.py +46 -78
  13. coralnet_toolbox/IO/QtSaveProject.py +18 -43
  14. coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +1 -1
  15. coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py +42 -22
  16. coralnet_toolbox/MachineLearning/VideoInference/QtBase.py +0 -4
  17. coralnet_toolbox/QtEventFilter.py +11 -0
  18. coralnet_toolbox/QtImageWindow.py +117 -68
  19. coralnet_toolbox/QtLabelWindow.py +13 -1
  20. coralnet_toolbox/QtMainWindow.py +5 -27
  21. coralnet_toolbox/QtProgressBar.py +52 -27
  22. coralnet_toolbox/Rasters/RasterTableModel.py +8 -8
  23. coralnet_toolbox/SAM/QtDeployPredictor.py +10 -0
  24. coralnet_toolbox/SeeAnything/QtDeployGenerator.py +779 -161
  25. coralnet_toolbox/SeeAnything/QtDeployPredictor.py +86 -149
  26. coralnet_toolbox/Tools/QtCutSubTool.py +18 -2
  27. coralnet_toolbox/Tools/QtResizeSubTool.py +19 -2
  28. coralnet_toolbox/Tools/QtSAMTool.py +72 -50
  29. coralnet_toolbox/Tools/QtSeeAnythingTool.py +8 -5
  30. coralnet_toolbox/Tools/QtSelectTool.py +27 -3
  31. coralnet_toolbox/Tools/QtSubtractSubTool.py +66 -0
  32. coralnet_toolbox/Tools/__init__.py +2 -0
  33. coralnet_toolbox/__init__.py +1 -1
  34. coralnet_toolbox/utilities.py +137 -47
  35. coralnet_toolbox-0.0.74.dist-info/METADATA +375 -0
  36. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.74.dist-info}/RECORD +40 -38
  37. coralnet_toolbox-0.0.73.dist-info/METADATA +0 -341
  38. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.74.dist-info}/WHEEL +0 -0
  39. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.74.dist-info}/entry_points.txt +0 -0
  40. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.74.dist-info}/licenses/LICENSE.txt +0 -0
  41. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.74.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,6 @@
1
1
  import warnings
2
2
 
3
- import time
4
-
5
- from PyQt5.QtCore import pyqtSignal
3
+ from PyQt5.QtCore import pyqtSignal, QPropertyAnimation, QEventLoop
6
4
  from PyQt5.QtWidgets import QProgressBar, QVBoxLayout, QDialog, QPushButton, QApplication
7
5
 
8
6
  warnings.filterwarnings("ignore", category=DeprecationWarning)
@@ -112,16 +110,35 @@ class ProgressBar(QDialog):
112
110
  def update_progress(self, new_title=None):
113
111
  """
114
112
  Increment the progress by one step.
115
- Updates the UI and checks if progress is complete.
113
+ Updates the UI intermittently to improve performance and checks if progress is complete.
116
114
  """
117
115
  if new_title is not None:
118
116
  self.setWindowTitle(new_title)
119
117
 
120
- if not self.canceled:
121
- self.value += 1
118
+ if self.canceled:
119
+ return
120
+
121
+ self.value += 1
122
+
123
+ # --- Performance Improvement ---
124
+ # To avoid excessive UI repaints that slow down the process, we only update
125
+ # the visual progress bar periodically. This aims for about 100 updates
126
+ # over the entire range, ensuring a smooth look without bogging down the main task.
127
+ # 'max(1, ...)' ensures we always have an interval of at least 1.
128
+ update_interval = max(1, self.max_value // 100)
129
+
130
+ # We update the bar visually only under two conditions:
131
+ # 1. It's the very last step, to ensure it always finishes at 100%.
132
+ # 2. The current value is a multiple of our calculated interval.
133
+ is_last_step = self.value >= self.max_value
134
+ is_update_step = self.value % update_interval == 0
135
+
136
+ if is_update_step or is_last_step:
122
137
  self.progress_bar.setValue(self.value)
123
- if self.value >= self.max_value:
124
- self.stop_progress()
138
+
139
+ # This is crucial. It processes pending events, allowing the GUI to
140
+ # redraw with the new progress value and to respond to user input,
141
+ # like clicking the 'Cancel' button.
125
142
  QApplication.processEvents()
126
143
 
127
144
  def update_progress_percentage(self, percentage):
@@ -141,30 +158,38 @@ class ProgressBar(QDialog):
141
158
 
142
159
  def finish_progress(self, duration_ms=500):
143
160
  """
144
- Animate the progress bar to its maximum value regardless of current value.
145
- This creates a visual effect of the progress bar completing over a short duration.
161
+ Animate the progress bar to its maximum value using a non-blocking animation.
162
+ This creates a smooth visual effect of completion without freezing the UI.
146
163
 
147
164
  Args:
148
165
  duration_ms: The duration in milliseconds for the animation (default: 500)
149
166
  """
150
-
151
- # Calculate the steps and delay
152
- start_value = self.value
153
- steps_needed = self.max_value - start_value
154
- if steps_needed <= 0:
155
- self.progress_bar.setValue(self.max_value)
156
- QApplication.processEvents()
167
+ # If the progress is already complete, just set the final value and exit.
168
+ if self.value >= self.max_value:
169
+ self.stop_progress()
157
170
  return
158
-
159
- # Calculate delay between steps (minimum 1ms)
160
- delay = max(duration_ms / steps_needed / 1000, 0.001)
161
-
162
- # Animate the progress
163
- for current in range(start_value + 1, self.max_value + 1):
164
- self.value = current
165
- self.progress_bar.setValue(current)
166
- QApplication.processEvents()
167
- time.sleep(delay)
171
+
172
+ # --- Non-Blocking Animation using QPropertyAnimation ---
173
+ # QPropertyAnimation is the standard Qt way to animate widget properties.
174
+ # It runs on the main event loop, so it does not freeze the application
175
+ # like the previous time.sleep() implementation. The property name "value"
176
+ # is passed as a bytes object (b"value").
177
+ self.animation = QPropertyAnimation(self.progress_bar, b"value")
178
+ self.animation.setDuration(duration_ms)
179
+ self.animation.setStartValue(self.value)
180
+ self.animation.setEndValue(self.max_value)
181
+ self.animation.start()
182
+
183
+ # We run a local event loop that waits for the animation's 'finished'
184
+ # signal. This ensures that the animation completes visually before
185
+ # this method returns control to the calling code, which is often
186
+ # the desired behavior for a "finishing" step.
187
+ loop = QEventLoop()
188
+ self.animation.finished.connect(loop.quit)
189
+ loop.exec_()
190
+
191
+ # Finally, update our internal state variable to match the final progress.
192
+ self.value = self.max_value
168
193
 
169
194
  def stop_progress(self):
170
195
  """
@@ -20,8 +20,9 @@ class RasterTableModel(QAbstractTableModel):
20
20
  Custom table model for displaying a list of Raster objects.
21
21
  """
22
22
  # Column indices
23
- FILENAME_COL = 0
24
- ANNOTATION_COUNT_COL = 1
23
+ CHECKBOX_COL = 0
24
+ FILENAME_COL = 1
25
+ ANNOTATION_COUNT_COL = 2
25
26
 
26
27
  # Row colors
27
28
  HIGHLIGHTED_COLOR = QColor(173, 216, 230) # Light blue
@@ -39,13 +40,10 @@ class RasterTableModel(QAbstractTableModel):
39
40
  self.raster_manager = raster_manager
40
41
  self.filtered_paths: List[str] = []
41
42
 
42
- # We'll remove this separate tracking mechanism to avoid inconsistency
43
- # self.highlighted_paths: Set[str] = set()
44
-
45
- self.column_headers = ["Image Name", "Annotations"]
43
+ self.column_headers = ["\u2713", "Image Name", "Annotations"]
46
44
 
47
45
  # Column widths
48
- self.column_widths = [-1, 120] # -1 means stretch
46
+ self.column_widths = [30, -1, 120] # -1 means stretch
49
47
 
50
48
  # Connect to manager signals
51
49
  self.raster_manager.rasterAdded.connect(self.on_raster_added)
@@ -82,7 +80,9 @@ class RasterTableModel(QAbstractTableModel):
82
80
  raster.set_display_name(max_length=25)
83
81
 
84
82
  if role == Qt.DisplayRole:
85
- if index.column() == self.FILENAME_COL:
83
+ if index.column() == self.CHECKBOX_COL:
84
+ return "\u2713" if raster.checkbox_state else ""
85
+ elif index.column() == self.FILENAME_COL:
86
86
  return raster.display_name
87
87
  elif index.column() == self.ANNOTATION_COUNT_COL:
88
88
  return str(raster.annotation_count)
@@ -142,6 +142,12 @@ class DeployPredictorDialog(QDialog):
142
142
  """
143
143
  group_box = QGroupBox("Parameters")
144
144
  layout = QFormLayout()
145
+
146
+ # Allow holes dropdown
147
+ self.allow_holes_dropdown = QComboBox()
148
+ self.allow_holes_dropdown.addItems(["True", "False"])
149
+ self.allow_holes_dropdown.setCurrentIndex(1) # Default to False
150
+ layout.addRow("Allow Holes:", self.allow_holes_dropdown)
145
151
 
146
152
  # Resize image dropdown
147
153
  self.resize_image_dropdown = QComboBox()
@@ -236,6 +242,10 @@ class DeployPredictorDialog(QDialog):
236
242
  group_box.setLayout(layout)
237
243
  self.layout.addWidget(group_box)
238
244
 
245
+ def get_allow_holes(self):
246
+ """Return the current setting for allowing holes."""
247
+ return self.allow_holes_dropdown.currentText() == "True"
248
+
239
249
  def initialize_uncertainty_threshold(self):
240
250
  """Initialize the uncertainty threshold slider with the current value"""
241
251
  current_value = self.main_window.get_uncertainty_thresh()