Skip to content

Update & de-duplicate skeleton builder#3258

Merged
MMathisLab merged 5 commits intomainfrom
cy/update-skeleton-builder
Apr 12, 2026
Merged

Update & de-duplicate skeleton builder#3258
MMathisLab merged 5 commits intomainfrom
cy/update-skeleton-builder

Conversation

@C-Achard
Copy link
Copy Markdown
Collaborator

@C-Achard C-Achard commented Mar 26, 2026

Motivation

Resolves #3257 and improves maintainability by reducing duplication and increasing coverage.

Scope

This pull request refactors and modularizes the skeleton builder functionality for DeepLabCut, minimizing code reuse between the GUI and CLI, and enhancing maintainability. The main changes include moving core logic to a new SkeletonBuilder base class in deeplabcut/utils/skeleton.py, updating config read/write utilities for better encoding handling, and adapting the GUI skeleton builder to use the new base class, as well as unit tests for the updated class.

Skeleton Builder Refactor and Code Reuse

  • Fixed clear() inconsistencies in updating the rendered skeleton
  • Replaced deprecated DataFrame.groupby(..., axis=1) usage with the transpose-based pattern (df.T.groupby(...).T)
  • Moved the core skeleton builder logic into a new SkeletonBuilder class in deeplabcut/utils/skeleton.py, enabling both GUI and CLI to share the same code and logic. The GUI's SkeletonBuilder now inherits from this base class, reducing code duplication and improving maintainability.
  • The GUI skeleton builder (deeplabcut/gui/widgets.py) was refactored to delegate skeleton-building logic to the new base class, and to implement only the UI-specific parts.

Configuration Handling Improvements

  • Updated config reading and writing functions in deeplabcut/utils/skeleton.py to use UTF-8 encoding and safe YAML loading/dumping, improving compatibility and preventing encoding issues.
  • Ensured that skeleton connections are written to config.yaml in a consistent and sorted order, and normalized to lists for YAML compatibility.

Code Cleanup and Maintenance

  • Improved imports organization in deeplabcut/gui/widgets.py for clarity and consistency.
  • Refactored the logic for picking the most complete labeled frame and handling missing body parts for both CLI and GUI skeleton builders, ensuring consistent behavior across interfaces.

Testing

  • Added unit tests for the skeleton builder logic
  • Manually tested both:
    • the standalone Python skeleton builder
    • the GUI skeleton builder dialog

Pandas compatibility note

Removing the axis argument from DataFrame.groupby is safe for our stack because:

  • groupby(axis=1) is already deprecated in pandas 2.2.x and pandas recommends frame.T.groupby(...) instead
  • in pandas 3.0.x, axis is no longer part of the DataFrame.groupby signature

@C-Achard C-Achard self-assigned this Mar 26, 2026
@C-Achard C-Achard added GUI issues relating to GUI bug fix! fix for a real buggy one... labels Mar 26, 2026
@C-Achard C-Achard mentioned this pull request Mar 26, 2026
2 tasks
@C-Achard C-Achard added the lint required Please run pre-commit hooks to ensure your formatting is up-to-date label Mar 30, 2026
Switch YAML usage to YAML(typ="rt") with explicit UTF-8 encoding for read/write to avoid encoding issues and make config I/O consistent. Replace scipy.spatial.cKDTree alias with KDTree import and adjust on_pick to correctly identify and discard the clicked segment and its sorted index pair, update the LineCollection and trigger a canvas redraw. Ensure skeleton pairs are written in a consistent order by sorting indices before saving. Minor cleanup: comment out unused path/verts assignments in on_select and add a TODO note about duplicate config functions.
Extract and decouple skeleton-building logic into deeplabcut.utils.skeleton.SkeletonBuilder and adapt the GUI to reuse it. The widgets.SkeletonBuilder now subclasses the new BaseSkeletonBuilder and Qt dialog, delegating setup to BaseSkeletonBuilder.__init__ and providing GUI-specific build_ui/display implementations. The core builder no longer calls plt.show() directly; it exposes build_ui() and display() so different frontends (matplotlib or Qt) can control presentation. Also fixed/clarified pick_labeled_frame grouping logic for 'individuals' columns and replaced immediate show() calls with canvas.draw_idle() in the Qt UI. Minor cleanup and UI wiring changes to support the refactor.
Introduce tests/utils/test_skeleton.py containing unit tests for the skeleton builder utilities. Covers pick_labeled_frame (multi-animal drop and no-individual fallback), clear (resetting indices, segments, and LineCollection), export (sorting pairs, writing config, and warning on unconnected bodyparts), on_select (adding pairs/segments, ignoring duplicate hits), on_pick (removing segments on right-click only), and lightweight SkeletonBuilder.__init__ integration (loading dataframe/image and error when no labeled data). Tests use KDTree, LineCollection, pandas/numpy, and monkeypatching to isolate I/O and rendering.
Add read_config/write_config hooks to GUI and core SkeletonBuilder to centralize config IO and ensure skeleton pairs are normalized to plain lists before writing. Update export to call the instance write_config, and make clear() reset the LineCollection to an empty list and trigger a canvas redraw to avoid stale drawing state. Add a simple dev test script (dev/test_skeleton.py) and adjust the unit test to attach a fake canvas before calling clear().
@C-Achard C-Achard force-pushed the cy/update-skeleton-builder branch from 7ddfe72 to da51be4 Compare March 30, 2026 17:54
@C-Achard
Copy link
Copy Markdown
Collaborator Author

Fixed linting per #3263

@C-Achard C-Achard removed the lint required Please run pre-commit hooks to ensure your formatting is up-to-date label Mar 30, 2026
@C-Achard C-Achard requested review from AlexEMG and MMathisLab April 7, 2026 14:41
@deruyter92 deruyter92 self-requested a review April 7, 2026 14:41
@MMathisLab MMathisLab merged commit 822d0b3 into main Apr 12, 2026
18 checks passed
@MMathisLab MMathisLab deleted the cy/update-skeleton-builder branch April 12, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug fix! fix for a real buggy one... GUI issues relating to GUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cannot build a skeleton

3 participants