Mocap¶
Motion-capture file readers and re-exports.
The QTM reader and the cross-modality utilities are re-exported from the
micromotion package. They used to live here and were moved on 2026-07-29 so that
one implementation of quantity of motion exists rather than two, and MGT now depends on
that package instead of carrying its own copy. Behaviour is unchanged: this module's
tests pass against micromotion unmodified.
The dependency points this way round on purpose. micromotion needs only numpy, scipy and
pandas, so someone analysing accelerometer data does not have to install a computer-vision
stack; MGT already depends on ambiscape the same way, and neither of those packages
imports MGT.
Import from micromotion directly in new code that needs the re-exported functions.
Its API reference, including the band each function uses and what it returns, is at
https://fourms.github.io/micromotion/ and the functions re-exported here are documented
there rather than below.
Beside the re-exports, this module holds MGT's own readers for the formats that most
measurement systems can write --- :func:read_trc for the tab-separated TRC format
(OpenSim, Motion Analysis, Pose2Sim, OpenCap), :func:read_c3d for the binary C3D
standard (Qualisys, OptiTrack, Vicon, Theia3D) and :func:read_freemocap for the
recording folders of the markerless FreeMoCap system. All return exactly the contract
of :func:read_qtm_tsv --- (marker_names, data, fs) with data of shape
(frames, markers, 3), gaps as NaN and positions in millimetres --- so everything
downstream of the QTM reader, such as
:func:~micromotion.mocap.compare_modality_envelopes, consumes their output unchanged.
read_trc ¶
read_trc(path)
Read a TRC (Track Row Column) motion-capture export.
TRC is the tab-separated text format written by Motion Analysis systems and used by
OpenSim, and it is the marker-trajectory export of the video-based pipelines
Pose2Sim and OpenCap. The documented layout is a five-line header --- a
PathFileType line, a line of field names (DataRate, CameraRate,
NumFrames, NumMarkers, Units, ...), a line of their values, a column-name
line (Frame#, Time, then one marker name per X/Y/Z triple) and a line of
per-axis labels (X1, Y1, Z1, ...) --- followed by the numeric block.
This reader locates the header rows by their content rather than by line number, so
files with a missing blank line or extra header material still parse.
Written against the TRC format as documented for OpenSim and Motion Analysis and the
synthetic fixtures in tests/test_mocap_readers.py; no vendor sample file was
available when it was written, so report files it misreads.
Positions are converted onto the contract's millimetre convention using the header's
Units field (m, cm, dm, mm or in; metres, for example, are
multiplied by 1000). Missing samples --- empty cells, non-numeric cells and
exact-zero XYZ triples (the gap convention :func:read_qtm_tsv also honours) ---
become NaN, never zeros. The Frame# and Time columns are consumed and
dropped; nothing else is in a TRC file, so nothing else is discarded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to the |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple[list[str], ndarray, float | None]
|
|
Source code in musicalgestures/_mocap.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | |
read_c3d ¶
read_c3d(path)
Read the marker trajectories of a C3D motion-capture file.
C3D is the binary interchange standard of the motion-capture world; Qualisys,
OptiTrack, Vicon and Theia3D all export it. Reading rides on the optional
ezc3d <https://github.com/pyomeca/ezc3d>_ library, installed with
pip install musicalgestures[c3d] (or pip install ezc3d); MGT's C3D writer
(pose(data_format='c3d')) uses the lighter pure-Python c3d package, and the
[c3d] extra installs both.
Written against files written and read back through ezc3d itself (the test suite's ground truth) and the C3D specification at https://www.c3d.org; no vendor sample file was available when it was written, so report files it misreads.
Positions are converted onto the contract's millimetre convention using the file's
POINT:UNITS parameter (metres, for example, are multiplied by 1000); a file
without the parameter is taken to be in millimetres already, the format's dominant
convention. Missing samples become NaN, never zeros: ezc3d already yields NaN
for samples flagged invalid, and this reader additionally masks any sample whose
residual is negative --- the C3D convention for missing data.
Only the point (marker) data are read. Analog channels (force plates, EMG, audio sync), events, rotations and the force-platform parameters are NOT read; they are in the file untouched, and a reader for them would be a separate function, not a silent extension of this one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to the |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple[list[str], ndarray, float]
|
|
Source code in musicalgestures/_mocap.py
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | |
read_freemocap ¶
read_freemocap(path)
Read the body trajectories of a FreeMoCap recording folder.
FreeMoCap <https://freemocap.org>_ is a markerless, multi-camera video-based
motion-capture system. Every released version of it (v1.0 through v1.8 verified in
the source, and the current rewrite still writes the same layout, which its
recording-structure documentation calls the legacy layout) saves the triangulated
body trajectories as output_data/mediapipe_body_3d_xyz.npy inside the recording
folder --- a float array of shape (frames, 33, 3) over MediaPipe's 33-landmark
body topology, in millimetres in the calibrated coordinate frame, with NaN
wherever a landmark could not be triangulated. Those NaN values pass through
unchanged and the millimetres are returned as they are; both conventions match the
contract already, so nothing is converted.
path is the recording folder; passing the output_data folder or the
*_body_3d_xyz.npy file itself also works. A body file written by a tracker
other than MediaPipe (FreeMoCap also names rtmpose_body_3d_xyz.npy files), or
one whose landmark count is not 33, is read with generic marker names
(landmark_0, ...) and a warning rather than mislabelled with MediaPipe names.
When no body file is found, a :class:ValueError names the expected files.
The frame rate is derived from the recording's own timestamp records under
synchronized_videos/timestamps/, the same way FreeMoCap's
get_recording_framerate derives it: the median rate in skellycam's
*_stats.json, else the median of the per-frame from_previous.framerate.hz
column in the *timestamps.csv files, else the median frame interval of the
per-camera nanosecond-timestamp .npy arrays that older recordings carry. The
per-camera rates reported by the video containers are not used --- cameras in one
synchronised recording disagree with each other about them --- and when no
timestamp record exists fs is None with a warning, never a guessed default.
Only the body trajectories are read. The hand and face trajectories
(*_right_hand_3d_xyz.npy, *_left_hand_3d_xyz.npy, *_face_3d_xyz.npy),
the centre-of-mass data (center_of_mass/), the pre-filtering raw_data
folder with its reprojection errors, the CSV and by-frame JSON exports and the
videos are NOT read; they are in the folder untouched.
Written against the FreeMoCap source (the saver in
core_processes/post_process_skeleton_data/split_and_save.py, the loader in
data_layer/data_saver/data_loader.py and the frame-rate derivation in
core/tasks/mocap/mocap_helpers/recording_framerate.py, at v1.8.2 and current
main) and the synthetic fixtures in tests/test_mocap_readers.py; no real
recording was available when it was written, so report recordings it misreads.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path to the recording folder (or to its |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple[list[str], ndarray, float | None]
|
|
Source code in musicalgestures/_mocap.py
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | |