pybemobil.preproc.process_rigid_body#

pybemobil.preproc.process_rigid_body(raw, rb_names=None, lowpass_orient=6.0, lowpass_pos=6.0, lowpass_deriv=18.0, compute_velocity=True, compute_acceleration=True, sfreq_target=None, unwrap=True, angle_unit='rad')[source]#

Process rigid body motion capture streams.

For each rigid body found in raw:

  1. Convert quaternions to Euler angles (ZYX convention = yaw-pitch-roll) if quaternion channels are present. The source quaternion channels are dropped and replaced by Euler angle channels.

  2. Unwrap the Euler angles (see unwrap). Samples where the rigid body was not tracked are bridged by linear interpolation first: samples where all of its channels are exactly 0 (how XDFLoader fills dropouts), quaternions with a norm of ~0, and spans annotated BAD_<rb>_missing. Such spans are annotated BAD_<rb>_missing in the output, so they can be rejected later; without bridging, filtering and differentiation would turn them into huge spurious velocities.

  3. Optionally resample all channels to sfreq_target.

  4. Optionally low-pass filter the orientation (and position) signals.

  5. Compute the first derivative (velocity) via finite differences, with an optional low-pass filter applied after differentiation.

  6. Compute the second derivative (acceleration) in the same way.

Derivative channels are appended to the returned raw object with the naming scheme <rb>_<type>_vel_<axis> and <rb>_<type>_acc_<axis>, where type is eul or pos so that orientation and position derivatives always have distinct names (e.g. head_eul_vel_x, head_pos_vel_x).

Parameters:
rawmne.io.BaseRaw

Source recording. Motion channels should be of type "misc" (which is the default when XDFLoader imports non-EEG streams).

rb_nameslist of str | None

Rigid body identifiers to process. If None, all identifiers found by find_rigid_bodies() are processed.

lowpass_orientfloat | None

Low-pass cutoff (Hz) applied to orientation channels. Default 6, BeMoBIL’s lowpass_motion. None skips this filter.

lowpass_posfloat | None

Low-pass cutoff (Hz) applied to position channels. Default 6 (lowpass_motion). None skips.

lowpass_derivfloat | None

Low-pass cutoff (Hz) applied to velocity and acceleration channels after differentiation. Default 18, BeMoBIL’s lowpass_motion_after_derivative. None skips.

compute_velocitybool

Whether to compute and append velocity channels.

compute_accelerationbool

Whether to compute and append acceleration channels. Works with compute_velocity=False too: the velocity is then computed internally but not appended.

sfreq_targetfloat | None

If not None, resample the recording to this rate after the quaternion conversion and before filtering and differentiation. Useful to match the EEG sample rate.

unwrapbool

If True (default), unwrap the Euler angles over time (numpy.unwrap()), as in BeMoBIL. Angles wrap at ±π, so a continuous rotation otherwise produces jumps of 2π that dominate the filtered signal and its derivatives. The returned orientation channels are then continuous and may exceed ±π (±180°).

angle_unit"rad" | "deg"

Unit of Euler input channels (<rb>_eul_*), used to unwrap them with the right period (2π or 360°). Default "rad". A warning is logged when "rad" is given but the angles exceed ±2π, which usually means degrees. Euler angles computed from quaternions are always in radians.

Returns:
raw_outmne.io.Raw

Copy of raw with quaternion channels replaced by Euler channels and velocity / acceleration channels appended.

rb_infodict

Per-rigid-body processing summary: {rb_name: {"mode": "quat->euler"|"euler", "channels": list[str], "n_missing": int}} where n_missing is the number of bridged samples (at the input sampling rate).