motionbids 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- motionbids-0.1.0/.github/workflows/docs.yml +58 -0
- motionbids-0.1.0/.github/workflows/tests.yml +45 -0
- motionbids-0.1.0/.gitignore +69 -0
- motionbids-0.1.0/LICENSE +21 -0
- motionbids-0.1.0/PKG-INFO +226 -0
- motionbids-0.1.0/README.md +204 -0
- motionbids-0.1.0/docs/class-reference.md +400 -0
- motionbids-0.1.0/docs/index.md +152 -0
- motionbids-0.1.0/docs/motivation.md +53 -0
- motionbids-0.1.0/docs/schema-fields.md +337 -0
- motionbids-0.1.0/docs/workflow.md +387 -0
- motionbids-0.1.0/example.py +136 -0
- motionbids-0.1.0/mkdocs.yml +66 -0
- motionbids-0.1.0/motionbids/__init__.py +92 -0
- motionbids-0.1.0/motionbids/bids_constants.py +46 -0
- motionbids-0.1.0/motionbids/channel.py +135 -0
- motionbids-0.1.0/motionbids/datamodel.py +230 -0
- motionbids-0.1.0/motionbids/datamodel_dynamic.py +355 -0
- motionbids-0.1.0/motionbids/datautils.py +24 -0
- motionbids-0.1.0/motionbids/exporter.py +518 -0
- motionbids-0.1.0/motionbids/schema_utils.py +147 -0
- motionbids-0.1.0/motionbids/validator.py +241 -0
- motionbids-0.1.0/pyproject.toml +40 -0
- motionbids-0.1.0/tests/test_datamodel.py +225 -0
- motionbids-0.1.0/tests/test_exporter.py +334 -0
- motionbids-0.1.0/tests/test_validator.py +252 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Deploy Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: "pages"
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
name: Build Documentation
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.11'
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@v3
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: |
|
|
35
|
+
uv pip install --system -e ".[docs]"
|
|
36
|
+
|
|
37
|
+
- name: Build documentation
|
|
38
|
+
run: |
|
|
39
|
+
mkdocs build --strict
|
|
40
|
+
|
|
41
|
+
- name: Upload artifact
|
|
42
|
+
uses: actions/upload-pages-artifact@v3
|
|
43
|
+
with:
|
|
44
|
+
path: ./site
|
|
45
|
+
|
|
46
|
+
deploy:
|
|
47
|
+
name: Deploy to GitHub Pages
|
|
48
|
+
needs: build
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
|
|
51
|
+
environment:
|
|
52
|
+
name: github-pages
|
|
53
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
54
|
+
|
|
55
|
+
steps:
|
|
56
|
+
- name: Deploy to GitHub Pages
|
|
57
|
+
id: deployment
|
|
58
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
18
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
|
|
28
|
+
- name: Install uv
|
|
29
|
+
uses: astral-sh/setup-uv@v3
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: |
|
|
33
|
+
uv pip install --system -e ".[dev]"
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: |
|
|
37
|
+
pytest tests/ -v --cov=motionbids --cov-report=xml --cov-report=term
|
|
38
|
+
|
|
39
|
+
- name: Upload coverage to Codecov
|
|
40
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
|
41
|
+
uses: codecov/codecov-action@v4
|
|
42
|
+
with:
|
|
43
|
+
file: ./coverage.xml
|
|
44
|
+
fail_ci_if_error: false
|
|
45
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
venv/
|
|
25
|
+
ENV/
|
|
26
|
+
env/
|
|
27
|
+
.venv
|
|
28
|
+
|
|
29
|
+
# IDEs
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# Testing
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.hypothesis/
|
|
42
|
+
|
|
43
|
+
# Distribution
|
|
44
|
+
*.whl
|
|
45
|
+
|
|
46
|
+
# OS
|
|
47
|
+
.DS_Store
|
|
48
|
+
Thumbs.db
|
|
49
|
+
|
|
50
|
+
# Example outputs
|
|
51
|
+
example_bids_dataset/
|
|
52
|
+
bids_out/
|
|
53
|
+
bids_root/
|
|
54
|
+
*.tsv
|
|
55
|
+
*.json
|
|
56
|
+
!pyproject.toml
|
|
57
|
+
!.github/**/*.json
|
|
58
|
+
|
|
59
|
+
# Jupyter
|
|
60
|
+
.ipynb_checkpoints/
|
|
61
|
+
*.ipynb
|
|
62
|
+
|
|
63
|
+
# uv
|
|
64
|
+
.uv/
|
|
65
|
+
uv.lock
|
|
66
|
+
|
|
67
|
+
# JOSS paper draft
|
|
68
|
+
paper.md
|
|
69
|
+
paper.bib
|
motionbids-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 motionbids contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: motionbids
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Lightweight converter for motion data to BIDS format
|
|
5
|
+
Author-email: Julius Welzel <julius.welzel@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: bidsschematools>=0.8.0
|
|
10
|
+
Requires-Dist: dataclasses-json>=0.6.0
|
|
11
|
+
Requires-Dist: numpy>=1.20.0
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: ipykernel>=6.29.5; extra == 'dev'
|
|
14
|
+
Requires-Dist: pip>=25.3; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
17
|
+
Provides-Extra: docs
|
|
18
|
+
Requires-Dist: mkdocs-material>=9.4.0; extra == 'docs'
|
|
19
|
+
Requires-Dist: mkdocs>=1.5.0; extra == 'docs'
|
|
20
|
+
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'docs'
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# motionbids
|
|
24
|
+
|
|
25
|
+
[](https://www.python.org/downloads/)
|
|
26
|
+
[](https://opensource.org/licenses/MIT)
|
|
27
|
+
[](https://github.com/JuliusWelzel/motionbids/actions/workflows/tests.yml)
|
|
28
|
+
[](https://codecov.io/gh/JuliusWelzel/motionbids)
|
|
29
|
+
|
|
30
|
+
A **lightweight** Python package for exporting motion capture data to **BIDS format**.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from motionbids import MotionData, Channel, export_bids_motion
|
|
36
|
+
import numpy as np
|
|
37
|
+
|
|
38
|
+
# Your motion data (1200 timepoints, 32 channels)
|
|
39
|
+
data = np.random.randn(1200, 32)
|
|
40
|
+
|
|
41
|
+
# Define channels following BIDS schema
|
|
42
|
+
channels = [
|
|
43
|
+
Channel(
|
|
44
|
+
channel_name=f"marker{i}_{axis}",
|
|
45
|
+
channel_component=axis,
|
|
46
|
+
channel_type="POS",
|
|
47
|
+
channel_tracked_point=f"marker{i}",
|
|
48
|
+
channel_units="mm"
|
|
49
|
+
)
|
|
50
|
+
for i in range(10)
|
|
51
|
+
for axis in ['x', 'y', 'z']
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
# Create BIDS motion object
|
|
55
|
+
motion = MotionData(
|
|
56
|
+
subject_id="01",
|
|
57
|
+
task_name="walk",
|
|
58
|
+
tracksys="optical",
|
|
59
|
+
sampling_frequency=120.0,
|
|
60
|
+
tracked_points_count=10,
|
|
61
|
+
manufacturer="Vicon",
|
|
62
|
+
data=data,
|
|
63
|
+
channels=channels
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Export to BIDS format
|
|
67
|
+
export_bids_motion(motion, out_dir="bids_dataset/")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Output:**
|
|
71
|
+
```
|
|
72
|
+
bids_dataset/
|
|
73
|
+
├── sub-01_task-walk_tracksys-optical_motion.json # Metadata
|
|
74
|
+
├── sub-01_task-walk_tracksys-optical_motion.tsv # Time series
|
|
75
|
+
└── sub-01_task-walk_tracksys-optical_channels.tsv # Channel info
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Installation
|
|
79
|
+
|
|
80
|
+
**📦 Not on PyPI**: This package is not yet published on PyPI. Install from source:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Clone the repository
|
|
84
|
+
git clone https://github.com/JuliusWelzel/motionbids.git
|
|
85
|
+
cd motionbids
|
|
86
|
+
|
|
87
|
+
# Install with uv (recommended)
|
|
88
|
+
uv venv # Create virtual environment
|
|
89
|
+
uv pip install -e .
|
|
90
|
+
|
|
91
|
+
# Or with pip
|
|
92
|
+
python -m venv .venv
|
|
93
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
94
|
+
pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Features
|
|
98
|
+
|
|
99
|
+
✅ **Schema-driven** - Auto-syncs with BIDS specification
|
|
100
|
+
✅ **Automatic validation** - Catches errors before export
|
|
101
|
+
✅ **Simple API** - Minimal code needed
|
|
102
|
+
✅ **Complete export** - JSON, TSV, channels files
|
|
103
|
+
✅ **Cross-platform** - Tested on Linux, macOS, Windows
|
|
104
|
+
|
|
105
|
+
## Documentation
|
|
106
|
+
|
|
107
|
+
**[Full Documentation](https://juliuswelzel.github.io/motionbids/)**
|
|
108
|
+
|
|
109
|
+
- [Motivation](https://juliuswelzel.github.io/motionbids/motivation/) - Why BIDS for motion?
|
|
110
|
+
- [Workflow](https://juliuswelzel.github.io/motionbids/workflow/) - Complete workflow guide
|
|
111
|
+
- [Class Reference](https://juliuswelzel.github.io/motionbids/class-reference/) - MotionData API
|
|
112
|
+
- [Schema Fields](https://juliuswelzel.github.io/motionbids/schema-fields/) - All BIDS fields
|
|
113
|
+
|
|
114
|
+
## Required Fields
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
motion = MotionData(
|
|
118
|
+
subject_id="01", # Subject identifier
|
|
119
|
+
task_name="walk", # Task name
|
|
120
|
+
tracksys="optical", # Tracking system (optical/imu/video)
|
|
121
|
+
sampling_frequency=120.0, # Sampling rate in Hz
|
|
122
|
+
tracked_points_count=10, # Number of markers
|
|
123
|
+
data=data, # NumPy array (rows=time, cols=channels)
|
|
124
|
+
channels=channels # List of Channel objects (BIDS-compliant)
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Channel Metadata
|
|
129
|
+
|
|
130
|
+
Each channel requires BIDS-compliant metadata:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from motionbids import Channel
|
|
134
|
+
|
|
135
|
+
channel = Channel(
|
|
136
|
+
channel_name="marker0_x", # Channel name
|
|
137
|
+
channel_component="x", # x, y, z, quat_x, quat_y, quat_z, quat_w, n/a
|
|
138
|
+
channel_type="POS", # POS, ORNT, VEL, ACCEL, GYRO, MAGN, etc.
|
|
139
|
+
channel_tracked_point="marker0", # Label of tracked point
|
|
140
|
+
channel_units="mm" # Units (mm, m, rad, deg, etc.)
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Validation
|
|
145
|
+
|
|
146
|
+
**Important**: Package validation is for convenience only and is **not officially supported by BIDS**. Always use the official [BIDS Validator](https://bids-standard.github.io/bids-validator/) before sharing your dataset.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from motionbids import validate_motion_data
|
|
150
|
+
|
|
151
|
+
# Convenience validation (checks basic requirements)
|
|
152
|
+
validate_motion_data(motion)
|
|
153
|
+
|
|
154
|
+
# Then validate with official BIDS Validator:
|
|
155
|
+
# https://bids-standard.github.io/bids-validator/
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Complete Workflow
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from motionbids import (
|
|
162
|
+
MotionData,
|
|
163
|
+
export_bids_motion,
|
|
164
|
+
create_bids_directory_structure,
|
|
165
|
+
export_dataset_description
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# 1. Create directory structure
|
|
169
|
+
motion_dir = create_bids_directory_structure(
|
|
170
|
+
base_dir="my_study",
|
|
171
|
+
subject_id="01",
|
|
172
|
+
session_id="01"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# 2. Create dataset description
|
|
176
|
+
export_dataset_description(
|
|
177
|
+
bids_root="my_study",
|
|
178
|
+
name="Motion Study",
|
|
179
|
+
authors=["Your Name"]
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# 3. Export motion data
|
|
183
|
+
motion = MotionData(...)
|
|
184
|
+
export_bids_motion(motion, out_dir=motion_dir)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Supported Systems
|
|
188
|
+
|
|
189
|
+
Works with any motion tracking technology:
|
|
190
|
+
- **Optical**: Vicon, Optitrack, Qualisys
|
|
191
|
+
- **IMU**: Xsens, APDM, Movella
|
|
192
|
+
- **Video**: OpenPose, MediaPipe, DeepLabCut
|
|
193
|
+
- **Other**: Custom systems
|
|
194
|
+
|
|
195
|
+
## Development
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Clone and install
|
|
199
|
+
git clone https://github.com/juliuswelzel/motionbids.git
|
|
200
|
+
cd motionbids
|
|
201
|
+
uv pip install -e ".[dev]"
|
|
202
|
+
|
|
203
|
+
# Run tests
|
|
204
|
+
pytest --cov=motionbids
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Citation
|
|
208
|
+
|
|
209
|
+
```bibtex
|
|
210
|
+
@software{motionbids,
|
|
211
|
+
author = {Welzel, Julius},
|
|
212
|
+
title = {motion2bids: BIDS converter for motion capture data},
|
|
213
|
+
year = {2025},
|
|
214
|
+
url = {https://github.com/JuliusWelzel/motionbids}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Links
|
|
219
|
+
|
|
220
|
+
- 📖 [Documentation](https://juliuswelzel.github.io/motionbids/)
|
|
221
|
+
- 🐛 [Issues](https://github.com/JuliusWelzel/motionbids/issues)
|
|
222
|
+
- 📜 [BIDS Spec](https://bids-specification.readthedocs.io/)
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# motionbids
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/downloads/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://github.com/JuliusWelzel/motionbids/actions/workflows/tests.yml)
|
|
6
|
+
[](https://codecov.io/gh/JuliusWelzel/motionbids)
|
|
7
|
+
|
|
8
|
+
A **lightweight** Python package for exporting motion capture data to **BIDS format**.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
from motionbids import MotionData, Channel, export_bids_motion
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
# Your motion data (1200 timepoints, 32 channels)
|
|
17
|
+
data = np.random.randn(1200, 32)
|
|
18
|
+
|
|
19
|
+
# Define channels following BIDS schema
|
|
20
|
+
channels = [
|
|
21
|
+
Channel(
|
|
22
|
+
channel_name=f"marker{i}_{axis}",
|
|
23
|
+
channel_component=axis,
|
|
24
|
+
channel_type="POS",
|
|
25
|
+
channel_tracked_point=f"marker{i}",
|
|
26
|
+
channel_units="mm"
|
|
27
|
+
)
|
|
28
|
+
for i in range(10)
|
|
29
|
+
for axis in ['x', 'y', 'z']
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
# Create BIDS motion object
|
|
33
|
+
motion = MotionData(
|
|
34
|
+
subject_id="01",
|
|
35
|
+
task_name="walk",
|
|
36
|
+
tracksys="optical",
|
|
37
|
+
sampling_frequency=120.0,
|
|
38
|
+
tracked_points_count=10,
|
|
39
|
+
manufacturer="Vicon",
|
|
40
|
+
data=data,
|
|
41
|
+
channels=channels
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Export to BIDS format
|
|
45
|
+
export_bids_motion(motion, out_dir="bids_dataset/")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Output:**
|
|
49
|
+
```
|
|
50
|
+
bids_dataset/
|
|
51
|
+
├── sub-01_task-walk_tracksys-optical_motion.json # Metadata
|
|
52
|
+
├── sub-01_task-walk_tracksys-optical_motion.tsv # Time series
|
|
53
|
+
└── sub-01_task-walk_tracksys-optical_channels.tsv # Channel info
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
**📦 Not on PyPI**: This package is not yet published on PyPI. Install from source:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Clone the repository
|
|
62
|
+
git clone https://github.com/JuliusWelzel/motionbids.git
|
|
63
|
+
cd motionbids
|
|
64
|
+
|
|
65
|
+
# Install with uv (recommended)
|
|
66
|
+
uv venv # Create virtual environment
|
|
67
|
+
uv pip install -e .
|
|
68
|
+
|
|
69
|
+
# Or with pip
|
|
70
|
+
python -m venv .venv
|
|
71
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
72
|
+
pip install -e .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Features
|
|
76
|
+
|
|
77
|
+
✅ **Schema-driven** - Auto-syncs with BIDS specification
|
|
78
|
+
✅ **Automatic validation** - Catches errors before export
|
|
79
|
+
✅ **Simple API** - Minimal code needed
|
|
80
|
+
✅ **Complete export** - JSON, TSV, channels files
|
|
81
|
+
✅ **Cross-platform** - Tested on Linux, macOS, Windows
|
|
82
|
+
|
|
83
|
+
## Documentation
|
|
84
|
+
|
|
85
|
+
**[Full Documentation](https://juliuswelzel.github.io/motionbids/)**
|
|
86
|
+
|
|
87
|
+
- [Motivation](https://juliuswelzel.github.io/motionbids/motivation/) - Why BIDS for motion?
|
|
88
|
+
- [Workflow](https://juliuswelzel.github.io/motionbids/workflow/) - Complete workflow guide
|
|
89
|
+
- [Class Reference](https://juliuswelzel.github.io/motionbids/class-reference/) - MotionData API
|
|
90
|
+
- [Schema Fields](https://juliuswelzel.github.io/motionbids/schema-fields/) - All BIDS fields
|
|
91
|
+
|
|
92
|
+
## Required Fields
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
motion = MotionData(
|
|
96
|
+
subject_id="01", # Subject identifier
|
|
97
|
+
task_name="walk", # Task name
|
|
98
|
+
tracksys="optical", # Tracking system (optical/imu/video)
|
|
99
|
+
sampling_frequency=120.0, # Sampling rate in Hz
|
|
100
|
+
tracked_points_count=10, # Number of markers
|
|
101
|
+
data=data, # NumPy array (rows=time, cols=channels)
|
|
102
|
+
channels=channels # List of Channel objects (BIDS-compliant)
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Channel Metadata
|
|
107
|
+
|
|
108
|
+
Each channel requires BIDS-compliant metadata:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from motionbids import Channel
|
|
112
|
+
|
|
113
|
+
channel = Channel(
|
|
114
|
+
channel_name="marker0_x", # Channel name
|
|
115
|
+
channel_component="x", # x, y, z, quat_x, quat_y, quat_z, quat_w, n/a
|
|
116
|
+
channel_type="POS", # POS, ORNT, VEL, ACCEL, GYRO, MAGN, etc.
|
|
117
|
+
channel_tracked_point="marker0", # Label of tracked point
|
|
118
|
+
channel_units="mm" # Units (mm, m, rad, deg, etc.)
|
|
119
|
+
)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Validation
|
|
123
|
+
|
|
124
|
+
**Important**: Package validation is for convenience only and is **not officially supported by BIDS**. Always use the official [BIDS Validator](https://bids-standard.github.io/bids-validator/) before sharing your dataset.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from motionbids import validate_motion_data
|
|
128
|
+
|
|
129
|
+
# Convenience validation (checks basic requirements)
|
|
130
|
+
validate_motion_data(motion)
|
|
131
|
+
|
|
132
|
+
# Then validate with official BIDS Validator:
|
|
133
|
+
# https://bids-standard.github.io/bids-validator/
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Complete Workflow
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from motionbids import (
|
|
140
|
+
MotionData,
|
|
141
|
+
export_bids_motion,
|
|
142
|
+
create_bids_directory_structure,
|
|
143
|
+
export_dataset_description
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# 1. Create directory structure
|
|
147
|
+
motion_dir = create_bids_directory_structure(
|
|
148
|
+
base_dir="my_study",
|
|
149
|
+
subject_id="01",
|
|
150
|
+
session_id="01"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# 2. Create dataset description
|
|
154
|
+
export_dataset_description(
|
|
155
|
+
bids_root="my_study",
|
|
156
|
+
name="Motion Study",
|
|
157
|
+
authors=["Your Name"]
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# 3. Export motion data
|
|
161
|
+
motion = MotionData(...)
|
|
162
|
+
export_bids_motion(motion, out_dir=motion_dir)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Supported Systems
|
|
166
|
+
|
|
167
|
+
Works with any motion tracking technology:
|
|
168
|
+
- **Optical**: Vicon, Optitrack, Qualisys
|
|
169
|
+
- **IMU**: Xsens, APDM, Movella
|
|
170
|
+
- **Video**: OpenPose, MediaPipe, DeepLabCut
|
|
171
|
+
- **Other**: Custom systems
|
|
172
|
+
|
|
173
|
+
## Development
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Clone and install
|
|
177
|
+
git clone https://github.com/juliuswelzel/motionbids.git
|
|
178
|
+
cd motionbids
|
|
179
|
+
uv pip install -e ".[dev]"
|
|
180
|
+
|
|
181
|
+
# Run tests
|
|
182
|
+
pytest --cov=motionbids
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Citation
|
|
186
|
+
|
|
187
|
+
```bibtex
|
|
188
|
+
@software{motionbids,
|
|
189
|
+
author = {Welzel, Julius},
|
|
190
|
+
title = {motion2bids: BIDS converter for motion capture data},
|
|
191
|
+
year = {2025},
|
|
192
|
+
url = {https://github.com/JuliusWelzel/motionbids}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Links
|
|
197
|
+
|
|
198
|
+
- 📖 [Documentation](https://juliuswelzel.github.io/motionbids/)
|
|
199
|
+
- 🐛 [Issues](https://github.com/JuliusWelzel/motionbids/issues)
|
|
200
|
+
- 📜 [BIDS Spec](https://bids-specification.readthedocs.io/)
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT License - see [LICENSE](LICENSE) for details.
|