Skip to content

Refactor ctd_conditions / conditions_provider + add ConditionsConfig + fix InferenceConfig - #3387

Merged
deruyter92 merged 20 commits into
mainfrom
jaap/fix_ctd_conditions_config
Jul 20, 2026
Merged

Refactor ctd_conditions / conditions_provider + add ConditionsConfig + fix InferenceConfig#3387
deruyter92 merged 20 commits into
mainfrom
jaap/fix_ctd_conditions_config

Conversation

@deruyter92

Copy link
Copy Markdown
Collaborator

Issues
This PR addresses two issues with the way conditions are specified for inference with a BUCTD model:

  1. With the introduction of typed configs, the InferenceConfig was too simplified: different schemas can be used to specify the conditions, but only a plain (unvalidated) dict was supported.
  2. The implementation of CondProvider in pose_estimation_pytorch/data/ctd.py was slightly incorrect and misleading:
    • the two subclasses CondFromFile and CondFromModel serve a different thing (either a provider that can read conditions from a file, or just a config object that still needs downstream loading of the BU model).
    • CondProvider was denoted as abstract base class, but both subclasses call super(). on the parent methods.
    • inference API required the CondFromModel configuration or a dict, which now should be replaced with a proper DLCBaseConfig instance.

Implementation

  • This PR introduces a ConditionsConfiguration schema with two subclasses ConditionsFileConfig and ConditionsModelConfig to solve the oversimplified schema design.
  • The implementation of CondProvider is refactored: only CondFromFile is kept, as it literally provides conditions from a file. The CondFromModel configuration class is replaced with ConditionsModelConfig.
  • inference API is refactored to accept ConditionsConfig or their raw arguments, and normalized + validated at the beginning.

Refactor type InferenceConfig.conditions with ConditionsConfig union
Replace the untyped `dict[str, Any] | None` conditions field with a proper
typed hierarchy: `ConditionsConfig` base class with `ConditionsFileConfig`
(filepath only) and `ConditionsModelConfig` (direct paths or DLC shuffle
shorthand) subclasses. A `ConditionsConfig.build()` classmethod normalizes
any raw YAML input (str, Path, dict) into the correct subtype.
- Add `config/ctd_conditions.py` with the three config classes
- Update `InferenceConfig.conditions` to `ConditionsModelConfig | ConditionsFileConfig | None`
  with a `mode="before"` field validator calling `ConditionsConfig.build()`
- Refactor `get_condition_provider()` to accept `ConditionsModelConfig | dict`
  and use `ConditionsConfig.build()` instead of ad-hoc dict inspection
- Fix bug in `CondFromModel.__init__`: `snapshot_path` was incorrectly
  assigned `Path(config_path)` instead of `Path(snapshot_path)`
CondProvider was denoted as abstract class, but was no abstract in practice since both subclasses call its methods. The helper is a cleaner way to achieve the same.
- remove CondFromModel: it was just a config. Now replaced with ConditionsModelConfig
- remove get_condition_provider: it was just a wrapper to initialize CondFromModel, which is now centralized in ConditionsModelConfig
@deruyter92 deruyter92 changed the title Refactor ctd_conditions / conditions_provider + add ConditionsConfig + fix InferenceConfig Refactor ctd_conditions / conditions_provider + add ConditionsConfig + fix InferenceConfig Jul 10, 2026
@deruyter92
deruyter92 requested a review from C-Achard July 10, 2026 08:34
Add ConditionsConfig subtype for unresolved shuffle-references. And hook-up ModelConfig.resolve_from_conditions().
@deruyter92

deruyter92 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

Edit
now added a third schema subclass which was accepted in the original design as well: ConditionsShuffleConfig for shuffle references that are not yet resolved to a model snapshot on disk. I added a resolve_from_conditions method to do the canonical resolution to a ConditionModelConfig (which finds the snapshot on disk) for BUCTD live inference.

@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.

I think this is a very good start, and indeed good to harden this a bit.

There are still a few things that may be worth clarifying:

  • Should we wrap the old CondFromModel with a deprecated constructor that routes to the new builder? Or not worth it as internal API/too much effort for the payoff
  • resolve_from_conditions is very nice to expose capabilities from the schema. It may be worth making the supported capabilities of each condition source more explicit, either in the documentation or through routing in the code, to make future refactors easier

Adding tests (which might already be done or planned) would be very helpful too.

Comment thread deeplabcut/pose_estimation_pytorch/apis/analyze_images.py Outdated
Comment thread deeplabcut/pose_estimation_pytorch/apis/videos.py Outdated
Comment thread deeplabcut/pose_estimation_pytorch/apis/analyze_images.py
Comment thread deeplabcut/pose_estimation_pytorch/apis/analyze_images.py Outdated
Comment thread deeplabcut/pose_estimation_pytorch/apis/videos.py Outdated
Comment thread deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py Outdated
Comment thread deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py Outdated
    - Only when task  is COND_TOP_DOWN.
    - falsey values "", {} etc should not silently fall back to model_cfg.inference.conditions
This function is just used internally, does not require a project config  and uses resolved model snapshots etc,. Since not all ConditionsConfigurations (e.g. shuffle) can be resolved without a projectconfig, and since resolution already happens in upstream funcitons it is more clean to strictly accept ConditionsModelConfig here.
…onfig or ConditionsModelConfig, not ConditionsFileConfig.
@C-Achard

Copy link
Copy Markdown
Collaborator

@deruyter92 I'm fixing the fast lane in another PR, sorry for the CI fails

Correctly reflect the available subtypes of ConditionsConfig for analysis or live inference
- remove circular assertion
- add missing tests (e.g. DLCLoader injects)
- format parametrized input as pytest.param for more clarity
@deruyter92
deruyter92 marked this pull request as ready for review July 15, 2026 07:53
@deruyter92

Copy link
Copy Markdown
Collaborator Author

@C-Achard thanks again for your initial review. I've addressed your comments and made some extra adjustments:

  • added tests
  • improved public API that accepts raw input forms for ConditionsModelConfig / ConditionsShuffleConfig and its raw form (dict)
  • improved docstrings and documentation for the distinction between ConditionsFileConfig (only used for evaluation) and ConditionsModelConfig / ConditionsShuffleConfig (used for live-inference; caches results in a file as well)

We should probably discuss whether it is worth to add the option of using precomputed conditions via ConditionsFileConfig / CondFromFile for inference as well. I completely agree with your earlier comment that this would feel natural, but I think it requires a substantial adjustment to the current implementation: now inference always assumes that unseen images can be passed and conditions are computed on the fly using the BU model (no-precomputed conditions available). The conditions are however cached, so the next time inference is run, the BU model will be skipped for existing images with the same scorer.

Let me know if you think this adjustment would still be worth it, or if you think that caching is sufficient for now.

@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.

Thanks for all the updates!

@C-Achard

Copy link
Copy Markdown
Collaborator

I think it requires a substantial adjustment to the current implementation: now inference always assumes that unseen images can be passed and conditions are computed on the fly using the BU model (no-precomputed conditions available)

Let's leave it out then

@deruyter92
deruyter92 merged commit 6a181fd into main Jul 20, 2026
4 of 5 checks passed
@deruyter92
deruyter92 deleted the jaap/fix_ctd_conditions_config branch July 20, 2026 12:15
@deruyter92 deruyter92 mentioned this pull request Jul 20, 2026
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants