ndx-pose Extension for NWB
ndx-pose is a standardized format for storing pose estimation data in NWB, such as from DeepLabCut, SLEAP, and DANNCE. Please post an issue or PR to suggest or add support for another pose estimation tool.
Data types overview
This extension consists of several new neurodata types. They are divided into two main categories:
- Pose estimation data: This includes the estimated positions of body parts (keypoints) over time, along with metadata about the pose estimation process.
- Training data: This includes ground truth data for training pose estimation models, such as labeled images and video frames.
Pose estimation data types
Skeletonwhich stores the relationship between the body parts (nodes and edges).Skeletonswhich is a container that stores multipleSkeletonobjects.PoseEstimationSerieswhich stores the estimated positions (x, y) or (x, y, z) of a body part over time as well as optionally the confidence/likelihood of the estimated positions.PoseEstimationwhich stores the estimated position data (PoseEstimationSeries) for multiple body parts, computed from a single camera view with the same tool/algorithm, and links to theDevice(camera) used.
Multi-camera 3D pose estimation types
For multi-camera setups that produce 3D world-space coordinates (e.g. DANNCE, Anipose):
CalibratedCamerawhich extendsDevicewith intrinsic and extrinsic calibration parameters (intrinsic matrix, rotation matrix, translation vector, distortion coefficients) for that single camera. Because it is aDevice, it is added once to the NWBFile and can be linked to by reference from multiplePoseEstimationobjects (e.g., one per subject in a multi-subject session), so the camera rig and its calibration are never duplicated.MultiCameraPoseEstimationwhich stores 3D world-spacePoseEstimationSeries, onePoseEstimationper camera view (holding that camera's 2D pixel-space estimates and its device link), and an optional link to aSkeleton.
Training data types
SkeletonInstancewhich stores the estimated positions and visibility of the body parts for a single frame.TrainingFramewhich stores the ground truth data for a single frame. It containsSkeletonInstanceobjects and references a frame of a source video (ImageSeries). The source videos can be stored internally as data arrays or externally as files referenced by relative file path.TrainingFrameswhich is a container that stores multipleTrainingFrameobjects.SourceVideoswhich is a container that stores multipleImageSeriesobjects representing source videos used in training.PoseTrainingwhich is a container that stores the ground truth data (TrainingFrames) and source videos (SourceVideos) used to train the pose estimation model.
It is recommended to place the Skeletons, PoseEstimation, MultiCameraPoseEstimation, and PoseTraining objects
in an NWB processing module named "behavior", as shown below.
Installation
pip install "ndx-pose"
Development installation
Development dependencies are defined as PEP 735 dependency groups in
pyproject.toml. Installing them requires pip 25.1 or later. To set up an editable install with the development
tools (tests, docs, and linters), run:
git clone https://github.com/rly/ndx-pose.git
cd ndx-pose
pip install -e . --group dev
The test, docs, and min-reqs groups can be installed individually with pip install -e . --group <name>.
Usage examples
Handling pose estimates for multiple subjects
NWB files are designed to store data from a single subject and have only one root-level Subject object.
As a result, ndx-pose was designed to store pose estimates from a single subject.
Pose estimates data from different subjects should be stored in separate NWB files.
Training images can involve multiple skeletons, however. These training images may be the same across subjects, and therefore the same across NWB files. These training images should be duplicated between files.
Resources
Utilities to convert DLC output to/from NWB
- For multi-animal projects, one NWB file is created per animal. The NWB file contains only a
PoseEstimationobject under/processing/behavior. ThatPoseEstimationobject containsPoseEstimationSeriesobjects, one for each body part, and general metadata about the pose estimation process, skeleton, and videos. ThePoseEstimationSeriesobjects contain the estimated positions for that body part for a particular animal.
Utilities to convert SLEAP pose tracking data to/from NWB
- Used by SLEAP (
sleap.io.dataset.Labels.export_nwb) - See also sleap/io/format/ndx_pose.py
- Supports read of
PoseEstimationobjects from NWB files.
- NeuroConv supports converting data from DeepLabCut, SLEAP (using
sleap_iodescribed above), and LightningPose to NWB. It also supports appending pose estimation data to an existing NWB file.
Ethome: Tools for machine learning of animal behavior
- Supports read of
PoseEstimationobjects from NWB files.
Related work:
Several NWB datasets use ndx-pose 0.1.1:
- A detailed behavioral, videographic, and neural dataset on object recognition in mice
- IBL Brain Wide Map
Several open-source conversion scripts on GitHub also use ndx-pose.
Diagram of pose estimation types
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', 'primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%%
classDiagram
direction LR
namespace ndx-pose {
class PoseEstimationSeries{
<<SpatialSeries>>
name : str
description : str
timestamps : array[float; dims [frame]]
data : array[float; dims [frame, [x, y]] or [frame, [x, y, z]]]
confidence : array[float; dims [frame]], optional
reference_frame: str
}
class PoseEstimation {
<<NWBDataInterface>>
name : str
description : str, optional
original_videos : array[str; dims [file]], optional, deprecated
labeled_videos : array[str; dims [file]], optional, deprecated
dimensions : array[uint, dims [file, [width, height]]], optional, deprecated
scorer : str, optional
source_software : str, optional
source_software__version : str, optional
PoseEstimationSeries
Skeleton, link, optional
device : Device, link, optional
source_video : ImageSeries, link, optional
labeled_video : ImageSeries, link, optional
}
class CalibratedCamera {
<<Device>>
intrinsic_matrix : array[float; dims [3, 3]]
rotation_matrix : array[float; dims [3, 3]], optional
translation_vector : array[float; dims [3]], optional
distortion_coefficients : array[float; dims [N]], optional
}
class MultiCameraPoseEstimation {
<<NWBDataInterface>>
description : str, optional
scorer : str, optional
source_software : str, optional
source_software__version : str, optional
PoseEstimationSeries (3D world-space)
PoseEstimation (one per camera view)
Skeleton, link, optional
}
class Skeletons {
<<NWBDataInterface>>
Skeleton
}
class Skeleton {
<<NWBDataInterface>>
name : str
nodes : array[str; dims [body part]]
edges : array[uint; dims [edge, [node, node]]]
subject: link (to pynwb.Subject), optional
}
}
class Device
class ImageSeries
PoseEstimation --o PoseEstimationSeries : contains 0 or more
PoseEstimation --> Skeleton : links to
PoseEstimation --> Device : links to (device)
PoseEstimation --> ImageSeries : links to (source_video)
PoseEstimation --> ImageSeries : links to (labeled_video)
CalibratedCamera --|> Device : extends
MultiCameraPoseEstimation --o PoseEstimationSeries : contains 0 or more
MultiCameraPoseEstimation --o PoseEstimation : contains 0 or more
MultiCameraPoseEstimation --> Skeleton : links to
Skeletons --o Skeleton : contains 0 or more
Diagram of all types
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#ffffff', 'primaryBorderColor': '#144E73', 'lineColor': '#D96F32'}}}%%
classDiagram
direction LR
namespace ndx-pose {
class PoseEstimationSeries{
<<SpatialSeries>>
name : str
description : str
timestamps : array[float; dims [frame]]
data : array[float; dims [frame, [x, y]] or [frame, [x, y, z]]]
confidence : array[float; dims [frame]], optional
reference_frame: str
}
class PoseEstimation {
<<NWBDataInterface>>
name : str
description : str, optional
original_videos : array[str; dims [file]], optional, deprecated
labeled_videos : array[str; dims [file]], optional, deprecated
dimensions : array[uint, dims [file, [width, height]]], optional, deprecated
scorer : str, optional
source_software : str, optional
source_software__version : str, optional
PoseEstimationSeries
Skeleton, link, optional
device : Device, link, optional
source_video : ImageSeries, link, optional
labeled_video : ImageSeries, link, optional
}
class CalibratedCamera {
<<Device>>
intrinsic_matrix : array[float; dims [3, 3]]
rotation_matrix : array[float; dims [3, 3]], optional
translation_vector : array[float; dims [3]], optional
distortion_coefficients : array[float; dims [N]], optional
}
class MultiCameraPoseEstimation {
<<NWBDataInterface>>
description : str, optional
scorer : str, optional
source_software : str, optional
source_software__version : str, optional
PoseEstimationSeries (3D world-space)
PoseEstimation (one per camera view)
Skeleton, link, optional
}
class Skeleton {
<<NWBDataInterface>>
name : str
nodes : array[str; dims [body part]]
edges : array[uint; dims [edge, [node, node]]]
}
class TrainingFrame {
<<NWBDataInterface>>
name : str
annotator : str, optional
source_video_frame_index : uint, optional
skeleton_instances : SkeletonInstances
source_video : ImageSeries, link, optional
source_frame : Image, link, optional
}
class SkeletonInstance {
<<NWBDataInterface>>
id: uint, optional
node_locations : array[float; dims [body part, [x, y]] or [body part, [x, y, z]]]
node_visibility : array[bool; dims [body part]], optional
Skeleton, link
}
class TrainingFrames {
<<NWBDataInterface>>
TrainingFrame
}
class SkeletonInstances {
<<NWBDataInterface>>
SkeletonInstance
}
class SourceVideos {
<<NWBDataInterface>>
ImageSeries
}
class Skeletons {
<<NWBDataInterface>>
Skeleton
}
class PoseTraining {
<<NWBDataInterface>>
training_frames : TrainingFrames, optional
source_videos : SourceVideos, optional
}
}
class Device
class ImageSeries
class Image
PoseEstimation --o PoseEstimationSeries : contains 0 or more
PoseEstimation --> Skeleton : links to
PoseEstimation --> Device : links to (device)
PoseEstimation --> ImageSeries : links to (source_video)
PoseEstimation --> ImageSeries : links to (labeled_video)
CalibratedCamera --|> Device : extends
MultiCameraPoseEstimation --o PoseEstimationSeries : contains 0 or more
MultiCameraPoseEstimation --o PoseEstimation : contains 0 or more
MultiCameraPoseEstimation --> Skeleton : links to
PoseTraining --o TrainingFrames : contains
PoseTraining --o SourceVideos : contains
TrainingFrames --o TrainingFrame : contains 0 or more
TrainingFrame --o SkeletonInstances : contains
TrainingFrame --> ImageSeries : links to
TrainingFrame --> Image : links to
SkeletonInstances --o SkeletonInstance : contains 0 or more
SkeletonInstance --> Skeleton : links to
SourceVideos --o ImageSeries : contains 0 or more
Skeletons --o Skeleton : contains 0 or more
Contributors
- @rly
- @bendichter
- @AlexEMG
- @roomrys
- @CBroz1
- @h-mayorquin
- @talmo
- @eberrigan
- @pauladkisson
- @alessandratrapani
This extension was created using ndx-template.
Metadata
Release files for ndx-pose 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ndx_pose-0.4.0.tar.gz | 182.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ndx_pose-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 203.1 kB
Release files / ndx_pose-0.4.0.tar.gz
| Download URL | ndx_pose-0.4.0.tar.gz |
|---|---|
| Size | 182.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5c5aaf5d56cd612e21bfee0841a14406f1414673f05d549e02170fc86e2aa75f
|
|
BLAKE2b-256 checksum How to use checksums |
8a46a90fc0d993dbdb594b9b70aad504f6c632238b447399e17901e305ae3ce4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / ndx_pose-0.4.0-py3-none-any.whl
| Download URL | ndx_pose-0.4.0-py3-none-any.whl |
|---|---|
| Size | 20.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5e9c77ebe7e776b3047cba38db31de004948225d1832ee314b43b16d1568da5e
|
|
BLAKE2b-256 checksum How to use checksums |
17eba5b8de21ec44cf52c4c06b09d3d23a0dee9e47ccb7d1684ae792748b7df1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|