Skip to content

Prepare TensorFlow deprecation - add deeplabcut.api - #3382

Open
deruyter92 wants to merge 72 commits into
feat/refreshed-apifrom
jaap/prepare_tf_deprecation
Open

Prepare TensorFlow deprecation - add deeplabcut.api#3382
deruyter92 wants to merge 72 commits into
feat/refreshed-apifrom
jaap/prepare_tf_deprecation

Conversation

@deruyter92

Copy link
Copy Markdown
Collaborator

Preparation for full TensorFlow deprecation

  1. Remove deeplabcut.compat and split into PyTorch-only deeplabcut.api and TF-only deeplabcut.tensorflow_compat
  2. Add TensorFlow routing and deprecation utilities which warns the user.

Background

TensorFlow support will be dropped soon and a clean preparation is needed to make the transition smooth. Although the pose_estimation code was already cleanly branched in deeplabcut/compat.py, this brought the disadvantage that the main entrypoint for DeepLabCut is actually mixed API, which was not ideal to test and remains a small obstacle to eventually remove TF cleanly.

This PR makes a large step towards clean TF deprecation, by splitting the compat module into our new clean user-facing API (Pytorch-only) with a fallback for TensorFlow instead of mixed API. It introduces some new packages and removes deeplabcut.compat as the entry point for the public API.

New

deeplabcut.api : the new home for user-facing API functions. Currently covers all pose estimation functions (train_network, evaluate_network, analyze_videos, analyze_images, etc.), but can cover other main API as well.

deeplabcut.tensorflow_compat — an isolated compatibility layer that holds the TensorFlow-specific branches, split out of compat.py. This module is explicitly marked as temporary and will be deleted wholesale when TF support is dropped.

deeplabcut.api._tf_routing — a new decorator-based routing system (@with_tensorflow_fallback) that automatically intercepts calls to functions in deeplabcut.api, resolves the engine and delegates to deeplabcut.tensorflow_compat handling TF-only legacy kwargs. A DLCDeprecationWarning is emitted to inform user about the migration.

Next steps

This PR intentionally scopes to pose estimation only. (I included generate_training_dataset as well first, it's probably better to work in incremental changes, rather than one big PR).

Several other areas still go through compat or have TF branches inline and need similar treatment in follow-up PRs:

  • Dataset creation (generate_training_dataset) — the largest remaining concern.
  • deeplabcut.utils — scattered TF-conditional helpers.
  • deeplabcut.modelzoo — TF-specific download / inference paths.
  • Other smaller callsites in the GUI and 3D/tracking modules.

The goal is that every user-facing function ultimately lives under deeplabcut.api with a clean, PyTorch-only signature, while all TF code is quarantined in deeplabcut.tensorflow_compat and removable in a single future commit.

Test coverage

  • tests/api/test_pose_estimation.py (480 lines) — smoke tests for the new deeplabcut.api pose estimation surface: parameter forwarding, engine routing, legacy kwarg handling.
  • tests/api/test_tf_routing.py (360 lines) — unit tests for the _tf_routing machinery: engine resolution, renamed/dropped param warnings, gputouse normalisation, multi-shuffle validation.
  • tests/core/test_visualization.py (191 lines) — new coverage for deeplabcut.core.visualization helpers.
  • tests/pose_estimation_pytorch/apis/test_apis_utils.py (102 lines) — new coverage for PyTorch API utilities.

@deruyter92

Copy link
Copy Markdown
Collaborator Author

(Needs formatted docstrings and typed configs still)

@deruyter92
deruyter92 marked this pull request as ready for review July 17, 2026 11:07
Comment thread deeplabcut/api/_tf_routing.py Outdated
Comment thread deeplabcut/api/_tf_routing.py Outdated

@C-Achard C-Achard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start,I really like the design overall, I just think some of the current routing might need to be made safer; happy to discuss if needed!

Comment thread deeplabcut/api/_tf_routing.py
Comment thread deeplabcut/api/_tf_routing.py
Comment thread deeplabcut/api/_tf_routing.py
Comment thread deeplabcut/api/_tf_routing.py Outdated
Comment thread deeplabcut/api/_tf_routing.py
Comment thread tests/api/test_tf_routing.py
Comment thread tests/api/test_tf_routing.py
Comment thread tests/api/test_tf_routing.py
Comment thread deeplabcut/api/pose_estimation.py
Comment thread tests/api/test_pose_estimation.py
Apply `renamed_params` aliases (e.g., `cfg_path` → `config`) to the
bound `unified` dict before `_resolve_engine` and `when` inspect it,
so they always see canonical parameter names.
@deruyter92

Copy link
Copy Markdown
Collaborator Author

@C-Achard thanks for your review. I've made the tf_routing more robust now. I've addressed all your comments, and added more tests.

I will do another iteration next week to see if there are more tests to be added, and try it out in practice a low. It is a high-impact PR, so I agree that it should be well-tested.

@deruyter92
deruyter92 requested a review from C-Achard August 10, 2026 09:24
@deruyter92
deruyter92 marked this pull request as ready for review August 10, 2026 09:24

@C-Achard C-Achard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few preliminary comments while going through this again, let's perhaps discuss which areas would benefit from further review/testing as it has grown quite a bit.



@deprecated(replacement="deeplabcut.core.config.ProjectConfig", since="3.1")
@deprecated(replacement="deeplabcut.core.config.ProjectConfig", since="3.0.1")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small question/design curiosity when I see this, should we have a file that defines several consts with version numbers mapping to deprecation, so that whenever there is a round of deprecating something, there is one single source for the version, minimizing the need to globally search for version numbers, and avoiding changing version numbers for an unrelated round of deprecation or on the wrong API?

def __init__(self, root, parent, h1_description):
super().__init__(root, parent, h1_description)

self._reload_timer = QTimer(self)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these defs be moved to the base class?

def __init__(self, root, parent, h1_description):
super().__init__(root, parent, h1_description)

self._reload_timer = QTimer(self)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned elsewhere, might be best moved to the base class instead ? Even if disabled by default

@deruyter92
deruyter92 changed the base branch from main to feat/refreshed-api August 12, 2026 14:59
@C-Achard
C-Achard self-requested a review August 13, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants