Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of a PoseTraining Group #9

Merged
merged 6 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 105 additions & 15 deletions spec/ndx-pose.extensions.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@
groups:
- neurodata_type_def: Skeleton
neurodata_type_inc: NWBDataInterface
default_name: Skeleton
doc: Group that holds node and edge data for defining parts of a pose and their
connections to one another.
attributes:
- name: id
dtype: text
doc: Unique ID associated with the skeleton.
datasets:
- name: nodes
dtype: text
dims:
- num_body_parts
shape:
- null
doc: Array of body part names corresponding to the names of the PoseEstimationSeries
objects or PoseTraining objects.
- name: edges
dtype: uint8
dims:
- num_edges
- nodes_index, nodes_index
shape:
- null
- 2
doc: Array of pairs of indices corresponding to edges between nodes. Index values
correspond to row indices of the 'nodes' dataset. Index values use 0-indexing.
quantity: '?'
- neurodata_type_def: PoseEstimationSeries
neurodata_type_inc: SpatialSeries
doc: Estimated position (x, y) or (x, y, z) of a body part over time.
Expand Down Expand Up @@ -92,27 +121,88 @@ groups:
dtype: text
doc: Version string of the software tool used.
required: false
- name: nodes
groups:
- neurodata_type_inc: PoseEstimationSeries
doc: Estimated position data for each body part.
quantity: '*'
links:
- target_type: Skeleton
doc: Layout of body part locations and connections.
- neurodata_type_def: TrainingFrame
neurodata_type_inc: NWBDataInterface
default_name: TrainingFrame
doc: Group that holds ground-truth position data for all instances of a skeleton in a single frame.
attributes:
- name: annotator
dtype: text
dims:
- num_body_parts
shape:
- null
doc: Array of body part names corresponding to the names of the PoseEstimationSeries
objects within this group.
doc: Name of annotator who labeled the TrainingFrame.
required: false
groups:
- neurodata_type_inc: Instance
doc: Position data for a single instance of a skeleton in a single training frame.
quantity: '*'
- name: source_video
roomrys marked this conversation as resolved.
Show resolved Hide resolved
neurodata_type_inc: ImageSeries
doc: Path to original video file and frame used.
quantity: '?'
- name: edges
attributes:
- name: frame_index
dtype: uint8
doc: Frame index of TrainingFrame in original video file.
required: true
- name: source_frame
neurodata_type_inc: Images
doc: Collection of images used for training (stored internally or externally).
quantity: 1
attributes:
- name: images_index
dtype: uint8
doc: Index of TrainingFrame in collection of frames stored in Images.
required: true
rly marked this conversation as resolved.
Show resolved Hide resolved
- neurodata_type_def: Instance
neurodata_type_inc: NWBDataInterface
default_name: Instance
doc: Group that holds ground-truth pose data for single subject in a single frame.
attributes:
- name: id
dtype: uint8
doc: ID used to differentiate instances.
roomrys marked this conversation as resolved.
Show resolved Hide resolved
required: false
datasets:
- name: node_locations
dtype: float
dims:
- num_edges
- nodes_index, nodes_index
- - num_body_parts
- x, y
- - num_body_parts
- x, y, z
shape:
- - null
- 2
- - null
- 3
doc: Locations (x, y) or (x, y, z) of nodes for single skeleton instance in single frame.
- name: node_visibility
dtype: bool
dims:
- num_body_parts
shape:
- null
- 2
doc: Array of pairs of indices corresponding to edges between nodes. Index values
correspond to row indices of the 'nodes' dataset. Index values use 0-indexing.
doc: Markers for node visibility where true corresponds to a visible node and
false corresponds to an occluded node.
quantity: '?'
links:
- target_type: Skeleton
doc: Layout of body part locations and connections.
- neurodata_type_def: PoseTraining
neurodata_type_inc: NWBDataInterface
default_name: PoseTraining
doc: Group that holds images, ground-truth annotations, and metadata for training
a pose estimator.
groups:
- neurodata_type_inc: PoseEstimationSeries
doc: Estimated position data for each body part.
- neurodata_type_inc: Skeleton
doc: Skeleton used in project where each skeleton corresponds to a unique morphology.
quantity: '*'
- neurodata_type_inc: TrainingFrame
doc: Frames and ground-truth annotations for training a pose estimator.
quantity: '*'
4 changes: 4 additions & 0 deletions spec/ndx-pose.namespace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ namespaces:
- Ryan Ly
- Ben Dichter
- Alexander Mathis
- Liezl Maree
roomrys marked this conversation as resolved.
Show resolved Hide resolved
- Chris Brozdowski
contact:
- rly@lbl.gov
- bdichter@lbl.gov
- alexander.mathis@epfl.ch
- lmaree@salk.edu
roomrys marked this conversation as resolved.
Show resolved Hide resolved
- cbroz@datajoint.com
doc: NWB extension to store pose estimation data
name: ndx-pose
schema:
Expand Down
172 changes: 151 additions & 21 deletions src/spec/create_extension_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,47 @@ def main():
doc='NWB extension to store pose estimation data',
name='ndx-pose',
version='0.1.1',
author=['Ryan Ly', 'Ben Dichter', 'Alexander Mathis'],
contact=['rly@lbl.gov', 'bdichter@lbl.gov', 'alexander.mathis@epfl.ch'],
author=['Ryan Ly', 'Ben Dichter', 'Alexander Mathis', 'Liezl Maree', 'Chris Brozdowski'],
contact=['rly@lbl.gov', 'bdichter@lbl.gov', 'alexander.mathis@epfl.ch', 'lmaree@salk.edu', 'cbroz@datajoint.com'],
)

ns_builder.include_type('SpatialSeries', namespace='core')
ns_builder.include_type('NWBDataInterface', namespace='core')

skeleton = NWBGroupSpec(
neurodata_type_def='Skeleton',
neurodata_type_inc='NWBDataInterface',
doc='Group that holds node and edge data for defining parts of a pose and their connections to one another.',
default_name='Skeleton',
attributes=[
NWBAttributeSpec(
name='id',
doc='Unique ID associated with the skeleton.',
dtype='text',
),
],
datasets=[
NWBDatasetSpec(
name='nodes',
doc=('Array of body part names corresponding to the names of the PoseEstimationSeries objects or '
'PoseTraining objects.'),
dtype='text',
dims=['num_body_parts'],
shape=[None],
quantity=1,
),
NWBDatasetSpec(
name='edges',
doc=("Array of pairs of indices corresponding to edges between nodes. Index values correspond to row "
"indices of the 'nodes' dataset. Index values use 0-indexing."),
dtype='uint8',
dims=['num_edges', 'nodes_index, nodes_index'],
shape=[None, 2],
quantity='?',
),
]
)

pose_estimation_series = NWBGroupSpec(
neurodata_type_def='PoseEstimationSeries',
neurodata_type_inc='SpatialSeries',
Expand Down Expand Up @@ -72,6 +106,13 @@ def main():
quantity='*',
),
],
links=[
NWBLinkSpec(
doc='Layout of body part locations and connections.',
target_type='Skeleton',
quantity=1
),
],
datasets=[
NWBDatasetSpec(
name='description',
Expand Down Expand Up @@ -123,24 +164,6 @@ def main():
),
],
),
NWBDatasetSpec(
name='nodes',
doc=('Array of body part names corresponding to the names of the PoseEstimationSeries objects within '
'this group.'),
dtype='text',
dims=['num_body_parts'],
shape=[None],
quantity='?',
),
NWBDatasetSpec(
name='edges',
doc=("Array of pairs of indices corresponding to edges between nodes. Index values correspond to row "
"indices of the 'nodes' dataset. Index values use 0-indexing."),
dtype='uint8',
dims=['num_edges', 'nodes_index, nodes_index'],
shape=[None, 2],
quantity='?',
),
],
# TODO: collections of multiple links is currently buggy in PyNWB/HDMF
# links=[
Expand All @@ -152,7 +175,114 @@ def main():
# ],
)

new_data_types = [pose_estimation_series, pose_estimation]
training_frame = NWBGroupSpec(
neurodata_type_def='TrainingFrame',
neurodata_type_inc='NWBDataInterface',
doc='Group that holds ground-truth position data for all instances of a skeleton in a single frame.',
default_name='TrainingFrame',
groups=[
NWBGroupSpec(
neurodata_type_inc='Instance',
doc='Position data for a single instance of a skeleton in a single training frame.',
quantity='*',
),
NWBGroupSpec(
name='source_video',
doc='Path to original video file and frame used.',
quantity='?',
attributes=[
NWBAttributeSpec(
name='path',
doc='Path to original video file.',
dtype='text',
required=False,
),
NWBAttributeSpec(
name='frame_index',
doc='Frame index of TrainingFrame in original video file.',
dtype='uint8',
required=False,
),
],
),
NWBGroupSpec(
neurodata_type_inc='Image',
name='source_frame',
doc='Image frame used for training (stored either internally or externally).',
quantity='1',
),
],
attributes=[
NWBAttributeSpec(
name='annotator',
doc='Name of annotator who labeled the TrainingFrame.',
dtype='text',
required=False,
),
],
)

instance = NWBGroupSpec(
neurodata_type_def='Instance',
neurodata_type_inc='NWBDataInterface',
doc='Group that holds ground-truth pose data for a single instance of a skeleton in a single frame.',
default_name='Instance',
links=[
NWBLinkSpec(
doc='Layout of body part locations and connections.',
target_type='Skeleton',
quantity=1
),
],
attributes=[
NWBAttributeSpec(
name='id',
doc='ID used to differentiate skeleton instances.',
dtype='uint8',
required=False,
),
],
datasets=[
NWBDatasetSpec(
name='node_locations',
doc=('Locations (x, y) or (x, y, z) of nodes for single instance in single frame.'),
dtype='float',
dims=[['num_body_parts', 'x, y'], ['num_body_parts', 'x, y, z']],
shape=[[None, 2], [None, 3]],
quantity=1,
),
NWBDatasetSpec(
name='node_visibility',
doc=('Markers for node visibility where true corresponds to a visible node and false corresponds to '
'an occluded node.'),
dtype='bool',
dims=['num_body_parts'],
shape=[None],
quantity='?',
),
],
)

pose_training = NWBGroupSpec(
neurodata_type_def='PoseTraining',
neurodata_type_inc='NWBDataInterface',
doc='Group that holds images, ground-truth annotations, and metadata for training a pose estimator.',
default_name='PoseTraining',
groups=[
NWBGroupSpec(
neurodata_type_inc='Skeleton',
doc='Skeleton used in project where each skeleton corresponds to a unique morphology.',
quantity='*',
),
NWBGroupSpec(
neurodata_type_inc='TrainingFrame',
doc='Frames and ground-truth annotations for training a pose estimator.',
quantity='*',
),
],
)

new_data_types = [skeleton, pose_estimation_series, pose_estimation, training_frame, instance, pose_training]

# export the spec to yaml files in the spec folder
output_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'spec'))
Expand Down