Visitar URL original
minor follow-up adjustments for config GUI validation by deruyter92 · Pull Request #3399 · DeepLabCut/DeepLabCut · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: widen worker and evaluate-network error handling
- Catch BaseException in Worker.run() so SystemExit from CLI functions
  is marshalled to the UI instead of silently killing the thread
- Wrap the full evaluate_network method in a single try/except Exception
  so runtime errors (GPU OOM, corrupted models, etc.) are consistently
  reported through show_task_error instead of only catching config errors
  • Loading branch information
deruyter92 committed Jul 17, 2026
commit 4472fd3fb7fed3c8eb55ac6c5278ece61be86cad
58 changes: 28 additions & 30 deletions deeplabcut/gui/tabs/evaluate_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
_create_label_widget,
_create_vertical_layout,
)
from deeplabcut.gui.dialogs.config_errors import CONFIG_LOAD_ERRORS
from deeplabcut.gui.displays.selected_shuffle_display import SelectedShuffleDisplay
from deeplabcut.gui.widgets import ConfigEditor, launch_napari
from deeplabcut.utils import auxiliaryfunctions
Expand Down Expand Up @@ -182,45 +181,44 @@ def update_bodypart_choice(self, s):
self.root.logger.info(f"Use selected bodyparts only: {self.bodyparts_list_widget.selected_bodyparts}")

def evaluate_network(self):
config_path = self.root.config_path
shuffle = self.root.shuffle_value
plotting = self.plot_predictions.isChecked()
try:
config_path = self.root.config_path
shuffle = self.root.shuffle_value
plotting = self.plot_predictions.isChecked()

bodyparts_to_use = "all"
if (
len(self.root.all_bodyparts) != len(self.bodyparts_list_widget.selected_bodyparts)
) and not self.use_all_bodyparts.isChecked():
bodyparts_to_use = self.bodyparts_list_widget.selected_bodyparts
bodyparts_to_use = "all"
if (
len(self.root.all_bodyparts) != len(self.bodyparts_list_widget.selected_bodyparts)
) and not self.use_all_bodyparts.isChecked():
bodyparts_to_use = self.bodyparts_list_widget.selected_bodyparts

try:
deeplabcut.evaluate_network(
config_path,
Shuffles=[shuffle],
plotting=plotting,
show_errors=True,
comparisonbodyparts=bodyparts_to_use,
)
except CONFIG_LOAD_ERRORS as error:
self.root.show_task_error(error, self.root.pose_cfg_path)
return

if plotting:
project_cfg = self.root.cfg
eval_folder = auxiliaryfunctions.get_evaluation_folder(
trainFraction=project_cfg["TrainingFraction"][0],
shuffle=shuffle,
cfg=project_cfg,
)
scorer, _ = auxiliaryfunctions.get_scorer_name(
cfg=project_cfg,
shuffle=shuffle,
trainFraction=project_cfg["TrainingFraction"][0],
)

image_dir = Path(self.root.project_folder) / eval_folder / f"LabeledImages_{scorer}"
labeled_images = [str(p) for p in image_dir.rglob("*.png")]
if len(labeled_images) > 0:
_ = launch_napari(labeled_images)
if plotting:
project_cfg = self.root.cfg
eval_folder = auxiliaryfunctions.get_evaluation_folder(
trainFraction=project_cfg["TrainingFraction"][0],
shuffle=shuffle,
cfg=project_cfg,
)
scorer, _ = auxiliaryfunctions.get_scorer_name(
cfg=project_cfg,
shuffle=shuffle,
trainFraction=project_cfg["TrainingFraction"][0],
)

image_dir = Path(self.root.project_folder) / eval_folder / f"LabeledImages_{scorer}"
labeled_images = [str(p) for p in image_dir.rglob("*.png")]
if len(labeled_images) > 0:
_ = launch_napari(labeled_images)
except Exception as error:
self.root.show_task_error(error, self.root.pose_cfg_path)

@Slot(Engine)
def _on_engine_change(self, engine: Engine) -> None:
Expand Down
2 changes: 1 addition & 1 deletion deeplabcut/gui/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(self, func):
def run(self):
try:
self._execute()
except Exception as exc:
except BaseException as exc:
# Marshal the exception to the GUI thread instead of crashing or
# silently killing the worker thread.
self.error.emit(exc)
Comment thread
deruyter92 marked this conversation as resolved.
Resolved
Expand Down