movement icon indicating copy to clipboard operation
movement copied to clipboard

Computing a (smooth) angular head velocity over time

Open sfmig opened this issue 11 months ago • 5 comments

Is your feature request related to a problem? Please describe. Right now to compute this one would: compute the polar angle of (user-defined) head vector, and then take the derivative.

But the output is probably noisy, we would need to think a bit more how this would be improved

sfmig avatar Dec 13 '24 17:12 sfmig

I forgot, I also used to use: https://github.com/circstat/pycircstat

adamltyson avatar Dec 14 '24 09:12 adamltyson

With #376 (this is my revival of #315, but still in draft), this can become a two step process:

from movement.kinematics import compute_heading_angle, compute_angle_time_derivative

head_angle = compute_heading_angle(ds.position, left_keypoint="left_ear", right_keypoint="right_ear")
angular_head_velocity = compute_angle_time_derivative(head_angle)

#376 just adds the first of these two functions. The envisioned 2nd function (not necessarily named as in the above example) should be added as a solution to this issue. That function should also provide some options for smoothing the derivative (see comments above).

niksirbi avatar Jan 17 '25 11:01 niksirbi

See also @kiradust's excellent notes on circular statistics here.

As far as I can tell, scipy's directional stats submodule implements the "intrinsic" circular mean and variance (see Kira's notes for the difference between "extrinsic" and "intrinsic" circular means).

niksirbi avatar Feb 18 '25 09:02 niksirbi

As far as I can tell, scipy's directional stats submodule implements the "intrinsic" circular mean and variance (see Kira's notes for the difference between "extrinsic" and "intrinsic" circular means).

Correction, after looking into scipy's source code, both me and Kira agree that they are actually computing the "extrinsic" mean.

niksirbi avatar Feb 20 '25 15:02 niksirbi

Hi @niksirbi I have some suggestions for the compute_angle_time_derivative function, there are two ways to approach the smoothing problem: either by smoothing the angle time series first and then differentiating, or by computing the raw angular velocity.

delta_theta = (angles[t+1] - angles[t] + π) % (2π) - π.

For each pair of consecutive angles, compute the smallest angular difference to avoid wrap-around issues. This ensures the difference lies between -π and π, representing the shortest path on the circle. Then, divide by the time step dt to get velocity in radians per second.

I am curious about using the extrinsic mean here as it could introduce bias or edge cases when smoothing head angles, especially near the ±π boundary? If needed, I’d be happy to look into whether implementing an intrinsic mean (or supporting both) would make sense use case. Also, in the direction of compute_angle_time_derivative, I can help draft or test the smoothing logic with both mean types to see which works best under noisy conditions. let me know if there is any way I can provide value here. Thanks

demoncoder-crypto avatar Mar 29 '25 14:03 demoncoder-crypto