-
Notifications
You must be signed in to change notification settings - Fork 70
Add I/O support for the ndx-pose NWB extension: take 2 #360
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
Changes from all commits
4b59ff0
ab60c04
f8a375a
1500081
8d1d5f3
c107737
c0e156c
32adc93
814e867
10e95f4
0db918e
71a09eb
85244bd
48e8bca
a6a8811
5a91a34
c328bc6
6a4f963
953cc8d
3d3d038
ae439a4
0cca671
684f33a
ac4f06c
465bd70
6291d14
9f807b9
486924f
a91c2d4
09cd0e4
1359e26
94a5f73
ea514fd
5b55970
9f679ce
bf68547
5760296
9947e9f
362a6a9
4ee68cf
081ba18
dcae070
9dd13b7
f3f261a
9728d8f
059944e
fd749ae
457f7de
2d98bd8
d094f6f
979027c
31d79ea
e83c859
441be86
ad86058
fcf2a68
f1eba42
153d996
75b6d62
aad6641
4ac8030
440fbcb
85243f4
e843944
e04cf79
d6dec2a
e90873a
9097679
fd1a121
3fdaaac
ab72903
5cdc4a4
bdc47f5
d397678
eccb6fa
72b7f2b
8af4f76
c0161ad
8bef5ef
0ac6caa
78cb0e1
8ef4b93
ab253e0
1cbec09
c0a90ce
7853af5
a425b5a
20c8f8e
186f17b
bc7280b
12636a3
2cee1d9
aa40bb1
fe83497
a53e888
9bd137d
463100f
ecab492
a42c05f
aeb0324
2a575aa
7a243ed
510c50e
9498839
32611a6
3518362
fdc6501
c4a8fbe
8e2d766
9c64a4e
36fcf52
1bf604c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,8 @@ To analyse pose tracks, `movement` supports loading data from various frameworks | |
- [LightingPose](lp:) (LP) | ||
- [Anipose](anipose:) (Anipose) | ||
|
||
Additionally, `movement` supports loading data stored in [Neurodata Without Borders (NWB)](https://nwb-overview.readthedocs.io/en/latest/) format (using the [``ndx-pose``](https://github.com/rly/ndx-pose) extension). | ||
|
||
To analyse bounding box tracks, `movement` currently supports the [VGG Image Annotator](via:) (VIA) format for [tracks annotation](via:docs/face_track_annotation.html). | ||
|
||
:::{note} | ||
|
@@ -36,44 +38,39 @@ To read a pose tracks file into a [movement poses dataset](target-poses-and-bbox | |
|
||
::::{tab-set} | ||
|
||
:::{tab-item} SLEAP | ||
|
||
To load [SLEAP analysis files](sleap:tutorials/analysis) in .h5 format (recommended): | ||
:::{tab-item} DeepLabCut | ||
To load DeepLabCut files in .h5 format: | ||
```python | ||
ds = load_poses.from_sleap_file("/path/to/file.analysis.h5", fps=30) | ||
ds = load_poses.from_dlc_file("/path/to/file.h5", fps=30) | ||
|
||
# or equivalently | ||
ds = load_poses.from_file( | ||
"/path/to/file.analysis.h5", source_software="SLEAP", fps=30 | ||
"/path/to/file.h5", source_software="DeepLabCut", fps=30 | ||
) | ||
``` | ||
To load [SLEAP analysis files](sleap:tutorials/analysis) in .slp format (experimental, see notes in {func}`movement.io.load_poses.from_sleap_file`): | ||
|
||
To load DeepLabCut files in .csv format: | ||
```python | ||
ds = load_poses.from_sleap_file("/path/to/file.predictions.slp", fps=30) | ||
ds = load_poses.from_dlc_file("/path/to/file.csv", fps=30) | ||
``` | ||
::: | ||
|
||
:::{tab-item} DeepLabCut | ||
|
||
To load DeepLabCut files in .h5 format: | ||
:::{tab-item} SLEAP | ||
To load [SLEAP analysis files](sleap:tutorials/analysis) in .h5 format (recommended): | ||
```python | ||
ds = load_poses.from_dlc_file("/path/to/file.h5", fps=30) | ||
ds = load_poses.from_sleap_file("/path/to/file.analysis.h5", fps=30) | ||
|
||
# or equivalently | ||
ds = load_poses.from_file( | ||
"/path/to/file.h5", source_software="DeepLabCut", fps=30 | ||
"/path/to/file.analysis.h5", source_software="SLEAP", fps=30 | ||
) | ||
``` | ||
|
||
To load DeepLabCut files in .csv format: | ||
To load [SLEAP analysis files](sleap:tutorials/analysis) in .slp format (experimental, see notes in {func}`movement.io.load_poses.from_sleap_file`): | ||
```python | ||
ds = load_poses.from_dlc_file("/path/to/file.csv", fps=30) | ||
ds = load_poses.from_sleap_file("/path/to/file.predictions.slp", fps=30) | ||
``` | ||
::: | ||
|
||
:::{tab-item} LightningPose | ||
|
||
To load LightningPose files in .csv format: | ||
```python | ||
ds = load_poses.from_lp_file("/path/to/file.analysis.csv", fps=30) | ||
|
@@ -86,26 +83,53 @@ ds = load_poses.from_file( | |
::: | ||
|
||
:::{tab-item} Anipose | ||
|
||
To load Anipose files in .csv format: | ||
```python | ||
ds = load_poses.from_anipose_file( | ||
"/path/to/file.analysis.csv", fps=30, individual_name="individual_0" | ||
) # We can optionally specify the individual name, by default it is "individual_0" | ||
) # Optionally specify the individual name; defaults to "individual_0" | ||
|
||
# or equivalently | ||
ds = load_poses.from_file( | ||
"/path/to/file.analysis.csv", source_software="Anipose", fps=30, individual_name="individual_0" | ||
"/path/to/file.analysis.csv", | ||
source_software="Anipose", | ||
fps=30, | ||
individual_name="individual_0", | ||
) | ||
``` | ||
::: | ||
|
||
:::{tab-item} NWB | ||
To load NWB files in .nwb format: | ||
```python | ||
ds = load_poses.from_nwb_file( | ||
"path/to/file.nwb", | ||
processing_module_key="behavior", | ||
pose_estimation_key="PoseEstimation", | ||
) # Optionally specify the name of the ProcessingModule and PoseEstimation objects. | ||
# Defaults are "behavior" and "PoseEstimation", respectively. | ||
|
||
# or equivalently | ||
ds = load_poses.from_file( | ||
"path/to/file.nwb", | ||
source_software="NWB", | ||
processing_module_key="behavior", | ||
pose_estimation_key="PoseEstimation", | ||
) | ||
``` | ||
The above functions also accept an {class}`NWBFile<pynwb.file.NWBFile>` object as input: | ||
```python | ||
with pynwb.NWBHDF5IO("path/to/file.nwb", mode="r") as io: | ||
nwb_file = io.read() | ||
ds = load_poses.from_nwb_file( | ||
nwb_file, pose_estimation_key="PoseEstimation" | ||
) | ||
``` | ||
::: | ||
|
||
:::{tab-item} From NumPy | ||
|
||
In the example below, we create random position data for two individuals, ``Alice`` and ``Bob``, | ||
with three keypoints each: ``snout``, ``centre``, and ``tail_base``. These keypoints are tracked in 2D space for 100 frames, at 30 fps. The confidence scores are set to 1 for all points. | ||
|
||
```python | ||
import numpy as np | ||
|
||
|
@@ -142,7 +166,6 @@ We currently support loading bounding box tracks in the VGG Image Annotator (VIA | |
|
||
::::{tab-set} | ||
:::{tab-item} VGG Image Annotator | ||
|
||
To load a VIA tracks .csv file: | ||
```python | ||
ds = load_bboxes.from_via_tracks_file("path/to/file.csv", fps=30) | ||
|
@@ -154,17 +177,12 @@ ds = load_bboxes.from_file( | |
fps=30, | ||
) | ||
``` | ||
|
||
Note that the x,y coordinates in the input VIA tracks .csv file represent the the top-left corner of each bounding box. Instead the corresponding ``movement`` dataset `ds` will hold in its `position` array the centroid of each bounding box. | ||
|
||
|
||
::: | ||
|
||
:::{tab-item} From NumPy | ||
|
||
In the example below, we create random position data for two bounding boxes, ``id_0`` and ``id_1``, | ||
both with the same width (40 pixels) and height (30 pixels). These are tracked in 2D space for 100 frames, which will be numbered in the resulting dataset from 0 to 99. The confidence score for all bounding boxes is set to 0.5. | ||
|
||
```python | ||
import numpy as np | ||
|
||
|
@@ -182,16 +200,16 @@ ds = load_bboxes.from_numpy( | |
|
||
The resulting data structure `ds` will include the centroid trajectories for each tracked bounding box, the boxes' widths and heights, and their associated confidence values if provided. | ||
|
||
|
||
|
||
For more information on the bounding boxes data structure, see the [movement dataset](target-poses-and-bboxes-dataset) page. | ||
|
||
|
||
(target-saving-pose-tracks)= | ||
## Saving pose tracks | ||
[movement poses datasets](target-poses-and-bboxes-dataset) can be saved in a variety of | ||
formats, including DeepLabCut-style files (.h5 or .csv) and | ||
[SLEAP-style analysis files](sleap:tutorials/analysis) (.h5). | ||
formats: | ||
- DeepLabCut-style files (.h5 or .csv) | ||
- [SLEAP-style analysis files](sleap:tutorials/analysis) (.h5) | ||
- NWB files (.nwb) | ||
|
||
To export pose tracks from `movement`, first import the {mod}`movement.io.save_poses` module: | ||
|
||
|
@@ -203,13 +221,22 @@ Then, depending on the desired format, use one of the following functions: | |
|
||
:::::{tab-set} | ||
|
||
::::{tab-item} SLEAP | ||
::::{tab-item} DeepLabCut | ||
To save as a DeepLabCut file, in .h5 or .csv format: | ||
```python | ||
save_poses.to_dlc_file(ds, "/path/to/file.h5") # preferred format | ||
save_poses.to_dlc_file(ds, "/path/to/file.csv") | ||
``` | ||
The {func}`movement.io.save_poses.to_dlc_file` function also accepts | ||
a `split_individuals` boolean argument. If set to `True`, the function will | ||
save the data as separate single-animal DeepLabCut-style files. | ||
:::: | ||
|
||
::::{tab-item} SLEAP | ||
To save as a SLEAP analysis file in .h5 format: | ||
```python | ||
save_poses.to_sleap_analysis_file(ds, "/path/to/file.h5") | ||
``` | ||
|
||
:::{note} | ||
When saving to SLEAP-style files, only `track_names`, `node_names`, `tracks`, `track_occupancy`, | ||
and `point_scores` are saved. `labels_path` will only be saved if the source | ||
|
@@ -222,22 +249,7 @@ each attribute and data variable represents, see the | |
::: | ||
:::: | ||
|
||
::::{tab-item} DeepLabCut | ||
|
||
To save as a DeepLabCut file, in .h5 or .csv format: | ||
```python | ||
save_poses.to_dlc_file(ds, "/path/to/file.h5") # preferred format | ||
save_poses.to_dlc_file(ds, "/path/to/file.csv") | ||
``` | ||
|
||
The {func}`movement.io.save_poses.to_dlc_file` function also accepts | ||
a `split_individuals` boolean argument. If set to `True`, the function will | ||
save the data as separate single-animal DeepLabCut-style files. | ||
|
||
:::: | ||
|
||
::::{tab-item} LightningPose | ||
|
||
To save as a LightningPose file in .csv format: | ||
```python | ||
save_poses.to_lp_file(ds, "/path/to/file.csv") | ||
|
@@ -249,8 +261,32 @@ DeepLabCut .csv format, the above command is equivalent to: | |
save_poses.to_dlc_file(ds, "/path/to/file.csv", split_individuals=True) | ||
``` | ||
::: | ||
:::: | ||
|
||
::::{tab-item} NWB | ||
To convert a `movement` poses dataset to {class}`NWBFile<pynwb.file.NWBFile>` objects: | ||
```python | ||
nwb_files = save_poses.to_nwb_file(ds) | ||
``` | ||
The {func}`movement.io.save_poses.to_nwb_file` function also accepts | ||
a {class}`movement.io.nwb.NWBFileSaveConfig` object as its ``config`` argument | ||
for customising metadata such as session or subject information in the resulting `NWBFile`s | ||
(see {func}`the API reference<movement.io.save_poses.to_nwb_file>` for examples). | ||
|
||
These `NWBFile`s can then be saved to disk as .nwb files using {class}`pynwb.NWBHDF5IO`: | ||
```python | ||
from pynwb import NWBHDF5IO | ||
|
||
for file in nwb_files: | ||
with NWBHDF5IO(f"{file.identifier}.nwb", "w") as io: | ||
io.write(file) | ||
``` | ||
:::{note} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps in this note (or above it within the tab) we should mention the config that can now be passed to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a line describing this |
||
To allow adding additional data to NWB files before saving, {func}`to_nwb_file<movement.io.save_poses.to_nwb_file>` does not write to disk directly. | ||
Instead, it returns a list of {class}`NWBFile<pynwb.file.NWBFile>` objects---one per individual in the dataset---since NWB files are designed to represent data from a single individual. | ||
::: | ||
:::: | ||
|
||
::::: | ||
|
||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.