[dev] C3-II Additional refactoring of configurations #3212
Merged
deruyter92 merged 28 commits intoFeb 20, 2026
Conversation
…ath and Enum serialization
… pipeline) update ProjectConfig add old fields resnet, croppedtraining
…mbiguous bbox_margin This commit resolves two issues: - the bbox_margin field that was defined in GenSamplingConfig was always populated with the bbox_margin value from model_cfg['data']['bbox_margin'], which is an implicit way of carrying over config fields. (Potentially breaks when implicit transfer was missing somewhere). - In most places, GenSamplingConfig is expected to NOT have a field bbox_margin, e.g. when converting to dict it is removed, where in 1 place it is expected (in PoseDataset in dataset.py). This is now resolved by keeping only the explicit config value in PoseConfig.data.bbox_margin, and adding a ctd_bbox_margin field in PoseDatasetParameters.
…onf DictConfig and ListConfig should not be in state dicts)
…RE validation Some config updates currently occur after initial creation and validation of the PoseConfig (e.g. when calling train_network). This commit makes sure that update_by_dotpath and loader.update_model_cfg are validated afterward
…nce(dict) -> assert isinstance(mapping)
21 tasks
C-Achard
approved these changes
Feb 19, 2026
Collaborator
C-Achard
left a comment
There was a problem hiding this comment.
See future notes ! Great job
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is part of the WIP for migrating from dictionary configs to typed & validated configurations, and follows PR #3191. (see issue #3193 for an overview). It is a follow-up of #3194, with additional refactors that are required to make the change to DictConfig working.
Summary
Improve YAML I/O : A pair of central factory functions
get_yaml_loader()andget_yaml_dumper()were added to deeplabcut/core/config/utils.py, instead of having downstream functions creating YAML handlers themselves. The dumper registers custom representers for Path, Enum, DictConfig, and ListConfig so these types are transparently serialized as plain YAML scalars/mappings. All call-sites across the codebase (metadata.py, export.py, modelzoo/config.py, test_trainset_metadata.py, etc.) now use these centralized factories instead of constructing YAML() / YAML(typ="safe", pure=True) ad hoc.Updates to the core configuration types
make_pytorch_pose_configflow is restructured (and corrected):Constructs a fully-typed PoseConfig object (with TrainSettingsConfig, WeightInitialization, etc.) before merging architecture defaults. Similarly, make_pytorch_test_config now constructs and validates a TestConfig instance. The Loader.update_model_cfg method now re-validates the config through PoseConfig after applying dot-path updates. This will be again further simplified at the end of the PR series (e.g. after moving to fully-typed configs
Improved handling/conversion of config Types: While in the central pipeline, we aim to move to typed configs, some places (e.g. before initial construction of the PoseConfig, or when serializing state dicts) may benefit from using plain dictionaries with native python types.
@ensure_plain_configdecorator that converts the config back to a plain dictionary. It is applied to key functions that must operate on plain dicts:update_config,update_config_by_dotpath,replace_default_values,_load_pose_config_defaults,_add_ctd_conditions,add_metadata, and the central registry'sbuild_from_cfg.paf_predictor.pynow uses int instead of numpy.int64, which was equivalent but non-serializable)None-safe .get() pattern fix
A widespread pattern cfg.get("key", {}) was replaced with cfg.get("key") or {}. When a key exists but is explicitly set to None in the config, the old pattern returns None (ignoring the default), leading to AttributeError on the chained .get(). The new pattern handles both missing keys and None values. These are marked with TODOs for future refactoring.
Fix invalid test configuration: in one of the test scripts, detector conditions are added to all of the training, even when bottom-up or ctd models are used. When these models are missing other required detector specifications, the new PoseConfig system throws an (accurate) validation error. The script is adjusted such that no partially detector-configs are added.