Skip to content

deeplabcut.pose_estimation_pytorch.config

Modules:

Name Description
ctd_conditions

Typed configuration for CTD (Conditional Top-Down) model conditions.

data

Data configuration classes for DeepLabCut pose estimation models.

enums
inference

Inference configuration classes for DeepLabCut pose estimation models.

logger

Logger configuration classes for DeepLabCut training runs.

make_pose_config

Methods to create the configuration files for PyTorch DeepLabCut models.

metadata
model

Model configuration class for DeepLabCut pose estimation models.

paf_parameters
pose

Main pose configuration class for DeepLabCut pose estimation models.

runner

Runner configuration class for DeepLabCut pose estimation models.

training

Training configuration classes for DeepLabCut pose estimation models.

utils

Util functions to create pytorch pose configuration files.

Classes:

Name Description
AutocastConfig

Automatic mixed precision configuration.

COCOLoaderConfig

Configuration for COCO Loader.

CSVLoggerConfig

Configuration for CSV logger.

CompileConfig

Model compilation configuration for inference optimization.

ConditionsConfig

Base class for CTD conditions configuration.

ConditionsFileConfig

Conditions loaded from a pre-computed predictions file (.h5, .json, .pickle).

ConditionsModelConfig

Resolved config for a BU model (i.e. a snapshot ref for live inference).

ConditionsShuffleConfig

Unresolved shuffle shorthand for CTD conditions.

DLCLoaderConfig

Configuration for DeepLabCut Loader.

DataConfig

Complete data configuration.

DataTransformationConfig

Data transformation configuration.

DatasetType

Enumeration of dataset types.

DetectorModelConfig

Configuration for detector models

DetectorType

Enumeration of detector types.

EvaluationConfig

Configuration for evaluation metrics computation.

GenSamplingConfig

Configuration for CTD models.

InferenceConfig

Complete inference configuration.

LoggerConfig

Base configuration for all loggers.

MethodType

Enumeration of pose estimation method types.

ModelConfig

Complete model configuration.

MultithreadingConfig

Multithreading configuration for inference.

NetType

Enumeration of network architecture types as stored in configs.

OptimizerConfig

Optimizer configuration.

PoseConfig

Main configuration class for DeepLabCut pose estimation models.

PoseMetadata
RunnerConfig

Training runner configuration.

SchedulerConfig

Learning rate scheduler configuration.

SnapshotCheckpointConfig

Snapshot configuration for model checkpoints.

TestConfig

Configuration class for DeepLabCut test/inference settings.

TrainSettingsConfig

Training settings configuration.

WandbLoggerConfig

Configuration for Weights & Biases (wandb) logger.

Functions:

Name Description
available_detectors

Returns: all the possible detectors that can be used

available_models

Returns: the possible variants of models that can be used

get_config_folder_path

Returns: the Path to the folder containing the "configs" for DeepLabCut 3.0

is_model_cond_top_down

Checks whether a given net_type is conditional top-down or not.

is_model_top_down

Checks whenever a given net_type is top-down or not.

load_backbones

Load backbones.

load_base_config

Returns: the base configuration for all PyTorch DeepLabCut models

load_detectors

Load detectors.

make_basic_project_config

Deprecated factory for basic config dict for non-DLC projects.

pretty_print

Prints a model configuration in a pretty and readable way.

read_config_as_dict

Args:

replace_default_values

Replaces placeholder values in a model configuration with their actual values.

update_config

Deprecated helper for updating config dictionaries.

update_config_by_dotpath

Deprecated helper for updating config dictionaries using dot notation.

write_config

Writes a pose configuration file to disk.

AutocastConfig

Bases: DLCBaseConfig

Automatic mixed precision configuration.

Attributes:

Name Type Description
enabled bool

Whether autocast is enabled

dtype bool

Data type for autocast (float16, bfloat16)

Source code in deeplabcut/pose_estimation_pytorch/config/inference.py
class AutocastConfig(DLCBaseConfig):
    """Automatic mixed precision configuration.

    Attributes:
        enabled: Whether autocast is enabled
        dtype: Data type for autocast (float16, bfloat16)
    """

    enabled: bool = False

COCOLoaderConfig

Bases: DLCBaseConfig

Configuration for COCO Loader.

Attributes:

Name Type Description
type Literal[COCOLoader]

Loader type identifier

Source code in deeplabcut/pose_estimation_pytorch/config/data.py
class COCOLoaderConfig(DLCBaseConfig):
    """Configuration for COCO Loader.

    Attributes:
        type: Loader type identifier
    """

    type: Literal[DataLoaderType.COCOLoader]

CSVLoggerConfig

Bases: LoggerConfig

Configuration for CSV logger.

This logger saves training stats and metrics to a CSV file.

Attributes:

Name Type Description
type Literal[CSVLogger]

Logger type (should be 'CSVLogger')

train_folder str

The path of the folder containing training files.

log_filename str

The name of the file in which to store training stats

Source code in deeplabcut/pose_estimation_pytorch/config/logger.py
class CSVLoggerConfig(LoggerConfig):  #
    """Configuration for CSV logger.

    This logger saves training stats and metrics to a CSV file.

    Attributes:
        type: Logger type (should be 'CSVLogger')
        train_folder: The path of the folder containing training files.
        log_filename: The name of the file in which to store training stats
    """

    type: Literal[LoggerType.CSVLogger]
    train_folder: str = ""
    log_filename: str = "learning_stats.csv"

CompileConfig

Bases: DLCBaseConfig

Model compilation configuration for inference optimization.

Attributes:

Name Type Description
enabled bool

Whether compilation is enabled

mode bool

Compilation mode

Source code in deeplabcut/pose_estimation_pytorch/config/inference.py
class CompileConfig(DLCBaseConfig):
    """Model compilation configuration for inference optimization.

    Attributes:
        enabled: Whether compilation is enabled
        mode: Compilation mode
    """

    enabled: bool = False
    backend: str = "inductor"

ConditionsConfig

Bases: DLCBaseConfig

Base class for CTD conditions configuration.

Use ConditionsConfig.build() to normalise any raw input into a typed subclass.

Subclasses
  • ConditionsFileConfig — pre-computed predictions file (evaluation only)
  • ConditionsModelConfig — resolved BU model (config + snapshot paths)
  • ConditionsShuffleConfig — unresolved shuffle shorthand (resolve to Model for live inference, or to CondFromFile for evaluation)

Methods:

Name Description
build

Normalise any raw input into a typed conditions config.

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
class ConditionsConfig(DLCBaseConfig):
    """Base class for CTD conditions configuration.

    Use ``ConditionsConfig.build()`` to normalise any raw input into a typed subclass.

    Subclasses:
        - ``ConditionsFileConfig``    — pre-computed predictions file (evaluation only)
        - ``ConditionsModelConfig``   — resolved BU model (config + snapshot paths)
        - ``ConditionsShuffleConfig`` — unresolved shuffle shorthand (resolve to Model
          for live inference, or to ``CondFromFile`` for evaluation)
    """

    source: Literal["file", "model", "shuffle"]

    @classmethod
    def build(
        cls,
        v: str | Path | dict | ConditionsConfig | None,
    ) -> ConditionsFileConfig | ConditionsModelConfig | ConditionsShuffleConfig | None:
        """Normalise any raw input into a typed conditions config.

        This method is pure — it never touches the filesystem. For shuffle
        shorthand inputs it returns a ``ConditionsShuffleConfig`` (unresolved).
        To obtain a fully resolved ``ConditionsModelConfig`` call
        ``ConditionsModelConfig.resolve_from_conditions()`` at the point where
        the project config is available.

        Args:
            v: Raw input. Accepted forms:
                - ``None`` or an existing ``ConditionsConfig`` → returned unchanged
                - ``str`` / ``Path`` → ``ConditionsFileConfig``
                - ``dict`` with ``filepath`` → ``ConditionsFileConfig``
                - ``dict`` with ``config_path`` + ``snapshot_path`` → ``ConditionsModelConfig``
                - ``dict`` with ``shuffle`` → ``ConditionsShuffleConfig``

        Returns:
            A typed ``ConditionsConfig`` subclass, or ``None``.
        """
        if v is None or isinstance(v, ConditionsConfig):
            return v
        if isinstance(v, (str, Path)):
            return ConditionsFileConfig(filepath=Path(v))
        if isinstance(v, dict):
            v = v.copy()
            source = v.pop("source", None)
            if source == "file" or (source is None and "filepath" in v):
                return ConditionsFileConfig(**v)
            if source == "shuffle" or (source is None and "shuffle" in v):
                return ConditionsShuffleConfig(**v)
            if source == "model" or "config_path" in v or "snapshot_path" in v:
                return ConditionsModelConfig(**v)
            raise ValueError(
                "Cannot determine conditions source from dict. "
                "Provide 'filepath' for a file source, "
                "'config_path'+'snapshot_path' for a model source, "
                "or 'shuffle' for a shuffle shorthand."
            )
        raise TypeError(f"Cannot build a ConditionsConfig from {type(v).__name__!r}: {v!r}")

build classmethod

build(
    v: str | Path | dict | ConditionsConfig | None,
) -> ConditionsFileConfig | ConditionsModelConfig | ConditionsShuffleConfig | None

Normalise any raw input into a typed conditions config.

This method is pure — it never touches the filesystem. For shuffle shorthand inputs it returns a ConditionsShuffleConfig (unresolved). To obtain a fully resolved ConditionsModelConfig call ConditionsModelConfig.resolve_from_conditions() at the point where the project config is available.

Parameters:

Name Type Description Default

v

str | Path | dict | ConditionsConfig | None

Raw input. Accepted forms: - None or an existing ConditionsConfig → returned unchanged - str / PathConditionsFileConfig - dict with filepathConditionsFileConfig - dict with config_path + snapshot_pathConditionsModelConfig - dict with shuffleConditionsShuffleConfig

required

Returns:

Type Description
ConditionsFileConfig | ConditionsModelConfig | ConditionsShuffleConfig | None

A typed ConditionsConfig subclass, or None.

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
@classmethod
def build(
    cls,
    v: str | Path | dict | ConditionsConfig | None,
) -> ConditionsFileConfig | ConditionsModelConfig | ConditionsShuffleConfig | None:
    """Normalise any raw input into a typed conditions config.

    This method is pure — it never touches the filesystem. For shuffle
    shorthand inputs it returns a ``ConditionsShuffleConfig`` (unresolved).
    To obtain a fully resolved ``ConditionsModelConfig`` call
    ``ConditionsModelConfig.resolve_from_conditions()`` at the point where
    the project config is available.

    Args:
        v: Raw input. Accepted forms:
            - ``None`` or an existing ``ConditionsConfig`` → returned unchanged
            - ``str`` / ``Path`` → ``ConditionsFileConfig``
            - ``dict`` with ``filepath`` → ``ConditionsFileConfig``
            - ``dict`` with ``config_path`` + ``snapshot_path`` → ``ConditionsModelConfig``
            - ``dict`` with ``shuffle`` → ``ConditionsShuffleConfig``

    Returns:
        A typed ``ConditionsConfig`` subclass, or ``None``.
    """
    if v is None or isinstance(v, ConditionsConfig):
        return v
    if isinstance(v, (str, Path)):
        return ConditionsFileConfig(filepath=Path(v))
    if isinstance(v, dict):
        v = v.copy()
        source = v.pop("source", None)
        if source == "file" or (source is None and "filepath" in v):
            return ConditionsFileConfig(**v)
        if source == "shuffle" or (source is None and "shuffle" in v):
            return ConditionsShuffleConfig(**v)
        if source == "model" or "config_path" in v or "snapshot_path" in v:
            return ConditionsModelConfig(**v)
        raise ValueError(
            "Cannot determine conditions source from dict. "
            "Provide 'filepath' for a file source, "
            "'config_path'+'snapshot_path' for a model source, "
            "or 'shuffle' for a shuffle shorthand."
        )
    raise TypeError(f"Cannot build a ConditionsConfig from {type(v).__name__!r}: {v!r}")

ConditionsFileConfig

Bases: ConditionsConfig

Conditions loaded from a pre-computed predictions file (.h5, .json, .pickle).

File-based conditions are for evaluation only (load_conditions_for_evaluation / CondFromFile). They cannot be used for live analyze_images / analyze_videos inference — use a shuffle or ConditionsModelConfig instead.

Attributes:

Name Type Description
filepath Path

Path to the predictions file.

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
class ConditionsFileConfig(ConditionsConfig):
    """Conditions loaded from a pre-computed predictions file (.h5, .json, .pickle).

    File-based conditions are for **evaluation only** (``load_conditions_for_evaluation``
    / ``CondFromFile``). They cannot be used for live ``analyze_images`` /
    ``analyze_videos`` inference — use a shuffle or ``ConditionsModelConfig`` instead.

    Attributes:
        filepath: Path to the predictions file.
    """

    source: Literal["file"] = "file"
    filepath: Path

ConditionsModelConfig

Bases: ConditionsConfig

Resolved config for a BU model (i.e. a snapshot ref for live inference).

Attributes:

Name Type Description
config_path Path

Path to the BU model's pytorch_config.yaml.

snapshot_path Path

Path to the BU snapshot file.

scorer str | None

Scorer name for the BU model. Used to look for pre-computed conditions files on disk before running the model.

Methods:

Name Description
from_shuffle

Resolve a DLC BU shuffle to its model config and snapshot paths.

resolve_from_conditions

Resolve conditions input to a ConditionsModelConfig for live BUCTD

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
class ConditionsModelConfig(ConditionsConfig):
    """Resolved config for a BU model (i.e. a snapshot ref for live inference).

    Attributes:
        config_path: Path to the BU model's ``pytorch_config.yaml``.
        snapshot_path: Path to the BU snapshot file.
        scorer: Scorer name for the BU model. Used to look for pre-computed
            conditions files on disk before running the model.
    """

    source: Literal["model"] = "model"
    config_path: Path
    snapshot_path: Path
    scorer: str | None = None

    @classmethod
    def from_shuffle(
        cls,
        config: str | Path,
        shuffle: int,
        trainset_index: int = 0,
        modelprefix: str = "",
        snapshot: str | None = None,
        snapshot_index: int | None = None,
    ) -> ConditionsModelConfig:
        """Resolve a DLC BU shuffle to its model config and snapshot paths."""
        from deeplabcut.pose_estimation_pytorch.data.ctd import resolve_bu_shuffle

        loader, bu_snapshot = resolve_bu_shuffle(config, shuffle, trainset_index, modelprefix, snapshot, snapshot_index)
        return cls(
            config_path=loader.model_config_path,
            snapshot_path=bu_snapshot.path,
            scorer=loader.scorer(bu_snapshot),
        )

    @classmethod
    def resolve_from_conditions(
        cls,
        conditions: dict | ConditionsShuffleConfig | ConditionsModelConfig,
        config: str | Path | None = None,
    ) -> ConditionsModelConfig:
        """Resolve conditions input to a ``ConditionsModelConfig`` for live BUCTD
        inference (``analyze_images`` / ``analyze_videos``).

        Call this in runtime code. It may touch the filesystem when resolving a
        ``ConditionsShuffleConfig`` to a ``ConditionsModelConfig``.

        Args:
            conditions: A dict, ``ConditionsShuffleConfig``, or
                ``ConditionsModelConfig``.File / path conditions cannot be resolved
                to a BU model for live inference; they are rejected.
            config: Project ``config.yaml`` path. Required when resolving a
                ``ConditionsShuffleConfig`` that does not already carry one in its
                ``config`` attribute.

        Returns:
            A resolved ``ConditionsModelConfig``.

        Raises:
            ValueError: If ``conditions`` builds to a ``ConditionsFileConfig``, or
                if a shuffle config has no project config available.
            TypeError: If ``conditions`` cannot be built into a supported type.
        """
        if not isinstance(conditions, ConditionsConfig):
            conditions = ConditionsConfig.build(conditions)

        if isinstance(conditions, ConditionsFileConfig):
            raise ValueError(
                "File-based conditions are for evaluation only and cannot be used "
                "for live BU inference. Provide a ConditionsModelConfig "
                "('config_path'+'snapshot_path') or a ConditionsShuffleConfig / "
                "shuffle dict."
            )
        if isinstance(conditions, cls):
            return conditions

        if not isinstance(conditions, ConditionsShuffleConfig):
            raise TypeError(
                f"Cannot resolve conditions of type {type(conditions).__name__} "
                "for live BU inference. Expected ConditionsShuffleConfig, "
                "ConditionsModelConfig, or a dict that builds to one of those."
            )
        cfg = conditions.config or (Path(config) if config is not None else None)
        if cfg is None:
            raise ValueError(
                "Cannot resolve shuffle conditions: no project config provided. "
                "Set 'config' in the shuffle conditions or pass it to "
                "resolve_from_conditions()."
            )
        return cls.from_shuffle(
            config=cfg,
            shuffle=conditions.shuffle,
            trainset_index=conditions.trainset_index,
            modelprefix=conditions.modelprefix,
            snapshot=conditions.snapshot,
            snapshot_index=conditions.snapshot_index,
        )

from_shuffle classmethod

from_shuffle(
    config: str | Path,
    shuffle: int,
    trainset_index: int = 0,
    modelprefix: str = "",
    snapshot: str | None = None,
    snapshot_index: int | None = None,
) -> ConditionsModelConfig

Resolve a DLC BU shuffle to its model config and snapshot paths.

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
@classmethod
def from_shuffle(
    cls,
    config: str | Path,
    shuffle: int,
    trainset_index: int = 0,
    modelprefix: str = "",
    snapshot: str | None = None,
    snapshot_index: int | None = None,
) -> ConditionsModelConfig:
    """Resolve a DLC BU shuffle to its model config and snapshot paths."""
    from deeplabcut.pose_estimation_pytorch.data.ctd import resolve_bu_shuffle

    loader, bu_snapshot = resolve_bu_shuffle(config, shuffle, trainset_index, modelprefix, snapshot, snapshot_index)
    return cls(
        config_path=loader.model_config_path,
        snapshot_path=bu_snapshot.path,
        scorer=loader.scorer(bu_snapshot),
    )

resolve_from_conditions classmethod

resolve_from_conditions(
    conditions: dict | ConditionsShuffleConfig | ConditionsModelConfig, config: str | Path | None = None
) -> ConditionsModelConfig

Resolve conditions input to a ConditionsModelConfig for live BUCTD inference (analyze_images / analyze_videos).

Call this in runtime code. It may touch the filesystem when resolving a ConditionsShuffleConfig to a ConditionsModelConfig.

Parameters:

Name Type Description Default

conditions

dict | ConditionsShuffleConfig | ConditionsModelConfig

A dict, ConditionsShuffleConfig, or ConditionsModelConfig.File / path conditions cannot be resolved to a BU model for live inference; they are rejected.

required

config

str | Path | None

Project config.yaml path. Required when resolving a ConditionsShuffleConfig that does not already carry one in its config attribute.

None

Returns:

Type Description
ConditionsModelConfig

A resolved ConditionsModelConfig.

Raises:

Type Description
ValueError

If conditions builds to a ConditionsFileConfig, or if a shuffle config has no project config available.

TypeError

If conditions cannot be built into a supported type.

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
@classmethod
def resolve_from_conditions(
    cls,
    conditions: dict | ConditionsShuffleConfig | ConditionsModelConfig,
    config: str | Path | None = None,
) -> ConditionsModelConfig:
    """Resolve conditions input to a ``ConditionsModelConfig`` for live BUCTD
    inference (``analyze_images`` / ``analyze_videos``).

    Call this in runtime code. It may touch the filesystem when resolving a
    ``ConditionsShuffleConfig`` to a ``ConditionsModelConfig``.

    Args:
        conditions: A dict, ``ConditionsShuffleConfig``, or
            ``ConditionsModelConfig``.File / path conditions cannot be resolved
            to a BU model for live inference; they are rejected.
        config: Project ``config.yaml`` path. Required when resolving a
            ``ConditionsShuffleConfig`` that does not already carry one in its
            ``config`` attribute.

    Returns:
        A resolved ``ConditionsModelConfig``.

    Raises:
        ValueError: If ``conditions`` builds to a ``ConditionsFileConfig``, or
            if a shuffle config has no project config available.
        TypeError: If ``conditions`` cannot be built into a supported type.
    """
    if not isinstance(conditions, ConditionsConfig):
        conditions = ConditionsConfig.build(conditions)

    if isinstance(conditions, ConditionsFileConfig):
        raise ValueError(
            "File-based conditions are for evaluation only and cannot be used "
            "for live BU inference. Provide a ConditionsModelConfig "
            "('config_path'+'snapshot_path') or a ConditionsShuffleConfig / "
            "shuffle dict."
        )
    if isinstance(conditions, cls):
        return conditions

    if not isinstance(conditions, ConditionsShuffleConfig):
        raise TypeError(
            f"Cannot resolve conditions of type {type(conditions).__name__} "
            "for live BU inference. Expected ConditionsShuffleConfig, "
            "ConditionsModelConfig, or a dict that builds to one of those."
        )
    cfg = conditions.config or (Path(config) if config is not None else None)
    if cfg is None:
        raise ValueError(
            "Cannot resolve shuffle conditions: no project config provided. "
            "Set 'config' in the shuffle conditions or pass it to "
            "resolve_from_conditions()."
        )
    return cls.from_shuffle(
        config=cfg,
        shuffle=conditions.shuffle,
        trainset_index=conditions.trainset_index,
        modelprefix=conditions.modelprefix,
        snapshot=conditions.snapshot,
        snapshot_index=conditions.snapshot_index,
    )

ConditionsShuffleConfig

Bases: ConditionsConfig

Unresolved shuffle shorthand for CTD conditions.

Stores shuffle parameters without touching the filesystem. Resolve at runtime when the project config is available:

  • Live BU inference: ConditionsModelConfig.resolve_from_conditions()
  • Evaluation predictions file: CondFromFile(config=..., shuffle=..., ...)

Attributes:

Name Type Description
shuffle int

The index of the BU shuffle to use for conditions.

config Path | None

Path to the DLC project config.yaml. Optional — can be injected later via resolve_from_conditions(config=...).

trainset_index int

The TrainingsetFraction index.

modelprefix str

The model prefix for the shuffle.

snapshot str | None

Specific snapshot filename to use. Takes priority over snapshot_index.

snapshot_index int | None

Index of the snapshot to use (default: -1, last).

Source code in deeplabcut/pose_estimation_pytorch/config/ctd_conditions.py
class ConditionsShuffleConfig(ConditionsConfig):
    """Unresolved shuffle shorthand for CTD conditions.

    Stores shuffle parameters without touching the filesystem. Resolve at runtime
    when the project config is available:

    - Live BU inference: ``ConditionsModelConfig.resolve_from_conditions()``
    - Evaluation predictions file: ``CondFromFile(config=..., shuffle=..., ...)``

    Attributes:
        shuffle: The index of the BU shuffle to use for conditions.
        config: Path to the DLC project ``config.yaml``. Optional — can be
            injected later via ``resolve_from_conditions(config=...)``.
        trainset_index: The TrainingsetFraction index.
        modelprefix: The model prefix for the shuffle.
        snapshot: Specific snapshot filename to use. Takes priority over
            ``snapshot_index``.
        snapshot_index: Index of the snapshot to use (default: -1, last).
    """

    source: Literal["shuffle"] = "shuffle"
    shuffle: int
    config: Path | None = None
    trainset_index: int = 0
    modelprefix: str = ""
    snapshot: str | None = None
    snapshot_index: int | None = None

DLCLoaderConfig

Bases: DLCBaseConfig

Configuration for DeepLabCut Loader.

Attributes:

Name Type Description
type Literal[DLCLoader]

Loader type identifier

config str | dict

Path to the DeepLabCut project config, or the project config itself

trainset_index NonNegativeInt

Index of the TrainingsetFraction for which to load data

shuffle NonNegativeInt

Index of the shuffle for which to load data

modelprefix str

The modelprefix for the shuffle

Source code in deeplabcut/pose_estimation_pytorch/config/data.py
class DLCLoaderConfig(DLCBaseConfig):
    """Configuration for DeepLabCut Loader.

    Attributes:
        type: Loader type identifier
        config: Path to the DeepLabCut project config, or the project config itself
        trainset_index: Index of the TrainingsetFraction for which to load data
        shuffle: Index of the shuffle for which to load data
        modelprefix: The modelprefix for the shuffle
    """

    type: Literal[DataLoaderType.DLCLoader]
    config: str | dict
    trainset_index: NonNegativeInt = 0
    shuffle: NonNegativeInt = 0
    modelprefix: str = ""

DataConfig

Bases: DLCBaseConfig

Complete data configuration.

Attributes:

Name Type Description
bbox_margin NonNegativeInt

Bounding box margin for top-down models

colormode Literal['RGB']

Color mode for images (e.g., 'RGB', 'BGR')

gen_sampling GenSamplingConfig | None

Generation sampling configuration

inference DataTransformationConfig | None

Inference data configuration

train DataTransformationConfig | None

Training data configuration

loader DLCLoaderConfig | COCOLoaderConfig | None

Data loader configuration

Source code in deeplabcut/pose_estimation_pytorch/config/data.py
class DataConfig(DLCBaseConfig):
    """Complete data configuration.

    Attributes:
        bbox_margin: Bounding box margin for top-down models
        colormode: Color mode for images (e.g., 'RGB', 'BGR')
        gen_sampling: Generation sampling configuration
        inference: Inference data configuration
        train: Training data configuration
        loader: Data loader configuration
    """

    bbox_margin: NonNegativeInt = 25
    colormode: Literal["RGB"] = "RGB"  # Docs state that it should never be changed to BGR
    gen_sampling: GenSamplingConfig | None = None
    inference: DataTransformationConfig | None = None
    train: DataTransformationConfig | None = None
    loader: DLCLoaderConfig | COCOLoaderConfig | None = Field(default=None, discriminator="type")

    @field_validator("train", "inference", mode="before")
    @classmethod
    def validate_transforms(cls, v):
        from deeplabcut.pose_estimation_pytorch.data import build_transforms

        try:
            build_transforms(v)
        except Exception as e:
            raise ValueError(f"Could not build transforms. Please check your config. Config: {v}; Error: {e}") from e
        return v

DataTransformationConfig

Bases: DLCBaseConfig

Data transformation configuration.

Attributes:

Name Type Description
resize dict | None

Resize transformation configuration

longest_max_size int | dict | None

Maximum size for longest edge

hflip bool | float | dict | None

Horizontal flip configuration

affine dict | None

Affine transformation configuration

random_bbox_transform dict | None

Random bbox transformation configuration

crop_sampling dict | None

Crop sampling configuration

hist_eq bool | dict | None

Whether to apply histogram equalization

motion_blur bool | dict | None

Whether to apply motion blur

covering bool | dict | None

Covering/CoarseDropout transformation configuration

elastic_transform bool | dict | None

Elastic transformation configuration

grayscale bool | dict | None

Grayscale transformation configuration

gaussian_noise bool | float | int | dict | None

Gaussian noise standard deviation

auto_padding dict | None

Auto padding configuration

normalize_images bool | dict | None

Whether to normalize images

scale_to_unit_range bool | dict | None

Whether to scale images to [0, 1] range

top_down_crop dict | None

Top-down crop configuration

collate dict | None

Collate function configuration

Source code in deeplabcut/pose_estimation_pytorch/config/data.py
class DataTransformationConfig(DLCBaseConfig):
    """Data transformation configuration.

    Attributes:
        resize: Resize transformation configuration
        longest_max_size: Maximum size for longest edge
        hflip: Horizontal flip configuration
        affine: Affine transformation configuration
        random_bbox_transform: Random bbox transformation configuration
        crop_sampling: Crop sampling configuration
        hist_eq: Whether to apply histogram equalization
        motion_blur: Whether to apply motion blur
        covering: Covering/CoarseDropout transformation configuration
        elastic_transform: Elastic transformation configuration
        grayscale: Grayscale transformation configuration
        gaussian_noise: Gaussian noise standard deviation
        auto_padding: Auto padding configuration
        normalize_images: Whether to normalize images
        scale_to_unit_range: Whether to scale images to [0, 1] range
        top_down_crop: Top-down crop configuration
        collate: Collate function configuration
    """

    resize: dict | None = None
    longest_max_size: int | dict | None = None
    hflip: bool | float | dict | None = None
    affine: dict | None = None
    random_bbox_transform: dict | None = None
    crop_sampling: dict | None = None
    hist_eq: bool | dict | None = False
    motion_blur: bool | dict | None = False
    covering: bool | dict | None = None
    elastic_transform: bool | dict | None = None
    grayscale: bool | dict | None = None
    gaussian_noise: bool | float | int | dict | None = None
    auto_padding: dict | None = None
    normalize_images: bool | dict | None = True
    scale_to_unit_range: bool | dict | None = False
    top_down_crop: dict | None = None
    collate: dict | None = None

DatasetType

Bases: str, Enum

Enumeration of dataset types.

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
class DatasetType(str, Enum):
    """Enumeration of dataset types."""

    # TODO @deruyter92 2026-02-05: Add other dataset types as needed.
    MULTIANIMAL_IMGAUG = "multi-animal-imgaug"

DetectorModelConfig

Bases: DLCBaseConfig

Configuration for detector models

Attributes:

Name Type Description
type str

Type of detector model (e.g., FasterRCNN)

freeze_bn_stats bool

Whether to freeze batch normalization statistics

freeze_bn_weights bool

Whether to freeze batch normalization weights

variant str | None

Specific variant of the detector model

Source code in deeplabcut/pose_estimation_pytorch/config/model.py
class DetectorModelConfig(DLCBaseConfig):
    """Configuration for detector models

    Attributes:
        type: Type of detector model (e.g., FasterRCNN)
        freeze_bn_stats: Whether to freeze batch normalization statistics
        freeze_bn_weights: Whether to freeze batch normalization weights
        variant: Specific variant of the detector model
    """

    type: str = ""
    freeze_bn_stats: bool = False
    freeze_bn_weights: bool = False
    variant: str | None = None
    box_score_thresh: Fraction | None = None

DetectorType

Bases: str, Enum

Enumeration of detector types.

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
class DetectorType(str, Enum):
    """Enumeration of detector types."""

    SSDLITE = "ssdlite"
    FASTERRCNN_RESNET50_FPN_V2 = "fasterrcnn_resnet50_fpn_v2"
    FASTERRCNN_MOBILENET_V3_LARGE_FPN = "fasterrcnn_mobilenet_v3_large_fpn"

EvaluationConfig

Bases: DLCBaseConfig

Configuration for evaluation metrics computation.

Attributes:

Name Type Description
pcutoff float | list[float] | dict[str, float]

Confidence threshold for RMSE computation. Can be: - float: Single threshold for all bodyparts - list[float]: One value per bodypart (and unique bodypart if any) - dict[str, float]: Mapping bodypart names to thresholds

comparison_bodyparts Literal['all'] | list[str] | None

Subset of bodyparts to compute metrics for. Can be "all", None (all bodyparts), or a list of bodypart names.

per_keypoint_evaluation bool

Whether to compute train and test RMSE for each keypoint individually.

force_multi_animal bool

If True, use multi-animal evaluation even if loader contains only a single animal.

Source code in deeplabcut/pose_estimation_pytorch/config/inference.py
class EvaluationConfig(DLCBaseConfig):
    """Configuration for evaluation metrics computation.

    Attributes:
        pcutoff: Confidence threshold for RMSE computation. Can be:
            - float: Single threshold for all bodyparts
            - list[float]: One value per bodypart (and unique bodypart if any)
            - dict[str, float]: Mapping bodypart names to thresholds
        comparison_bodyparts: Subset of bodyparts to compute metrics for.
            Can be "all", None (all bodyparts), or a list of bodypart names.
        per_keypoint_evaluation: Whether to compute train and test RMSE
            for each keypoint individually.
        force_multi_animal: If True, use multi-animal evaluation even if
            loader contains only a single animal.
    """

    mode: Literal["train", "test", "all"] = "all"
    pcutoff: float | list[float] | dict[str, float] = 0.6
    comparison_bodyparts: Literal["all"] | list[str] | None = "all"
    per_keypoint_evaluation: bool = False
    force_multi_animal: bool = False

GenSamplingConfig

Bases: DLCBaseConfig

Configuration for CTD models.

Parameters:

Name Type Description Default

keypoint_sigmas

The sigma for each keypoint.

required

keypoints_symmetry

Indices of symmetric keypoints (e.g. left/right eye)

required

jitter_prob

The probability of applying jitter. Jitter error is defined as a small displacement from the GT keypoint.

required

swap_prob

The probability of applying a swap error. Swap error represents a confusion between the same or similar parts which belong to different persons.

required

inv_prob

The probability of applying an inversion error. Inversion error occurs when a pose estimation model is confused between semantically similar parts that belong to the same instance.

required

miss_prob

The probability of applying a miss error. Miss error represents a large displacement from the GT keypoint position.

required
Source code in deeplabcut/pose_estimation_pytorch/config/data.py
class GenSamplingConfig(DLCBaseConfig):
    """Configuration for CTD models.

    Args:
        keypoint_sigmas: The sigma for each keypoint.
        keypoints_symmetry: Indices of symmetric keypoints (e.g. left/right eye)
        jitter_prob: The probability of applying jitter. Jitter error is defined as
            a small displacement from the GT keypoint.
        swap_prob: The probability of applying a swap error. Swap error represents
            a confusion between the same or similar parts which belong to different
            persons.
        inv_prob: The probability of applying an inversion error. Inversion error
            occurs when a pose estimation model is confused between semantically
            similar parts that belong to the same instance.
        miss_prob: The probability of applying a miss error. Miss error represents a
            large displacement from the GT keypoint position.
    """

    model_config = ConfigDict(frozen=True)

    keypoint_sigmas: NonNegativeFloat | list[NonNegativeFloat] = 0.1
    keypoints_symmetry: list[tuple[int, int]] | None = None
    jitter_prob: Fraction = 0.16
    swap_prob: Fraction = 0.08
    inv_prob: Fraction = 0.03
    miss_prob: Fraction = 0.10

InferenceConfig

Bases: DLCBaseConfig

Complete inference configuration.

Attributes:

Name Type Description
multithreading MultithreadingConfig

Multithreading configuration

compile CompileConfig

Compilation configuration

autocast AutocastConfig

Autocast configuration

conditions ConditionsModelConfig | ConditionsFileConfig | ConditionsShuffleConfig | None

Conditions for conditional models (CTD). File configs are evaluation-only; Shuffle/Model are used for live analyze.

snapshot int | str | list[int] | None

Snapshot(s) to use for inference

eval EvaluationConfig

Evaluation configuration

Source code in deeplabcut/pose_estimation_pytorch/config/inference.py
class InferenceConfig(DLCBaseConfig):
    """Complete inference configuration.

    Attributes:
        multithreading: Multithreading configuration
        compile: Compilation configuration
        autocast: Autocast configuration
        conditions: Conditions for conditional models (CTD). File configs are
            evaluation-only; Shuffle/Model are used for live analyze.
        snapshot: Snapshot(s) to use for inference
        eval: Evaluation configuration
    """

    multithreading: MultithreadingConfig = Field(default_factory=MultithreadingConfig)
    compile: CompileConfig = Field(default_factory=CompileConfig)
    autocast: AutocastConfig = Field(default_factory=AutocastConfig)
    conditions: ConditionsModelConfig | ConditionsFileConfig | ConditionsShuffleConfig | None = None
    snapshot: int | str | list[int] | None = None
    eval: EvaluationConfig = Field(default_factory=EvaluationConfig)
    output_dir: str | None = None

    @field_validator("conditions", mode="before")
    @classmethod
    def _normalize_conditions(cls, v: Any) -> Any:
        return ConditionsConfig.build(v)

LoggerConfig

Bases: DLCBaseConfig

Base configuration for all loggers.

Attributes:

Name Type Description
type str

The type of logger to use (WandbLogger or CSVLogger)

Source code in deeplabcut/pose_estimation_pytorch/config/logger.py
class LoggerConfig(DLCBaseConfig):
    """Base configuration for all loggers.

    Attributes:
        type: The type of logger to use (WandbLogger or CSVLogger)
    """

    type: str

MethodType

Bases: str, Enum

Enumeration of pose estimation method types.

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
class MethodType(str, Enum):
    """Enumeration of pose estimation method types."""

    BOTTOM_UP = "bu"
    TOP_DOWN = "td"
    CONDITIONAL_TOP_DOWN = "ctd"

ModelConfig

Bases: DLCBaseConfig

Complete model configuration.

Attributes:

Name Type Description
backbone dict

Backbone configuration

backbone_output_channels int | None

Number of output channels from backbone

heads dict[str, dict]

Dictionary of head configurations by name

neck dict | None

Neck configuration

pose_model dict | None

Pose model configuration

Source code in deeplabcut/pose_estimation_pytorch/config/model.py
class ModelConfig(DLCBaseConfig):
    """Complete model configuration.

    Attributes:
        backbone: Backbone configuration
        backbone_output_channels: Number of output channels from backbone
        heads: Dictionary of head configurations by name
        neck: Neck configuration
        pose_model: Pose model configuration
    """

    backbone: dict = Field(default_factory=dict)
    heads: dict[str, dict] = Field(default_factory=dict)
    backbone_output_channels: int | None = None
    neck: dict | None = None
    pose_model: dict | None = None

MultithreadingConfig

Bases: DLCBaseConfig

Multithreading configuration for inference.

Attributes:

Name Type Description
enabled bool

Whether multithreading is enabled

queue_length int

Length of the processing queue

timeout float

Timeout for processing tasks

Source code in deeplabcut/pose_estimation_pytorch/config/inference.py
class MultithreadingConfig(DLCBaseConfig):
    """Multithreading configuration for inference.

    Attributes:
        enabled: Whether multithreading is enabled
        queue_length: Length of the processing queue
        timeout: Timeout for processing tasks
    """

    enabled: bool = True
    queue_length: int = 4
    timeout: float = 30.0

NetType

Bases: str, Enum

Enumeration of network architecture types as stored in configs.

Note

Aliases (e.g. top_down_resnet_50) are user-facing names that map to a canonical member plus an optional top-down flag. See alias, from_alias, and available_aliases

Methods:

Name Description
alias

User-facing name (e.g. top_down_resnet_50 for backbone + TD).

available_aliases

All selectable model names for GUI / docs / create_training_dataset.

from_alias

Parse user-facing / legacy name → (canonical enum, top_down).

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
class NetType(str, Enum):
    """Enumeration of network architecture types as stored in configs.

    Note:
        Aliases (e.g. ``top_down_resnet_50``) are user-facing names that map to
        a canonical member plus an optional top-down flag. See ``alias``,
        ``from_alias``, and ``available_aliases``
    """

    RESNET_50 = "resnet_50"
    RESNET_101 = "resnet_101"

    HRNET_W18 = "hrnet_w18"
    HRNET_W32 = "hrnet_w32"
    HRNET_W48 = "hrnet_w48"

    CSPNEXT_S = "cspnext_s"
    CSPNEXT_M = "cspnext_m"
    CSPNEXT_X = "cspnext_x"

    DEKR_W18 = "dekr_w18"
    DEKR_W32 = "dekr_w32"
    DEKR_W48 = "dekr_w48"

    CTD_COAM_W32 = "ctd_coam_w32"
    CTD_COAM_W48 = "ctd_coam_w48"
    CTD_COAM_W48_HUMAN = "ctd_coam_w48_human"
    CTD_PRENET_HRNET_W32 = "ctd_prenet_hrnet_w32"
    CTD_PRENET_HRNET_W48 = "ctd_prenet_hrnet_w48"
    CTD_PRENET_RTMPOSE_S = "ctd_prenet_rtmpose_s"
    CTD_PRENET_RTMPOSE_M = "ctd_prenet_rtmpose_m"
    CTD_PRENET_RTMPOSE_X = "ctd_prenet_rtmpose_x"
    CTD_PRENET_RTMPOSE_X_HUMAN = "ctd_prenet_rtmpose_x_human"

    DLCRNET_STRIDE16_MS5 = "dlcrnet_stride16_ms5"
    DLCRNET_STRIDE32_MS5 = "dlcrnet_stride32_ms5"

    RTMPOSE_S = "rtmpose_s"
    RTMPOSE_M = "rtmpose_m"
    RTMPOSE_X = "rtmpose_x"

    ANIMALTOKENPOSE_BASE = "animaltokenpose_base"

    @functools.cached_property
    def is_backbone(self) -> bool:
        from deeplabcut.pose_estimation_pytorch.config.utils import (
            get_config_folder_path,
            load_backbones,
        )

        return self.value in frozenset(load_backbones(get_config_folder_path()))

    def alias(self, *, top_down: bool = False) -> str:
        """User-facing name (e.g. ``top_down_resnet_50`` for backbone + TD)."""
        if top_down and self.is_backbone:
            return f"{_TOP_DOWN_PREFIX}{self.value}"
        return self.value

    @classmethod
    def from_alias(cls, label: str) -> tuple[NetType, bool]:
        """Parse user-facing / legacy name → (canonical enum, top_down)."""
        label = _LEGACY_NET_TYPE_ALIASES.get(label, label)
        label_has_td_prefix = False
        if label.startswith(_TOP_DOWN_PREFIX):
            label = label.removeprefix(_TOP_DOWN_PREFIX)
            label_has_td_prefix = True
        return cls(label), label_has_td_prefix

    @classmethod
    def available_aliases(cls) -> list[str]:
        """All selectable model names for GUI / docs / ``create_training_dataset``."""
        labels: list[str] = []
        for net_type in cls:
            labels.append(net_type.alias(top_down=False))
            if net_type.is_backbone:
                labels.append(net_type.alias(top_down=True))
        return sorted(labels)

alias

alias(*, top_down: bool = False) -> str

User-facing name (e.g. top_down_resnet_50 for backbone + TD).

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
def alias(self, *, top_down: bool = False) -> str:
    """User-facing name (e.g. ``top_down_resnet_50`` for backbone + TD)."""
    if top_down and self.is_backbone:
        return f"{_TOP_DOWN_PREFIX}{self.value}"
    return self.value

available_aliases classmethod

available_aliases() -> list[str]

All selectable model names for GUI / docs / create_training_dataset.

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
@classmethod
def available_aliases(cls) -> list[str]:
    """All selectable model names for GUI / docs / ``create_training_dataset``."""
    labels: list[str] = []
    for net_type in cls:
        labels.append(net_type.alias(top_down=False))
        if net_type.is_backbone:
            labels.append(net_type.alias(top_down=True))
    return sorted(labels)

from_alias classmethod

from_alias(label: str) -> tuple[NetType, bool]

Parse user-facing / legacy name → (canonical enum, top_down).

Source code in deeplabcut/pose_estimation_pytorch/config/enums.py
@classmethod
def from_alias(cls, label: str) -> tuple[NetType, bool]:
    """Parse user-facing / legacy name → (canonical enum, top_down)."""
    label = _LEGACY_NET_TYPE_ALIASES.get(label, label)
    label_has_td_prefix = False
    if label.startswith(_TOP_DOWN_PREFIX):
        label = label.removeprefix(_TOP_DOWN_PREFIX)
        label_has_td_prefix = True
    return cls(label), label_has_td_prefix

OptimizerConfig

Bases: DLCBaseConfig

Optimizer configuration.

Attributes:

Name Type Description
type str

Optimizer type (e.g., AdamW, SGD)

params dict[str, Any] | None

Optimizer parameters

Source code in deeplabcut/pose_estimation_pytorch/config/runner.py
class OptimizerConfig(DLCBaseConfig):
    """Optimizer configuration.

    Attributes:
        type: Optimizer type (e.g., AdamW, SGD)
        params: Optimizer parameters
    """

    type: str = ""
    params: dict[str, Any] | None = None

PoseConfig

Bases: DLCVersionedConfig

Main configuration class for DeepLabCut pose estimation models.

This is the top-level configuration that brings together all the different configuration domains (project, model, data, training, etc.).

Attributes:

Name Type Description
net_type NetType

Network architecture type (e.g., resnet_50, hrnet_w32, dlcrnet_stride16_ms5)

method MethodType

Method type (bu=Bottom-Up, td=Top-Down, ctd=Conditional Top-Down)

device str

Device configuration (auto, cpu, cuda)

project str

Project configuration (skeleton, individuals, etc.)

model ModelConfig

Model configuration (backbone, heads, etc.)

detector DetectorConfig | None

Detector configuration (for top-down models)

data DataConfig

Data configuration (loaders, transforms, etc.)

training DataConfig

Training configuration (runner, optimizer, etc.)

inference InferenceConfig

Inference configuration (multithreading, compilation, etc.)

logger CSVLoggerConfig | WandbLoggerConfig | None

Logger configuration (e.g., WandB or CSV logger)

with_center_keypoints bool

Whether to include center keypoints (for DEKR models)

Methods:

Name Description
build

Build a typed PoseConfig for a project

Source code in deeplabcut/pose_estimation_pytorch/config/pose.py
class PoseConfig(DLCVersionedConfig):
    """Main configuration class for DeepLabCut pose estimation models.

    This is the top-level configuration that brings together all the different
    configuration domains (project, model, data, training, etc.).

    Attributes:
        net_type: Network architecture type (e.g., resnet_50, hrnet_w32, dlcrnet_stride16_ms5)
        method: Method type (bu=Bottom-Up, td=Top-Down, ctd=Conditional Top-Down)
        device: Device configuration (auto, cpu, cuda)
        project: Project configuration (skeleton, individuals, etc.)
        model: Model configuration (backbone, heads, etc.)
        detector: Detector configuration (for top-down models)
        data: Data configuration (loaders, transforms, etc.)
        training: Training configuration (runner, optimizer, etc.)
        inference: Inference configuration (multithreading, compilation, etc.)
        logger: Logger configuration (e.g., WandB or CSV logger)
        with_center_keypoints: Whether to include center keypoints (for DEKR models)
    """

    model: ModelConfig = Field(default_factory=ModelConfig)
    net_type: NetType = NetType.RESNET_50
    method: MethodType = MethodType.BOTTOM_UP
    device: str = "auto"
    metadata: PoseMetadata
    data: DataConfig
    runner: RunnerConfig
    train_settings: TrainSettingsConfig
    inference: InferenceConfig = Field(default_factory=InferenceConfig)
    logger: CSVLoggerConfig | WandbLoggerConfig | None = Field(default=None, discriminator="type")
    with_center_keypoints: bool = False
    detector: DetectorConfig | None = None
    resume_training_from: str | None = None

    @field_validator("net_type", mode="before")
    @classmethod
    def _coerce_net_type(cls, v: object) -> NetType:
        if isinstance(v, NetType):
            return v
        net_type, _ = NetType.from_alias(str(v))
        return net_type

    @classmethod
    def build(
        cls,
        project_config: ProjectConfig | dict | Path | str,
        pose_config_path: str | Path,
        *,
        top_down: bool,
        multi_animal: bool | None = None,
        net_type: NetType | str | None = None,
        detector_type: DetectorType | str | None = None,
        weight_init: WeightInitialization | dict | Path | str | None = None,
        ctd_conditions: int | str | Path | tuple[int, str] | tuple[int, int] | None = None,
        save: bool = False,
    ) -> Self:
        """Build a typed PoseConfig for a project

        Args:
            project_config (ProjectConfig | dict | Path | str): The project configuration.
            pose_config_path (str | Path): The path to the pose configuration.
            top_down (bool): Whether to use a top-down backbone.
            net_type (NetType | str | None, optional): The network architecture type (without 'top_down_' prefix).
                If None, the default net type from the project config will be used.
            detector_type (DetectorType | str | None, optional): The detector architecture. Required for td models.
            weight_init (WeightInitialization | None, optional): The weight initialization object or path.
            ctd_conditions (int | str | Path | tuple[int, str] | tuple[int, int] | None, optional):
                The conditional top-down conditions. Only required for CTD models.
                A predictions file path is evaluation-only; shuffle refs work for
                both evaluation and live analyze.
            save (bool, optional): Whether to save the pose configuration.

        Note:
            For generic backbone models, ``method`` is resolved from ``top_down``. For non-backbone models,
            the ``top_down`` is ignored and ``method`` is resolved from the default config.
        """
        from deeplabcut.core.weight_init import WeightInitialization

        # Normalize input parameters + set defaults if not provided
        project_config = ProjectConfig.from_any(project_config)
        if multi_animal is None:
            multi_animal = project_config.multianimalproject
        net_type, task = resolve_net_type_and_task(
            net_type,
            default=project_config.default_net_type,
            top_down=top_down,
        )
        if detector_type is not None:
            detector_type = DetectorType(detector_type)
        if weight_init is not None:
            weight_init = WeightInitialization.from_any(weight_init)

        # Build related configurations (PoseMetadata, PAFParameters, DetectorConfig)
        metadata = PoseMetadata.build(project_config, pose_config_path=pose_config_path)
        paf_parameters = None
        detector_config = None
        if task == Task.BOTTOM_UP and multi_animal:
            paf_parameters = PAFParameters.build(project_config)
        elif task == Task.TOP_DOWN:
            detector_config = DetectorConfig.build(metadata.num_individuals, detector_type)

        # Build the pose model config
        defaults: dict = build_pose_config_defaults(
            net_type=net_type,
            metadata=metadata,
            paf_parameters=paf_parameters,
            weight_init=weight_init,
            task=task,
            multi_animal=multi_animal,
            detector_config=detector_config,
            ctd_conditions=ctd_conditions,
        )
        pose_config = cls.from_dict(defaults)

        # Save if needed
        if save:
            pose_config.to_yaml(pose_config_path, overwrite=True)

        return pose_config

    @classmethod
    def build_for_superanimal_inference(
        cls,
        super_animal: str,
        *,
        model_name: str,
        detector_name: str | None = None,
        max_individuals: int = 30,
        device: str | None = None,
    ) -> Self:
        from deeplabcut.pose_estimation_pytorch.modelzoo.config import build_superanimal_inference_config

        metadata = PoseMetadata.build_for_superanimal(
            super_animal=super_animal, model_name=model_name, max_individuals=max_individuals
        )
        return cls.from_dict(
            build_superanimal_inference_config(
                super_animal=super_animal,
                model_name=model_name,
                detector_name=detector_name,
                metadata=metadata,
                device=device,
            )
        )

    @classmethod
    def build_for_superanimal_finetune(
        cls,
        project_config: ProjectConfig | dict | Path | str,
        *,
        model_name: str,
        detector_name: str | None,
        pose_config_path: str | Path,
        weight_init: WeightInitialization,
        inference_config: InferenceConfig | dict | Path | str | None = None,
        save: bool = False,
    ) -> Self:
        from deeplabcut.pose_estimation_pytorch.modelzoo.config import build_superanimal_finetune_config

        # Normalize input parameters + build related configurations
        project_config = ProjectConfig.from_any(project_config)
        if inference_config is None:
            inference_config = InferenceConfig()
        else:
            inference_config = InferenceConfig.from_any(inference_config)
        metadata = PoseMetadata.build(project_config, pose_config_path=pose_config_path)

        # Input validation
        if weight_init.dataset is None:
            raise ValueError("`WeightInitialization.dataset` is required for fine-tuning SuperAnimal models.")

        if not weight_init.with_decoder:
            raise ValueError(
                "`weight_init.with_decoder=True` is required for fine-tuning SuperAnimal models."
                "Please set `with_decoder=True` to fine-tune a model, or create a transfer learning config instead."
            )

        # Build the pose configuration
        pose_config = cls.from_dict(
            build_superanimal_finetune_config(
                weight_init,
                metadata,
                model_name,
                detector_name,
                inference_config=inference_config,
            )
        )

        if save:
            pose_config.to_yaml(metadata.pose_config_path, overwrite=True)
        return pose_config

build classmethod

build(
    project_config: ProjectConfig | dict | Path | str,
    pose_config_path: str | Path,
    *,
    top_down: bool,
    multi_animal: bool | None = None,
    net_type: NetType | str | None = None,
    detector_type: DetectorType | str | None = None,
    weight_init: WeightInitialization | dict | Path | str | None = None,
    ctd_conditions: int | str | Path | tuple[int, str] | tuple[int, int] | None = None,
    save: bool = False
) -> Self

Build a typed PoseConfig for a project

Parameters:

Name Type Description Default

project_config

ProjectConfig | dict | Path | str

The project configuration.

required

pose_config_path

str | Path

The path to the pose configuration.

required

top_down

bool

Whether to use a top-down backbone.

required

net_type

NetType | str | None

The network architecture type (without 'top_down_' prefix). If None, the default net type from the project config will be used.

None

detector_type

DetectorType | str | None

The detector architecture. Required for td models.

None

weight_init

WeightInitialization | None

The weight initialization object or path.

None

ctd_conditions

int | str | Path | tuple[int, str] | tuple[int, int] | None

The conditional top-down conditions. Only required for CTD models. A predictions file path is evaluation-only; shuffle refs work for both evaluation and live analyze.

None

save

bool

Whether to save the pose configuration.

False
Note

For generic backbone models, method is resolved from top_down. For non-backbone models, the top_down is ignored and method is resolved from the default config.

Source code in deeplabcut/pose_estimation_pytorch/config/pose.py
@classmethod
def build(
    cls,
    project_config: ProjectConfig | dict | Path | str,
    pose_config_path: str | Path,
    *,
    top_down: bool,
    multi_animal: bool | None = None,
    net_type: NetType | str | None = None,
    detector_type: DetectorType | str | None = None,
    weight_init: WeightInitialization | dict | Path | str | None = None,
    ctd_conditions: int | str | Path | tuple[int, str] | tuple[int, int] | None = None,
    save: bool = False,
) -> Self:
    """Build a typed PoseConfig for a project

    Args:
        project_config (ProjectConfig | dict | Path | str): The project configuration.
        pose_config_path (str | Path): The path to the pose configuration.
        top_down (bool): Whether to use a top-down backbone.
        net_type (NetType | str | None, optional): The network architecture type (without 'top_down_' prefix).
            If None, the default net type from the project config will be used.
        detector_type (DetectorType | str | None, optional): The detector architecture. Required for td models.
        weight_init (WeightInitialization | None, optional): The weight initialization object or path.
        ctd_conditions (int | str | Path | tuple[int, str] | tuple[int, int] | None, optional):
            The conditional top-down conditions. Only required for CTD models.
            A predictions file path is evaluation-only; shuffle refs work for
            both evaluation and live analyze.
        save (bool, optional): Whether to save the pose configuration.

    Note:
        For generic backbone models, ``method`` is resolved from ``top_down``. For non-backbone models,
        the ``top_down`` is ignored and ``method`` is resolved from the default config.
    """
    from deeplabcut.core.weight_init import WeightInitialization

    # Normalize input parameters + set defaults if not provided
    project_config = ProjectConfig.from_any(project_config)
    if multi_animal is None:
        multi_animal = project_config.multianimalproject
    net_type, task = resolve_net_type_and_task(
        net_type,
        default=project_config.default_net_type,
        top_down=top_down,
    )
    if detector_type is not None:
        detector_type = DetectorType(detector_type)
    if weight_init is not None:
        weight_init = WeightInitialization.from_any(weight_init)

    # Build related configurations (PoseMetadata, PAFParameters, DetectorConfig)
    metadata = PoseMetadata.build(project_config, pose_config_path=pose_config_path)
    paf_parameters = None
    detector_config = None
    if task == Task.BOTTOM_UP and multi_animal:
        paf_parameters = PAFParameters.build(project_config)
    elif task == Task.TOP_DOWN:
        detector_config = DetectorConfig.build(metadata.num_individuals, detector_type)

    # Build the pose model config
    defaults: dict = build_pose_config_defaults(
        net_type=net_type,
        metadata=metadata,
        paf_parameters=paf_parameters,
        weight_init=weight_init,
        task=task,
        multi_animal=multi_animal,
        detector_config=detector_config,
        ctd_conditions=ctd_conditions,
    )
    pose_config = cls.from_dict(defaults)

    # Save if needed
    if save:
        pose_config.to_yaml(pose_config_path, overwrite=True)

    return pose_config

PoseMetadata

Bases: DLCBaseConfig

Methods:

Name Description
build

Get metadata from a project configuration with optional overrides

Source code in deeplabcut/pose_estimation_pytorch/config/metadata.py
class PoseMetadata(DLCBaseConfig):
    project_path: Path | None = None
    pose_config_path: Path | None = None
    bodyparts: UniqueStrList = Field(default_factory=list)
    unique_bodyparts: UniqueStrList = Field(default_factory=list, json_schema_extra={"aliases": ["uniquebodyparts"]})
    individuals: UniqueStrList = Field(default_factory=lambda: ["individual_1"])

    # TODO @deruyter92 2026-06-09: Nullable field to support old configs with empty identity field -> fix in v1
    with_identity: bool | None = Field(default=None, json_schema_extra={"aliases": ["identity"]})

    @property
    def num_individuals(self) -> int:
        return len(self.individuals)

    @property
    def num_bodyparts(self) -> int:
        return len(self.bodyparts)

    @property
    def num_unique_bodyparts(self) -> int:
        return len(self.unique_bodyparts) if self.unique_bodyparts is not None else 0

    @classmethod
    def build(
        cls,
        project_config: ProjectConfig | dict | Path | str,
        *,
        project_path: Path | str | None = None,
        pose_config_path: Path | str | None = None,
        bodyparts: list[str] | None = None,
        unique_bodyparts: list[str] | None = None,
        individuals: list[str] | None = None,
        with_identity: bool | None = None,
    ) -> Self:
        """Get metadata from a project configuration with optional overrides"""
        cfg = ProjectConfig.from_any(project_config)

        # Conversions for diverging fields in ProjectConfig
        cfg_bodyparts = cfg.bodyparts_list
        cfg_unique_bodyparts = cfg.uniquebodyparts
        cfg_with_identity = cfg.identity

        return cls(
            project_path=project_path if project_path is not None else cfg.project_path,
            pose_config_path=pose_config_path if pose_config_path is not None else cfg.pose_config_path,
            bodyparts=bodyparts if bodyparts is not None else cfg_bodyparts,
            unique_bodyparts=unique_bodyparts if unique_bodyparts is not None else cfg_unique_bodyparts,
            individuals=individuals if individuals is not None else cfg.individuals,
            with_identity=with_identity if with_identity is not None else cfg_with_identity,
        )

    @classmethod
    def build_for_superanimal(cls, super_animal: str, model_name: str, max_individuals: int) -> Self:
        from deeplabcut.pose_estimation_pytorch.modelzoo.config import build_superanimal_metadata

        metadata = build_superanimal_metadata(
            super_animal=super_animal,
            model_name=model_name,
            max_individuals=max_individuals,
        )
        return cls.from_dict(metadata)

    # NOTE @deruyter92 2026-06-12
    # This serves as a replacement for pose_estimation_pytorch.config.make_basic_project_config.
    # It can safely be removed when we stop supporting that API. Prefer PoseMetadata(..) instead.
    def to_dict_legacy(self) -> dict:
        return dict(
            project_path=self.project_path,
            multianimalproject=self.num_individuals > 1,
            bodyparts=self.bodyparts if self.num_individuals <= 1 else "MULTI!",
            multianimalbodyparts=self.bodyparts if self.num_individuals > 1 else None,
            uniquebodyparts=[],
            individuals=self.individuals,
        )

build classmethod

build(
    project_config: ProjectConfig | dict | Path | str,
    *,
    project_path: Path | str | None = None,
    pose_config_path: Path | str | None = None,
    bodyparts: list[str] | None = None,
    unique_bodyparts: list[str] | None = None,
    individuals: list[str] | None = None,
    with_identity: bool | None = None
) -> Self

Get metadata from a project configuration with optional overrides

Source code in deeplabcut/pose_estimation_pytorch/config/metadata.py
@classmethod
def build(
    cls,
    project_config: ProjectConfig | dict | Path | str,
    *,
    project_path: Path | str | None = None,
    pose_config_path: Path | str | None = None,
    bodyparts: list[str] | None = None,
    unique_bodyparts: list[str] | None = None,
    individuals: list[str] | None = None,
    with_identity: bool | None = None,
) -> Self:
    """Get metadata from a project configuration with optional overrides"""
    cfg = ProjectConfig.from_any(project_config)

    # Conversions for diverging fields in ProjectConfig
    cfg_bodyparts = cfg.bodyparts_list
    cfg_unique_bodyparts = cfg.uniquebodyparts
    cfg_with_identity = cfg.identity

    return cls(
        project_path=project_path if project_path is not None else cfg.project_path,
        pose_config_path=pose_config_path if pose_config_path is not None else cfg.pose_config_path,
        bodyparts=bodyparts if bodyparts is not None else cfg_bodyparts,
        unique_bodyparts=unique_bodyparts if unique_bodyparts is not None else cfg_unique_bodyparts,
        individuals=individuals if individuals is not None else cfg.individuals,
        with_identity=with_identity if with_identity is not None else cfg_with_identity,
    )

RunnerConfig

Bases: DLCBaseConfig

Training runner configuration.

Attributes:

Name Type Description
type str

Runner type (e.g., PoseTrainingRunner)

gpus Any | None

GPU configuration

key_metric str

Key metric for evaluation

key_metric_asc bool

Whether key metric should be ascending

eval_interval int

Evaluation interval in epochs

optimizer OptimizerConfig | None

Optimizer configuration

scheduler SchedulerConfig | None

Scheduler configuration

snapshots SnapshotCheckpointConfig | None

Snapshot configuration

load_weights_only bool | None

Value for torch.load() weights_only parameter

Source code in deeplabcut/pose_estimation_pytorch/config/runner.py
class RunnerConfig(DLCBaseConfig):
    """Training runner configuration.

    Attributes:
        type: Runner type (e.g., PoseTrainingRunner)
        gpus: GPU configuration
        key_metric: Key metric for evaluation
        key_metric_asc: Whether key metric should be ascending
        eval_interval: Evaluation interval in epochs
        optimizer: Optimizer configuration
        scheduler: Scheduler configuration
        snapshots: Snapshot configuration
        load_weights_only: Value for torch.load() weights_only parameter
    """

    type: str = "PoseTrainingRunner"
    # TODO @deruyter92: Currently different configs for device are used in
    # parallel. We should probably move to only 'PoseConfig.device'. This is
    # kept here for backwards compatibility.
    gpus: Any | None = None
    device: str = "auto"  # <- unused, but present in test scripts.
    key_metric: str = "test.mAP"
    key_metric_asc: bool = True
    eval_interval: int = 10
    optimizer: OptimizerConfig | None = None
    scheduler: SchedulerConfig | None = None
    snapshots: SnapshotCheckpointConfig | None = None
    snapshot_prefix: str | None = None
    load_weights_only: bool | None = None

SchedulerConfig

Bases: DLCBaseConfig

Learning rate scheduler configuration.

Attributes:

Name Type Description
type str

Scheduler type (e.g., LRListScheduler, CosineAnnealingLR, SequentialLR)

params dict[str, Any] | None

Scheduler parameters

Source code in deeplabcut/pose_estimation_pytorch/config/runner.py
class SchedulerConfig(DLCBaseConfig):
    """Learning rate scheduler configuration.

    Attributes:
        type: Scheduler type (e.g., LRListScheduler, CosineAnnealingLR, SequentialLR)
        params: Scheduler parameters
    """

    type: str = ""
    params: dict[str, Any] | None = None

SnapshotCheckpointConfig

Bases: DLCBaseConfig

Snapshot configuration for model checkpoints.

Attributes:

Name Type Description
max_snapshots int

Maximum number of snapshots to keep

save_epochs int

Interval for saving snapshots

save_optimizer_state bool

Whether to save optimizer state

Source code in deeplabcut/pose_estimation_pytorch/config/runner.py
class SnapshotCheckpointConfig(DLCBaseConfig):
    """Snapshot configuration for model checkpoints.

    Attributes:
        max_snapshots: Maximum number of snapshots to keep
        save_epochs: Interval for saving snapshots
        save_optimizer_state: Whether to save optimizer state
    """

    max_snapshots: int = 5
    save_epochs: int = 25
    save_optimizer_state: bool = False

TestConfig

Bases: DLCBaseConfig

Configuration class for DeepLabCut test/inference settings.

This configuration is used for downstream tracking and evaluation, containing the essential metadata about joints and network architecture.

Attributes:

Name Type Description
dataset Path

Path to the project/dataset.

dataset_type DatasetType

Type of dataset (required for downstream tracking).

num_joints NonNegativeInt

Total number of joints (bodyparts + unique bodyparts).

all_joints list[list[NonNegativeInt]]

List of joint indices, each as a single-element list.

all_joints_names UniqueStrList

List of joint names.

net_type NetType

Network architecture type.

global_scale Fraction

Global scale factor for inference.

scoremap_dir Path

Directory for score maps.

Source code in deeplabcut/pose_estimation_pytorch/config/pose.py
class TestConfig(DLCBaseConfig):
    """Configuration class for DeepLabCut test/inference settings.

    This configuration is used for downstream tracking and evaluation, containing
    the essential metadata about joints and network architecture.

    Attributes:
        dataset: Path to the project/dataset.
        dataset_type: Type of dataset (required for downstream tracking).
        num_joints: Total number of joints (bodyparts + unique bodyparts).
        all_joints: List of joint indices, each as a single-element list.
        all_joints_names: List of joint names.
        net_type: Network architecture type.
        global_scale: Global scale factor for inference.
        scoremap_dir: Directory for score maps.
    """

    # TODO @deruyter92 2026-02-05: Is this additional configuration really needed?
    # We could aim for using the PoseConfig class or InferenceConfig class instead.
    dataset: Path = Path()
    num_joints: NonNegativeInt = 0
    all_joints: list[list[NonNegativeInt]] = Field(default_factory=list)
    all_joints_names: UniqueStrList = Field(default_factory=list)
    net_type: NetType = NetType.RESNET_50
    dataset_type: DatasetType = DatasetType.MULTIANIMAL_IMGAUG
    global_scale: Fraction = 1.0
    scoremap_dir: Path = Path()

    @classmethod
    def build(
        cls,
        pose_config: PoseConfig | dict | Path | str,
        *,
        dataset_type: DatasetType = DatasetType.MULTIANIMAL_IMGAUG,
        scoremap_dir: Path | str = "test",
        test_config_path: Path | str | None = None,
        global_scale: Fraction = 1.0,
        save: bool = False,
    ) -> Self:

        # Needs a validated PoseConfig
        cfg = PoseConfig.from_any(pose_config)
        metadata = cfg.metadata

        # Build the test config
        test_config = cls(
            dataset=cfg.metadata.project_path,
            dataset_type=dataset_type,  # required for downstream tracking
            num_joints=metadata.num_bodyparts + metadata.num_unique_bodyparts,
            all_joints=[[i] for i in range(metadata.num_bodyparts + metadata.num_unique_bodyparts)],
            all_joints_names=metadata.bodyparts + metadata.unique_bodyparts,
            net_type=cfg.net_type,
            global_scale=global_scale,
            scoremap_dir=scoremap_dir,
        )

        # Save if needed
        if save:
            if test_config_path is None:
                raise ValueError("test_config_path is required to save the test config.")
            test_config.to_yaml(test_config_path, overwrite=True)

        return test_config

TrainSettingsConfig

Bases: DLCBaseConfig

Training settings configuration.

Attributes:

Name Type Description
batch_size int

Training batch size

dataloader_workers int

Number of data loader workers

dataloader_pin_memory bool

Whether to pin memory in data loader

display_iters int

Display interval for training progress

epochs int

Number of training epochs

seed int

Random seed for reproducibility

weight_init WeightInitialization | None

Weight initialization configuration

Source code in deeplabcut/pose_estimation_pytorch/config/training.py
class TrainSettingsConfig(DLCBaseConfig):
    """Training settings configuration.

    Attributes:
        batch_size: Training batch size
        dataloader_workers: Number of data loader workers
        dataloader_pin_memory: Whether to pin memory in data loader
        display_iters: Display interval for training progress
        epochs: Number of training epochs
        seed: Random seed for reproducibility
        weight_init: Weight initialization configuration
    """

    batch_size: int = 8
    dataloader_workers: int = 0
    dataloader_pin_memory: bool = False
    display_iters: int = 500
    epochs: int = 200
    seed: int = 42
    # @TODO @deruyter92 2026-02-13: V0 pipeline uses None for default initialization
    # (with ImageNet weights). We should update this to explicit WeightInitialization.
    weight_init: WeightInitialization | None = None

WandbLoggerConfig

Bases: LoggerConfig

Configuration for Weights & Biases (wandb) logger.

This logger tracks experiments and logs data to Weights & Biases. Refer to: https://docs.wandb.ai/guides for more information.

Attributes:

Name Type Description
type Literal[WandbLogger]

Logger type (should be 'WandbLogger')

project_name str

The name of the wandb project

run_name str

The name of the wandb run

image_log_interval int | None

How often train/test images are logged in epochs (if None, train/test inputs are never logged)

model dict | None

The model architecture to log

train_folder str | None

The path of the folder containing training files.

wandb_kwargs dict | None

Additional keyword arguments to pass to wandb.init

Source code in deeplabcut/pose_estimation_pytorch/config/logger.py
class WandbLoggerConfig(LoggerConfig):  #
    """Configuration for Weights & Biases (wandb) logger.

    This logger tracks experiments and logs data to Weights & Biases.
    Refer to: https://docs.wandb.ai/guides for more information.

    Attributes:
        type: Logger type (should be 'WandbLogger')
        project_name: The name of the wandb project
        run_name: The name of the wandb run
        image_log_interval: How often train/test images are logged in epochs
            (if None, train/test inputs are never logged)
        model: The model architecture to log
        train_folder: The path of the folder containing training files.
        wandb_kwargs: Additional keyword arguments to pass to wandb.init
    """

    type: Literal[LoggerType.WandbLogger]
    project_name: str = "deeplabcut"
    run_name: str = "tmp"
    image_log_interval: int | None = None
    model: dict | None = None
    train_folder: str | None = None
    wandb_kwargs: dict | None = None

available_detectors

available_detectors() -> list[str]

Returns: all the possible detectors that can be used

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def available_detectors() -> list[str]:
    """Returns: all the possible detectors that can be used"""
    return load_detectors(get_config_folder_path())

available_models

available_models() -> list[str]

Returns: the possible variants of models that can be used

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def available_models() -> list[str]:
    """Returns: the possible variants of models that can be used"""
    configs_folder_path = get_config_folder_path()
    backbones = load_backbones(configs_folder_path)
    models = set()
    for backbone in backbones:
        models.add(backbone)
        models.add("top_down_" + backbone)

    other_architectures = [
        p for p in configs_folder_path.iterdir() if p.is_dir() and p.name not in ("backbones", "base", "detectors")
    ]
    for folder in other_architectures:
        variants = [p.stem for p in folder.iterdir() if p.suffix == ".yaml"]
        for variant in variants:
            models.add(variant)

    return list(sorted(models))

get_config_folder_path

get_config_folder_path() -> Path

Returns: the Path to the folder containing the "configs" for DeepLabCut 3.0

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def get_config_folder_path() -> Path:
    """Returns: the Path to the folder containing the "configs" for DeepLabCut 3.0"""
    dlc_parent_path = auxiliaryfunctions.get_deeplabcut_path()
    return dlc_parent_path / "pose_estimation_pytorch" / "config"

is_model_cond_top_down

is_model_cond_top_down(net_type: str) -> bool

Checks whether a given net_type is conditional top-down or not.

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def is_model_cond_top_down(net_type: str) -> bool:
    """Checks whether a given net_type is conditional top-down or not."""
    if net_type not in available_models():
        raise ValueError(f"Model {net_type} is not part of available models, which are {str(available_models())}")

    if net_type.startswith("ctd_"):
        return True
    else:
        return False

is_model_top_down

is_model_top_down(net_type: str) -> bool

Checks whenever a given net_type is top-down or not.

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def is_model_top_down(net_type: str) -> bool:
    """Checks whenever a given net_type is top-down or not."""
    if net_type not in available_models():
        raise ValueError(f"Model {net_type} is not part of available models, which are {str(available_models())}")

    configs_dir = get_config_folder_path()
    backbones = load_backbones(configs_dir)

    if net_type.startswith("top_down_"):
        return True
    elif net_type in backbones:
        return False

    configs_dir = get_config_folder_path()

    architecture = net_type.split("_")[0]

    cfg_path = configs_dir / architecture / f"{net_type}.yaml"
    model_cfg = read_config_as_dict(cfg_path)

    return model_cfg.get("method", "BU").upper() == "TD"

load_backbones

load_backbones(configs_dir: Path) -> list[str]

Load backbones.

Parameters:

Name Type Description Default

configs_dir

Path

the Path to the folder containing the "configs" for PyTorch DeepLabCut

required

Returns:

Type Description
list[str]

all backbones with default configurations that can be used

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def load_backbones(configs_dir: Path) -> list[str]:
    """Load backbones.

    Args:
        configs_dir: the Path to the folder containing the "configs" for PyTorch
            DeepLabCut

    Returns:
        all backbones with default configurations that can be used
    """
    backbone_dir = configs_dir / "backbones"
    backbones = [p.stem for p in backbone_dir.iterdir() if p.suffix == ".yaml"]
    return backbones

load_base_config

load_base_config(config_folder_path: Path) -> dict

Returns: the base configuration for all PyTorch DeepLabCut models

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def load_base_config(config_folder_path: Path) -> dict:
    """Returns: the base configuration for all PyTorch DeepLabCut models"""
    base_dir = config_folder_path / "base"
    base_config = read_config_as_dict(base_dir / "base.yaml")
    return base_config

load_detectors

load_detectors(configs_dir: Path) -> list[str]

Load detectors.

Parameters:

Name Type Description Default

configs_dir

Path

the Path to the folder containing the "configs" for PyTorch DeepLabCut

required

Returns:

Type Description
list[str]

all detectors that are available

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
def load_detectors(configs_dir: Path) -> list[str]:
    """Load detectors.

    Args:
        configs_dir: the Path to the folder containing the "configs" for PyTorch
            DeepLabCut

    Returns:
        all detectors that are available
    """
    detector_dir = configs_dir / "detectors"
    detectors = [p.stem for p in detector_dir.iterdir() if p.suffix == ".yaml"]
    return detectors

make_basic_project_config

make_basic_project_config(
    dataset_path: Path | str, bodyparts: list[str], max_individuals: int, multi_animal: bool = True
) -> dict

Deprecated factory for basic config dict for non-DLC projects.

Source code in deeplabcut/pose_estimation_pytorch/config/make_pose_config.py
@deprecated(replacement="pose_estimation_pytorch.config.PoseMetadata", since="3.0.1")
def make_basic_project_config(
    dataset_path: Path | str,
    bodyparts: list[str],
    max_individuals: int,
    multi_animal: bool = True,
) -> dict:
    """Deprecated factory for basic config dict for non-DLC projects."""
    return PoseMetadata(
        project_path=dataset_path,
        bodyparts=bodyparts,
        individuals=[f"individual{i:03d}" for i in range(max_individuals)],
    ).to_dict_legacy()

pretty_print

pretty_print(config: dict, indent: int = 0, print_fn: Callable[[str], None] | None = None) -> None

Prints a model configuration in a pretty and readable way.

Parameters:

Name Type Description Default

config

dict

the config to print

required

indent

int

the base indent on all keys

0

print_fn

Callable[[str], None] | None

custom function to call (simply calls print if None)

None
Source code in deeplabcut/core/config/utils.py
def pretty_print(
    config: dict,
    indent: int = 0,
    print_fn: Callable[[str], None] | None = None,
) -> None:
    """Prints a model configuration in a pretty and readable way.

    Args:
        config: the config to print
        indent: the base indent on all keys
        print_fn: custom function to call (simply calls ``print`` if None)
    """
    if print_fn is None:
        print_fn = print

    for k, v in config.items():
        if isinstance(v, dict):
            print_fn(f"{indent * ' '}{k}:")
            pretty_print(v, indent + 2, print_fn=print_fn)
        else:
            print_fn(f"{indent * ' '}{k}: {v}")

read_config_as_dict

read_config_as_dict(config_path: str | Path) -> dict

Parameters:

Name Type Description Default

config_path

str | Path

the path to the configuration file to load

required

Returns:

Type Description
dict

The configuration file with pure Python classes

Raises:

Type Description
FileNotFoundError

if the config file does not exist

Source code in deeplabcut/core/config/utils.py
def read_config_as_dict(config_path: str | Path) -> dict:
    """
    Args:
        config_path: the path to the configuration file to load

    Returns:
        The configuration file with pure Python classes

    Raises:
        FileNotFoundError: if the config file does not exist
    """
    if not Path(config_path).exists():
        raise FileNotFoundError(f"Config {config_path} is not found. Please make sure that the file exists.")
    with open(config_path) as f:
        cfg = get_yaml_loader().load(f)
    if cfg is None:
        raise ValueError(f"Config {config_path} is empty or null.")
    if not isinstance(cfg, dict):
        raise ValueError(f"Config {config_path} must be a YAML mapping at the top level, got {type(cfg).__name__}.")
    return cfg

replace_default_values

replace_default_values(
    config: dict | list,
    num_bodyparts: int | None = None,
    num_individuals: int | None = None,
    backbone_output_channels: int | None = None,
    **kwargs
) -> dict

Replaces placeholder values in a model configuration with their actual values.

This method allows to create template PyTorch configurations for models with values such as "num_bodyparts", which are replaced with the number of bodyparts for a project when making its Pytorch configuration.

This code can also do some basic arithmetic. You can write "num_bodyparts x 2" (or any factor other than 2) for location refinement channels, and the number of channels will be twice the number of bodyparts. You can write "backbone_output_channels // 2" for the number of channels in a layer, and it will be half the number of channels output by the backbone. You can write "num_bodyparts + 1" (such as for DEKR heatmaps, where a "center" bodypart is added).

The three base placeholder values that can be computed are "num_bodyparts", "num_individuals" and "backbone_output_channels". You can add more through the keyword arguments (such as "paf_graph": list[tuple[int, int]] or "paf_edges_to_keep": list[int] for DLCRNet models).

Parameters:

Name Type Description Default

config

dict | list

the configuration in which to replace default values

required

num_bodyparts

int | None

the number of bodyparts

None

num_individuals

int | None

the number of individuals

None

backbone_output_channels

int | None

the number of backbone output channels

None

kwargs

other placeholder values to fill in

{}

Returns:

Type Description
dict

the configuration with placeholder values replaced

Raises:

Type Description
ValueError

If there is a placeholder value who's "updated" value was not given to the method

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
@ensure_plain_config
def replace_default_values(
    config: dict | list,
    num_bodyparts: int | None = None,
    num_individuals: int | None = None,
    backbone_output_channels: int | None = None,
    **kwargs,
) -> dict:
    """Replaces placeholder values in a model configuration with their actual values.

    This method allows to create template PyTorch configurations for models with values
    such as "num_bodyparts", which are replaced with the number of bodyparts for a
    project when making its Pytorch configuration.

    This code can also do some basic arithmetic. You can write "num_bodyparts x 2" (or
    any factor other than 2) for location refinement channels, and the number of
    channels will be twice the number of bodyparts. You can write
    "backbone_output_channels // 2" for the number of channels in a layer, and it will
    be half the number of channels output by the backbone. You can write
    "num_bodyparts + 1" (such as for DEKR heatmaps, where a "center" bodypart is added).

    The three base placeholder values that can be computed are "num_bodyparts",
    "num_individuals" and "backbone_output_channels". You can add more through the
    keyword arguments (such as "paf_graph": list[tuple[int, int]] or
    "paf_edges_to_keep": list[int] for DLCRNet models).

    Args:
        config: the configuration in which to replace default values
        num_bodyparts: the number of bodyparts
        num_individuals: the number of individuals
        backbone_output_channels: the number of backbone output channels
        kwargs: other placeholder values to fill in

    Returns:
        the configuration with placeholder values replaced

    Raises:
        ValueError: If there is a placeholder value who's "updated" value was not
            given to the method
    """

    def get_updated_value(variable: str) -> int | list[int]:
        var_parts = variable.strip().split(" ")
        var_name = var_parts[0]
        if updated_values[var_name] is None:
            raise ValueError(
                f"Found {variable} in the configuration file, but there is no default value for this variable."
            )

        if len(var_parts) == 1:
            return updated_values[var_name]
        elif len(var_parts) == 3:
            operator, factor = var_parts[1], var_parts[2]
            if not factor.isdigit():
                raise ValueError(f"F must be an integer in variable: {variable}")

            factor = int(factor)
            if operator == "+":
                return updated_values[var_name] + factor
            elif operator == "x":
                return updated_values[var_name] * factor
            elif operator == "//":
                return updated_values[var_name] // factor
            else:
                raise ValueError(f"Unknown operator for variable: {variable}")

        raise ValueError(f"Found {variable} in the configuration file, but cannot parse it.")

    updated_values = {
        "num_bodyparts": num_bodyparts,
        "num_individuals": num_individuals,
        "backbone_output_channels": backbone_output_channels,
        **kwargs,
    }

    config = copy.deepcopy(config)
    if isinstance(config, dict):
        keys_to_update = list(config.keys())
    elif isinstance(config, list):
        keys_to_update = range(len(config))
    else:
        raise ValueError(f"Config to update must be dict or list, found {type(config)}")

    for k in keys_to_update:
        if isinstance(config[k], (list, dict)):
            config[k] = replace_default_values(
                config[k],
                num_bodyparts,
                num_individuals,
                backbone_output_channels,
                **kwargs,
            )
        elif isinstance(config[k], str) and config[k].strip().split(" ")[0] in updated_values.keys():
            config[k] = get_updated_value(config[k])

    return config

update_config

update_config(config: dict, updates: dict, copy_original: bool = True) -> dict

Deprecated helper for updating config dictionaries.

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
@deprecated(replacement=None, since="3.0.1")
def update_config(config: dict, updates: dict, copy_original: bool = True) -> dict:
    """Deprecated helper for updating config dictionaries."""
    from deeplabcut.pose_estimation_pytorch.config.make_pose_config import _update_config

    return _update_config(config, updates, copy_original)

update_config_by_dotpath

update_config_by_dotpath(config: dict, updates: dict, copy_original: bool = True) -> dict

Deprecated helper for updating config dictionaries using dot notation. DLCBaseConfig.set_nested (new in 3.0.1) can be used instead (not identical).

Updates items in the configuration file using dot notation for nested keys

The configuration dict should only be composed of primitive Python types (dict, list and values). This is the case when reading the file using read_config_as_dict.

Parameters:

Name Type Description Default

config

dict

the configuration dict to update

required

updates

dict

single-level dict with dot notation keys indicating nested paths e.g. {"device": "cuda", "runner.gpus": [0,1]}

required

copy_original

bool

whether to copy the original dict before updating it

True

Returns:

Type Description
dict

the updated dictionary

Source code in deeplabcut/pose_estimation_pytorch/config/utils.py
@deprecated(replacement=None, since="3.0.1")
def update_config_by_dotpath(config: dict, updates: dict, copy_original: bool = True) -> dict:
    """Deprecated helper for updating config dictionaries using dot notation.
    ``DLCBaseConfig.set_nested`` (new in 3.0.1) can be used instead (not identical).

    Updates items in the configuration file using dot notation for nested keys

    The configuration dict should only be composed of primitive Python types
    (dict, list and values). This is the case when reading the file using
    `read_config_as_dict`.

    Args:
        config: the configuration dict to update
        updates: single-level dict with dot notation keys indicating nested paths
            e.g. {"device": "cuda", "runner.gpus": [0,1]}
        copy_original: whether to copy the original dict before updating it

    Returns:
        the updated dictionary
    """
    if copy_original:
        config = copy.deepcopy(config)

    for key, value in updates.items():
        # Split key into parts by dots
        parts = key.split(".")

        # Handle non-nested case
        if len(parts) == 1:
            config[key] = copy.deepcopy(value)
            continue

        # Navigate to nested location
        current = config
        for part in parts[:-1]:
            if part not in current or current[part] is None:
                current[part] = {}
            current = current[part]

        # Set the value at final location
        current[parts[-1]] = copy.deepcopy(value)

    return config

write_config

write_config(config_path: str | Path, config: dict, overwrite: bool = True) -> None

Writes a pose configuration file to disk.

Parameters:

Name Type Description Default

config_path

str | Path

the path where the config should be saved

required

config

dict

the config to save

required

overwrite

bool

whether to overwrite the file if it already exists

True
Source code in deeplabcut/core/config/utils.py
def write_config(config_path: str | Path, config: dict, overwrite: bool = True) -> None:
    """Writes a pose configuration file to disk.

    Args:
        config_path: the path where the config should be saved
        config: the config to save
        overwrite: whether to overwrite the file if it already exists

    Raises:
        FileExistsError if overwrite=True and the file already exists
    """
    if not overwrite and Path(config_path).exists():
        raise FileExistsError(f"Cannot write to {config_path} - set overwrite=True to force")

    with open(config_path, "w") as file:
        get_yaml_dumper().dump(config, file)