Skip to content

deeplabcut.pose_estimation_pytorch.config.make_pose_config

Methods to create the configuration files for PyTorch DeepLabCut models.

Functions:

Name Description
build_detector_config_defaults

Adds a detector to a model.

build_pose_config_defaults

Load the model config defaults (from model-specific yaml) for a given project and net_type.

make_basic_project_config

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

resolve_net_type_and_task

Resolve the net type from build args and project config default.

build_detector_config_defaults

build_detector_config_defaults(num_individuals: int, detector_type: DetectorType) -> dict

Adds a detector to a model.

Parameters:

Name Type Description Default

configs_dir

path to the DeepLabCut "configs" directory

required

num_individuals

int

the maximum number of individuals the model should detect

required

detector_type

DetectorType

the type of detector to use (if None, uses ssdlite)

required

Returns:

Type Description
dict

the model configuration with an added detector config

Source code in deeplabcut/pose_estimation_pytorch/config/make_pose_config.py
def build_detector_config_defaults(
    num_individuals: int,
    detector_type: DetectorType,
) -> dict:
    """Adds a detector to a model.

    Args:
        configs_dir: path to the DeepLabCut "configs" directory
        num_individuals: the maximum number of individuals the model should detect
        detector_type: the type of detector to use (if None, uses ``ssdlite``)

    Returns:
        the model configuration with an added detector config
    """
    configs_dir = get_config_folder_path()
    detector_config = _update_config(
        read_config_as_dict(configs_dir / "base" / "base_detector.yaml"),
        read_config_as_dict(configs_dir / "detectors" / f"{detector_type.value}.yaml"),
    )
    detector_config = replace_default_values(
        detector_config,
        num_individuals=num_individuals,
    )
    return dict(sorted(detector_config.items()))

build_pose_config_defaults

build_pose_config_defaults(
    net_type: NetType,
    metadata: PoseMetadata,
    *,
    task: Task,
    multi_animal: bool,
    paf_parameters: PAFParameters | None = None,
    weight_init: WeightInitialization | None = None,
    detector_config: DetectorConfig | None = None,
    ctd_conditions: int | str | Path | tuple[int, str] | tuple[int, int] | None = None
) -> dict

Load the model config defaults (from model-specific yaml) for a given project and net_type.

The base/ folder contains default configurations, such as data augmentations or heatmap heads (that can be used to predict pose or identity based on visual features). These files are used to create pose model configurations.

All available backbone configurations are stored in the backbones/ folder. - any backbone can be a single animal model with a heatmap head added on top - any backbone can be a top-down model with a detector and a heatmap head - any backbone can be a bottom-up model with a detector and a heatmap + PAF head

All other model architectures have their own folders, with different variants available. Top-down model architectures must specify method: TD in their configuration files, from which this method adds a backbone configuration.

Placeholder values (such as num_bodyparts or num_individuals) are filled in based on the project config file.

Parameters:

Name Type Description Default

project_config

the DeepLabCut project config (used to infer individuals, bodyparts and identity tracking)

required

net_type

NetType

the architecture of the desired pose estimation model

required

task

Task

when the net_type is a backbone, whether to create a top-down model by associating a detector to the pose model. Required for multi-animal projects when net_type is a backbone (as a backbone + heatmap head can only predict pose for single individuals).

required

detector_type

for top-down pose models, the architecture of the desired object detection model

required

ctd_conditions

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

int | str | Path | tuple[int, str] | tuple[int, int] , optional, default = None, If using a conditional-top-down (CTD) net_type, this argument needs to be specified. It defines the conditions that will be used with the CTD model. It can be either: * A shuffle number (ctd_conditions: int), which must correspond to a bottom-up (BU) network type. Valid for both evaluation and live analyze. * A predictions file path (ctd_conditions: string | Path), which must correspond to a .json or .h5 predictions file. Evaluation-only — not valid for analyze_images / analyze_videos. * A shuffle number and a particular snapshot (ctd_conditions: tuple[int, str] | tuple[int, int]), which respectively correspond to a bottom-up (BU) network type and a particular snapshot name or index.

None

Returns:

Type Description
dict

The model configuration defaults as a dictionary.

Source code in deeplabcut/pose_estimation_pytorch/config/make_pose_config.py
def build_pose_config_defaults(
    net_type: NetType,
    metadata: PoseMetadata,
    *,
    task: Task,
    multi_animal: bool,
    paf_parameters: PAFParameters | None = None,
    weight_init: WeightInitialization | None = None,
    detector_config: DetectorConfig | None = None,
    ctd_conditions: int | str | Path | tuple[int, str] | tuple[int, int] | None = None,
) -> dict:
    """
    Load the model config defaults (from model-specific yaml) for a given project and net_type.

    The base/ folder contains default configurations, such as data augmentations or
    heatmap heads (that can be used to predict pose or identity based on visual
    features). These files are used to create pose model configurations.

    All available backbone configurations are stored in the backbones/ folder.
        - any backbone can be a single animal model with a heatmap head added on top
        - any backbone can be a top-down model with a detector and a heatmap head
        - any backbone can be a bottom-up model with a detector and a heatmap + PAF head

    All other model architectures have their own folders, with different variants
    available. Top-down model architectures must specify `method: TD` in their
    configuration files, from which this method adds a backbone configuration.

    Placeholder values (such as `num_bodyparts` or `num_individuals`) are filled in
    based on the project config file.

    Args:
        project_config: the DeepLabCut project config (used to infer individuals, bodyparts and identity tracking)
        net_type: the architecture of the desired pose estimation model
        task: when the net_type is a backbone, whether to create a top-down model
            by associating a detector to the pose model. Required for multi-animal
            projects when net_type is a backbone (as a backbone + heatmap head can only
            predict pose for single individuals).
        detector_type: for top-down pose models, the architecture of the desired object
            detection model
        ctd_conditions: int | str | Path | tuple[int, str] | tuple[int, int] , optional, default = None,
            If using a conditional-top-down (CTD) net_type, this argument needs to be specified.
            It defines the conditions that will be used with the CTD model.
            It can be either:
                * A shuffle number (ctd_conditions: int), which must correspond to a bottom-up (BU) network type.
                  Valid for both evaluation and live analyze.
                * A predictions file path (ctd_conditions: string | Path), which must correspond to a .json or .h5
                predictions file. Evaluation-only — not valid for ``analyze_images`` / ``analyze_videos``.
                * A shuffle number and a particular snapshot (ctd_conditions: tuple[int, str] | tuple[int, int]), which
                respectively correspond to a bottom-up (BU) network type and a particular snapshot name or index.


    Returns:
        The model configuration defaults as a dictionary.
    """
    configs_dir = get_config_folder_path()
    base_cfg = load_base_config(configs_dir)
    backbones = load_backbones(configs_dir)

    if net_type in backbones:
        if task == Task.BOTTOM_UP and multi_animal:
            if paf_parameters is None:
                raise ValueError("PAF parameters are required for multi-animal bottom-up models.")
            model_cfg = _create_backbone_with_paf_model(
                configs_dir=configs_dir,
                net_type=net_type,
                num_individuals=metadata.num_individuals,
                bodyparts=metadata.bodyparts,
                paf_parameters=paf_parameters.to_dict(),
            )
        else:
            model_cfg = _create_backbone_with_heatmap_model(
                configs_dir=configs_dir,
                net_type=net_type,
                multianimal_project=multi_animal,
                bodyparts=metadata.bodyparts,
                top_down=task == Task.TOP_DOWN,
            )
    else:
        architecture = net_type.value.split("_")[0]
        default_value_kwargs = {}
        if architecture == "dlcrnet":
            if paf_parameters is None:
                raise ValueError("PAF parameters are required for DLCRNet models.")
            default_value_kwargs.update(paf_parameters.to_dict())

        cfg_path = configs_dir / architecture / f"{net_type.value}.yaml"
        model_cfg = read_config_as_dict(cfg_path)
        model_cfg = replace_default_values(
            model_cfg,
            num_bodyparts=metadata.num_bodyparts,
            num_individuals=metadata.num_individuals,
            **default_value_kwargs,
        )
    model_cfg["net_type"] = net_type.value

    if task == Task.TOP_DOWN:
        if detector_config is None:
            raise ValueError("detector_config is required for top-down pose configs.")
        model_cfg["detector"] = detector_config.to_dict()

    # add the default augmentations to the config
    aug_filename = "aug_default.yaml" if task == Task.BOTTOM_UP else "aug_top_down.yaml"
    aug_cfg = {"data": read_config_as_dict(configs_dir / "base" / aug_filename)}

    model_cfg = _update_config(model_cfg, aug_cfg)
    model_cfg = _update_config(base_cfg, model_cfg)

    # add a unique bodypart head if needed
    if metadata.unique_bodyparts:
        if task != Task.BOTTOM_UP:
            raise ValueError(
                f"You selected a top-down model architecture ({net_type.value}), but you have"
                f" unique bodyparts, which is not yet implemented for top-down models."
                " Please select a bottom-up architecture such as `resnet_50` for single"
                " animal projects or `dlcrnet_50` for multi-animal projects."
            )

        model_cfg = _add_unique_bodypart_head(
            configs_dir,
            model_cfg,
            num_unique_bodyparts=metadata.num_unique_bodyparts,
            backbone_output_channels=model_cfg["model"]["backbone_output_channels"],
        )

    # add an identity head if needed
    if metadata.with_identity:
        if task != Task.BOTTOM_UP:
            raise ValueError(
                f"You selected a top-down model architecture ({net_type.value}), but you have"
                f" set `identity: true`, which is not yet implemented for top-down"
                f" models. Please select a bottom-up architecture such as `dlcrnet_50`"
                f" to train with identity, or set `identity: false`."
            )

        model_cfg = _add_identity_head(
            configs_dir,
            model_cfg,
            num_individuals=metadata.num_individuals,
            backbone_output_channels=model_cfg["model"]["backbone_output_channels"],
        )

    model_cfg["inference"] = InferenceConfig().to_dict()
    # Add conditions for CTD models if specified
    if task == Task.COND_TOP_DOWN:
        if ctd_conditions is None:
            raise ValueError("A CTD conditions is required for conditional-top-down models.")
        _add_ctd_conditions(model_cfg, ctd_conditions)

    # Add metadata and weight init to the model config
    model_cfg["metadata"] = metadata.to_dict()
    if weight_init is not None:
        model_cfg["train_settings"]["weight_init"] = weight_init.to_dict()
    return model_cfg

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()

resolve_net_type_and_task

resolve_net_type_and_task(net_type: str | NetType | None, *, default: str, top_down: bool) -> tuple[NetType, Task]

Resolve the net type from build args and project config default.

Parameters:

Name Type Description Default

net_type

str | None

Architecture name, or None to use default from project config.

required

default

str

Fallback when net_type is None. Invalid values warn and fall back to resnet_50.

required

top_down

bool

Build a top-down backbone (ignored for non-backbones).

required

Returns:

Type Description
(NetType, Task)

the resolved canonical NetType and Task

Source code in deeplabcut/pose_estimation_pytorch/config/make_pose_config.py
def resolve_net_type_and_task(
    net_type: str | NetType | None,
    *,
    default: str,
    top_down: bool,
) -> tuple[NetType, Task]:
    """Resolve the net type from build args and project config default.

    Args:
        net_type (str | None): Architecture name, or None to use ``default``
            from project config.
        default (str): Fallback when ``net_type`` is None. Invalid values warn
            and fall back to ``resnet_50``.
        top_down (bool): Build a top-down backbone (ignored for non-backbones).

    Returns:
        (NetType, Task): the resolved canonical NetType and Task
    """
    if net_type is None:
        try:
            net_type, td_prefix = NetType.from_alias(default)
        except ValueError as e:
            raise ValueError(
                f"Invalid default_net_type in project config: {default}. Must be one of {NetType.available_aliases()}"
            ) from e
    else:
        net_type, td_prefix = NetType.from_alias(str(net_type))  # fails loudly if invalid

    if td_prefix:
        if top_down:
            logger.warning(
                "Passed net_type with top_down prefix. Instead use "
                "PoseConfig.build(..., top_down=True) to specify the task."
            )
        else:
            raise ValueError(
                "Passed net_type with top_down prefix. but top_down is False."
                "Please use only PoseConfig.build(..., top_down=True/False) to specify the task."
            )
    task = _resolve_task(net_type, top_down=top_down)
    return net_type, task