coralnet-toolbox 0.0.73__py2.py3-none-any.whl → 0.0.75__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 (50) 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/QtDataItem.py +52 -22
  9. coralnet_toolbox/Explorer/QtExplorer.py +293 -1614
  10. coralnet_toolbox/Explorer/QtSettingsWidgets.py +203 -85
  11. coralnet_toolbox/Explorer/QtViewers.py +1568 -0
  12. coralnet_toolbox/Explorer/transformer_models.py +59 -0
  13. coralnet_toolbox/Explorer/yolo_models.py +112 -0
  14. coralnet_toolbox/IO/QtExportTagLabAnnotations.py +30 -10
  15. coralnet_toolbox/IO/QtImportTagLabAnnotations.py +21 -15
  16. coralnet_toolbox/IO/QtOpenProject.py +46 -78
  17. coralnet_toolbox/IO/QtSaveProject.py +18 -43
  18. coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +1 -1
  19. coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py +253 -141
  20. coralnet_toolbox/MachineLearning/VideoInference/QtBase.py +0 -4
  21. coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/run.py +102 -16
  22. coralnet_toolbox/QtAnnotationWindow.py +16 -10
  23. coralnet_toolbox/QtEventFilter.py +11 -0
  24. coralnet_toolbox/QtImageWindow.py +120 -75
  25. coralnet_toolbox/QtLabelWindow.py +13 -1
  26. coralnet_toolbox/QtMainWindow.py +5 -27
  27. coralnet_toolbox/QtProgressBar.py +52 -27
  28. coralnet_toolbox/Rasters/RasterTableModel.py +28 -8
  29. coralnet_toolbox/SAM/QtDeployGenerator.py +1 -4
  30. coralnet_toolbox/SAM/QtDeployPredictor.py +11 -3
  31. coralnet_toolbox/SeeAnything/QtDeployGenerator.py +805 -162
  32. coralnet_toolbox/SeeAnything/QtDeployPredictor.py +130 -151
  33. coralnet_toolbox/Tools/QtCutSubTool.py +18 -2
  34. coralnet_toolbox/Tools/QtPolygonTool.py +42 -3
  35. coralnet_toolbox/Tools/QtRectangleTool.py +30 -0
  36. coralnet_toolbox/Tools/QtResizeSubTool.py +19 -2
  37. coralnet_toolbox/Tools/QtSAMTool.py +72 -50
  38. coralnet_toolbox/Tools/QtSeeAnythingTool.py +8 -5
  39. coralnet_toolbox/Tools/QtSelectTool.py +27 -3
  40. coralnet_toolbox/Tools/QtSubtractSubTool.py +66 -0
  41. coralnet_toolbox/Tools/__init__.py +2 -0
  42. coralnet_toolbox/__init__.py +1 -1
  43. coralnet_toolbox/utilities.py +158 -47
  44. coralnet_toolbox-0.0.75.dist-info/METADATA +378 -0
  45. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/RECORD +49 -44
  46. coralnet_toolbox-0.0.73.dist-info/METADATA +0 -341
  47. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/WHEEL +0 -0
  48. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/entry_points.txt +0 -0
  49. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/licenses/LICENSE.txt +0 -0
  50. {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/top_level.txt +0 -0
@@ -7,6 +7,8 @@ from PyQt5.QtWidgets import (QVBoxLayout, QHBoxLayout, QPushButton, QComboBox, Q
7
7
  QLineEdit, QFileDialog, QFormLayout, QSpinBox, QDoubleSpinBox)
8
8
 
9
9
  from coralnet_toolbox.MachineLearning.Community.cfg import get_available_configs
10
+ from coralnet_toolbox.Explorer.transformer_models import TRANSFORMER_MODELS
11
+ from coralnet_toolbox.Explorer.yolo_models import YOLO_MODELS
10
12
 
11
13
  warnings.filterwarnings("ignore", category=DeprecationWarning)
12
14
 
@@ -242,7 +244,7 @@ class AnnotationSettingsWidget(QGroupBox):
242
244
  self.setup_ui()
243
245
 
244
246
  def setup_ui(self):
245
- # The main layout is vertical, to hold the top columns, the stretch, and the bottom buttons
247
+ # The main layout is vertical, to hold the top columns and the bottom buttons
246
248
  layout = QVBoxLayout(self)
247
249
 
248
250
  # A horizontal layout to contain the filter columns
@@ -256,7 +258,7 @@ class AnnotationSettingsWidget(QGroupBox):
256
258
 
257
259
  self.images_list = QListWidget()
258
260
  self.images_list.setSelectionMode(QListWidget.ExtendedSelection)
259
- self.images_list.setMaximumHeight(50)
261
+ self.images_list.setMinimumHeight(100)
260
262
 
261
263
  if hasattr(self.main_window, 'image_window') and hasattr(self.main_window.image_window, 'raster_manager'):
262
264
  for path in self.main_window.image_window.raster_manager.image_paths:
@@ -284,7 +286,7 @@ class AnnotationSettingsWidget(QGroupBox):
284
286
 
285
287
  self.annotation_type_list = QListWidget()
286
288
  self.annotation_type_list.setSelectionMode(QListWidget.ExtendedSelection)
287
- self.annotation_type_list.setMaximumHeight(50)
289
+ self.annotation_type_list.setMinimumHeight(100)
288
290
  self.annotation_type_list.addItems(["PatchAnnotation",
289
291
  "RectangleAnnotation",
290
292
  "PolygonAnnotation",
@@ -312,7 +314,7 @@ class AnnotationSettingsWidget(QGroupBox):
312
314
 
313
315
  self.label_list = QListWidget()
314
316
  self.label_list.setSelectionMode(QListWidget.ExtendedSelection)
315
- self.label_list.setMaximumHeight(50)
317
+ self.label_list.setMinimumHeight(100)
316
318
 
317
319
  if hasattr(self.main_window, 'label_window') and hasattr(self.main_window.label_window, 'labels'):
318
320
  for label in self.main_window.label_window.labels:
@@ -335,9 +337,6 @@ class AnnotationSettingsWidget(QGroupBox):
335
337
  # Add the horizontal layout of columns to the main vertical layout
336
338
  layout.addLayout(conditions_layout)
337
339
 
338
- # Add a stretch item to push the columns to the top
339
- layout.addStretch(1)
340
-
341
340
  # Bottom buttons layout with Apply and Clear buttons on the right
342
341
  bottom_layout = QHBoxLayout()
343
342
  bottom_layout.addStretch() # Push buttons to the right
@@ -350,9 +349,12 @@ class AnnotationSettingsWidget(QGroupBox):
350
349
  self.clear_button.clicked.connect(self.clear_all_conditions)
351
350
  bottom_layout.addWidget(self.clear_button)
352
351
 
353
- # Add the bottom buttons layout to the main layout, keeping it at the bottom
352
+ # Add the bottom buttons layout to the main layout
354
353
  layout.addLayout(bottom_layout)
355
354
 
355
+ # Add a stretch item to push all content to the top
356
+ layout.addStretch(1)
357
+
356
358
  # Set defaults
357
359
  self.set_defaults()
358
360
 
@@ -435,68 +437,111 @@ class AnnotationSettingsWidget(QGroupBox):
435
437
 
436
438
 
437
439
  class ModelSettingsWidget(QGroupBox):
438
- """Widget containing model selection with tabs for different model sources."""
440
+ """Widget containing a structured, hierarchical model selection system."""
439
441
  selection_changed = pyqtSignal()
440
442
 
441
443
  def __init__(self, main_window, parent=None):
442
444
  super(ModelSettingsWidget, self).__init__("Model Settings", parent)
443
445
  self.main_window = main_window
444
446
  self.explorer_window = parent
447
+
448
+ # --- Data for hierarchical selection ---
449
+ # Convert YOLO_MODELS to a hierarchical structure for the UI
450
+ self.standard_models_map = self._create_hierarchical_model_map()
451
+ self.community_configs = get_available_configs(task='classify')
452
+
453
+ # --- Models for feature extraction ---
454
+ self.transformer_models = TRANSFORMER_MODELS
455
+ self.yolo_models = YOLO_MODELS
456
+
445
457
  self.setup_ui()
446
458
 
459
+ def _create_hierarchical_model_map(self):
460
+ """Convert the flat YOLO_MODELS dictionary to a hierarchical structure."""
461
+ hierarchical_map = {}
462
+
463
+ # Process each model in YOLO_MODELS
464
+ for display_name, model_file in YOLO_MODELS.items():
465
+ # Parse the family and size from the display name
466
+ # Expected format: "YOLOvX (Size)"
467
+ parts = display_name.split(' ')
468
+ if len(parts) >= 2:
469
+ family = parts[0] # "YOLOv8", "YOLOv11", etc.
470
+ size = parts[1].strip('()') # "Nano", "Small", etc.
471
+
472
+ # Create the family entry if it doesn't exist
473
+ if family not in hierarchical_map:
474
+ hierarchical_map[family] = {}
475
+
476
+ # Extract the size code from the model filename
477
+ # For example, get 'n' from 'yolov8n-cls.pt'
478
+ if model_file.startswith(family.lower()):
479
+ size_code = model_file[len(family.lower())]
480
+ else:
481
+ # Default fallback if parsing fails
482
+ size_code = size[0].lower()
483
+
484
+ # Add the size entry to the family
485
+ hierarchical_map[family][size] = size_code
486
+
487
+ # If no models were processed, fallback to the default structure
488
+ if not hierarchical_map:
489
+ hierarchical_map = {
490
+ 'YOLOv8': {'Nano': 'n', 'Small': 's', 'Medium': 'm', 'Large': 'l', 'X-Large': 'x'},
491
+ 'YOLOv11': {'Nano': 'n', 'Small': 's', 'Medium': 'm', 'Large': 'l', 'X-Large': 'x'},
492
+ 'YOLOv12': {'Nano': 'n', 'Small': 's', 'Medium': 'm', 'Large': 'l', 'X-Large': 'x'}
493
+ }
494
+
495
+ return hierarchical_map
496
+
447
497
  def setup_ui(self):
448
498
  """Set up the UI with a tabbed interface for model selection."""
449
499
  main_layout = QVBoxLayout(self)
450
-
451
- # --- Tabbed Interface for Model Selection ---
452
500
  self.tabs = QTabWidget()
453
501
 
454
- # Tab 1: Select Model
502
+ # === Tab 1: Select Pre-defined Model ===
455
503
  model_select_tab = QWidget()
456
- model_select_layout = QFormLayout(model_select_tab)
457
- model_select_layout.setContentsMargins(5, 10, 5, 5) # Add some top margin
458
-
459
- self.model_combo = QComboBox()
460
- self.model_combo.addItems(["Color Features"])
461
- self.model_combo.insertSeparator(1) # Add a separator
462
-
463
- standard_models = [
464
- 'yolov8n-cls.pt',
465
- 'yolov8s-cls.pt',
466
- 'yolov8m-cls.pt',
467
- 'yolov8l-cls.pt',
468
- 'yolov8x-cls.pt',
469
- 'yolo11n-cls.pt',
470
- 'yolo11s-cls.pt',
471
- 'yolo11m-cls.pt',
472
- 'yolo11l-cls.pt',
473
- 'yolo11x-cls.pt',
474
- 'yolo12n-cls.pt',
475
- 'yolo12s-cls.pt',
476
- 'yolo12m-cls.pt',
477
- 'yolo12l-cls.pt',
478
- 'yolo12x-cls.pt'
479
- ]
480
-
481
- self.model_combo.addItems(standard_models)
482
-
483
- community_configs = get_available_configs(task='classify')
484
- if community_configs:
485
- self.model_combo.insertSeparator(len(standard_models) + 2)
486
- self.model_combo.addItems(list(community_configs.keys()))
487
-
488
- self.model_combo.setCurrentText('Color Features')
489
- model_select_layout.addRow("Model:", self.model_combo)
504
+ self.model_select_layout = QFormLayout(model_select_tab)
505
+ self.model_select_layout.setContentsMargins(5, 10, 5, 5)
506
+
507
+ # 1. Main Category ComboBox
508
+ self.category_combo = QComboBox()
509
+ self.category_combo.addItems(["Color Features", "Standard Model", "Community Model", "Transformer Model"])
510
+ self.model_select_layout.addRow("Category:", self.category_combo)
511
+
512
+ # 2. Standard Model Options (initially hidden)
513
+ self.family_combo = QComboBox()
514
+ self.family_combo.addItems(self.standard_models_map.keys())
515
+ self.size_combo = QComboBox()
516
+ self.family_combo.currentTextChanged.connect(self._update_size_combo)
517
+ self._update_size_combo(self.family_combo.currentText())
518
+
519
+ self.standard_model_widgets = [QLabel("Family:"), self.family_combo, QLabel("Size:"), self.size_combo]
520
+ self.model_select_layout.addRow(self.standard_model_widgets[0], self.standard_model_widgets[1])
521
+ self.model_select_layout.addRow(self.standard_model_widgets[2], self.standard_model_widgets[3])
522
+
523
+ # 3. Community Model Options (initially hidden)
524
+ self.community_combo = QComboBox()
525
+ if self.community_configs:
526
+ self.community_combo.addItems(list(self.community_configs.keys()))
527
+ self.community_model_widgets = [QLabel("Model:"), self.community_combo]
528
+ self.model_select_layout.addRow(self.community_model_widgets[0], self.community_model_widgets[1])
529
+
530
+ # 4. Transformer Model Options (initially hidden)
531
+ self.transformer_combo = QComboBox()
532
+ self.transformer_combo.addItems(list(self.transformer_models.keys()))
533
+ self.transformer_model_widgets = [QLabel("Model:"), self.transformer_combo]
534
+ self.model_select_layout.addRow(self.transformer_model_widgets[0], self.transformer_model_widgets[1])
490
535
 
491
536
  self.tabs.addTab(model_select_tab, "Select Model")
492
537
 
493
- # Tab 2: Existing Model from File
538
+ # === Tab 2: Existing Model from File ===
494
539
  model_existing_tab = QWidget()
495
540
  model_existing_layout = QFormLayout(model_existing_tab)
496
541
  model_existing_layout.setContentsMargins(5, 10, 5, 5)
497
542
 
498
543
  self.model_path_edit = QLineEdit()
499
- self.model_path_edit.setPlaceholderText("Path to a existing .pt model file...")
544
+ self.model_path_edit.setPlaceholderText("Path to a compatible .pt model file...")
500
545
  browse_button = QPushButton("Browse...")
501
546
  browse_button.clicked.connect(self.browse_for_model)
502
547
 
@@ -505,82 +550,155 @@ class ModelSettingsWidget(QGroupBox):
505
550
  path_layout.addWidget(browse_button)
506
551
  model_existing_layout.addRow("Model Path:", path_layout)
507
552
 
553
+ help_label = QLabel("Note: Select an Ultralytics model (.pt).")
554
+ help_label.setStyleSheet("color: gray; font-style: italic;")
555
+ model_existing_layout.addRow("", help_label)
556
+
508
557
  self.tabs.addTab(model_existing_tab, "Use Existing Model")
509
558
 
510
559
  main_layout.addWidget(self.tabs)
511
-
512
- # Connect all relevant widgets to a single slot that emits the new signal
513
- self.model_combo.currentTextChanged.connect(self._on_selection_changed)
514
- self.tabs.currentChanged.connect(self._on_selection_changed)
515
- self.model_path_edit.textChanged.connect(self._on_selection_changed)
516
-
517
- # Add feature extraction mode selection outside of tabs
560
+
561
+ # === Feature Extraction Mode (Reverted to bottom) ===
518
562
  feature_mode_layout = QFormLayout()
519
563
  self.feature_mode_combo = QComboBox()
520
564
  self.feature_mode_combo.addItems(["Predictions", "Embed Features"])
521
- self.feature_mode_combo.currentTextChanged.connect(self._on_selection_changed)
565
+ self.feature_mode_combo.setCurrentText("Embed Features") # Set default to Embed Features
522
566
  feature_mode_layout.addRow("Feature Mode:", self.feature_mode_combo)
523
567
  main_layout.addLayout(feature_mode_layout)
568
+
569
+ # --- Connect Signals ---
570
+ self.category_combo.currentTextChanged.connect(self._on_category_changed)
571
+ self.tabs.currentChanged.connect(self._on_selection_changed)
572
+ for widget in [self.category_combo, self.family_combo, self.size_combo,
573
+ self.community_combo, self.transformer_combo, self.model_path_edit, self.feature_mode_combo]:
574
+ if isinstance(widget, QComboBox):
575
+ widget.currentTextChanged.connect(self._on_selection_changed)
576
+ elif isinstance(widget, QLineEdit):
577
+ widget.textChanged.connect(self._on_selection_changed)
578
+
579
+ # --- Initial State ---
580
+ self._on_category_changed(self.category_combo.currentText())
581
+ self._on_selection_changed()
582
+
583
+ @pyqtSlot(str)
584
+ def _update_size_combo(self, family):
585
+ """Populate the size combo box based on the selected family."""
586
+ self.size_combo.clear()
587
+ if family in self.standard_models_map:
588
+ self.size_combo.addItems(self.standard_models_map[family].keys())
589
+
590
+ @pyqtSlot(str)
591
+ def _on_category_changed(self, category):
592
+ """Show or hide sub-option widgets based on the selected category."""
593
+ is_standard = (category == "Standard Model")
594
+ is_community = (category == "Community Model")
595
+ is_transformer = (category == "Transformer Model")
596
+
597
+ for widget in self.standard_model_widgets:
598
+ widget.setVisible(is_standard)
599
+ for widget in self.community_model_widgets:
600
+ widget.setVisible(is_community)
601
+ for widget in self.transformer_model_widgets:
602
+ widget.setVisible(is_transformer)
524
603
 
525
- # Initialize the feature mode state and emit the first signal
526
604
  self._on_selection_changed()
527
605
 
528
606
  def browse_for_model(self):
529
607
  """Open a file dialog to browse for model files."""
530
608
  options = QFileDialog.Options()
531
609
  file_path, _ = QFileDialog.getOpenFileName(
532
- self,
533
- "Select Model File",
534
- "",
535
- "PyTorch Models (*.pt);;All Files (*)",
536
- options=options
537
- )
610
+ self, "Select Model File", "", "PyTorch Models (*.pt);;All Files (*)", options=options)
538
611
  if file_path:
539
612
  self.model_path_edit.setText(file_path)
540
613
 
541
614
  @pyqtSlot()
542
615
  def _on_selection_changed(self):
543
- """Central slot to handle any change in model selection and emit a single signal."""
616
+ """Central slot to handle any change and emit a single signal."""
544
617
  self._update_feature_mode_state()
545
618
  self.selection_changed.emit()
546
619
 
547
- def _update_feature_mode_state(self, *args):
548
- """Update the enabled state of the feature mode field based on the current model selection."""
549
- current_tab_index = self.tabs.currentIndex()
620
+ def _update_feature_mode_state(self):
621
+ """Update the enabled state and tooltip of the feature mode field."""
550
622
  is_color_features = False
623
+ is_transformer = False
624
+ is_community = False # Add a new flag for community models
625
+ current_tab_index = self.tabs.currentIndex()
551
626
 
552
627
  if current_tab_index == 0:
553
- # Select Model tab - check if Color Features is selected
554
- current_model = self.model_combo.currentText()
555
- is_color_features = current_model == "Color Features"
556
- elif current_tab_index == 1:
557
- # Use Existing Model tab - feature mode should always be enabled
558
- is_color_features = False
628
+ category = self.category_combo.currentText()
629
+ is_color_features = (category == "Color Features")
630
+ is_transformer = (category == "Transformer Model")
631
+ is_community = (category == "Community Model") # Check for Community Model
559
632
 
560
- # Enable feature mode only if not Color Features
561
- self.feature_mode_combo.setEnabled(not is_color_features)
633
+ # Disable feature mode for Color Features, Transformer Models, and Community Models
634
+ self.feature_mode_combo.setEnabled(not (is_color_features or is_transformer or is_community))
635
+
636
+ # If disabled categories are selected, force the combo to "Embed Features"
637
+ if is_color_features or is_transformer or is_community:
638
+ self.feature_mode_combo.setCurrentText("Embed Features")
562
639
 
563
- # Update the tooltip based on state
564
640
  if is_color_features:
565
- self.feature_mode_combo.setToolTip("Feature Mode is not available for Color Features")
641
+ self.feature_mode_combo.setToolTip("Feature Mode is not applicable for Color Features.")
642
+ elif is_transformer:
643
+ self.feature_mode_combo.setToolTip("Transformer models always output embedding features.")
644
+ elif is_community:
645
+ self.feature_mode_combo.setToolTip("Community models always output embedding features.")
566
646
  else:
567
- self.feature_mode_combo.setToolTip("Select the feature extraction mode")
647
+ self.feature_mode_combo.setToolTip(
648
+ "Choose 'Predictions' for class probabilities (for uncertainty analysis)\n"
649
+ "or 'Embed Features' for a general-purpose feature vector."
650
+ )
568
651
 
569
652
  def get_selected_model(self):
570
653
  """Get the currently selected model name/path and feature mode."""
571
654
  current_tab_index = self.tabs.currentIndex()
655
+ model_name = ""
572
656
 
573
- # Get model name/path and feature mode based on the active tab
657
+ # Standard Model Tab
574
658
  if current_tab_index == 0:
575
- model_name = self.model_combo.currentText()
659
+ category = self.category_combo.currentText()
660
+
661
+ if category == "Color Features":
662
+ model_name = "Color Features"
663
+
664
+ elif category == "Standard Model":
665
+ family_text = self.family_combo.currentText()
666
+ size_text = self.size_combo.currentText()
667
+
668
+ # Add a guard clause to prevent crashing if a combo is empty.
669
+ if not family_text or not size_text:
670
+ return "", "N/A" # Return a safe default
671
+
672
+ # Create the display name format to look up in YOLO_MODELS
673
+ display_name = f"{family_text} ({size_text})"
674
+ if display_name in self.yolo_models:
675
+ model_name = self.yolo_models[display_name]
676
+ else:
677
+ # Fallback to the old method if not found
678
+ family_key = family_text.lower().replace('-', '')
679
+ size_key = self.standard_models_map[family_text][size_text]
680
+ model_name = f"{family_key}{size_key}-cls.pt"
681
+
682
+ elif category == "Community Model":
683
+ model_display_name = self.community_combo.currentText()
684
+ # Use the path (value) instead of the name (key) for community models
685
+ if self.community_configs and model_display_name in self.community_configs:
686
+ model_name = self.community_configs[model_display_name]
687
+ else:
688
+ model_name = model_display_name # Fallback to using the display name
689
+
690
+ elif category == "Transformer Model":
691
+ # Get the HuggingFace model ID from the transformer models map
692
+ selected_display_name = self.transformer_combo.currentText()
693
+ model_name = self.transformer_models.get(selected_display_name, selected_display_name)
694
+
695
+ # Custom Model Tab
576
696
  elif current_tab_index == 1:
577
697
  model_name = self.model_path_edit.text()
578
- else:
579
- return "", None
580
698
 
581
- feature_mode = self.feature_mode_combo.currentText() if self.feature_mode_combo.isEnabled() else "N/A"
699
+ feature_mode = self.feature_mode_combo.currentText()
582
700
  return model_name, feature_mode
583
-
701
+
584
702
 
585
703
  class EmbeddingSettingsWidget(QGroupBox):
586
704
  """Widget containing settings with tabs for models and embedding."""
@@ -716,4 +834,4 @@ class EmbeddingSettingsWidget(QGroupBox):
716
834
  if hasattr(self.explorer_window, '_clear_selections'):
717
835
  self.explorer_window._clear_selections()
718
836
 
719
- self.explorer_window.run_embedding_pipeline()
837
+ self.explorer_window.run_embedding_pipeline()