Skip to content

[Metrics] Add function for computing E_max (maximum expected displacement)Β #905

@vybhav72954

Description

@vybhav72954

Is your feature request related to a problem? Please describe.
$E_{\max}$ is a scale-independent straightness measure based on eigenvalue decomposition of the mean step rotation matrix. Unlike the straightness index ($D/L$), which is sensitive to trajectory length, $E_{\max}$ characterises the inherent directional persistence of the movement process itself. Computes how far an animal is expected to travel given its typical turning behavior and step lengths. It is one of the core trajectory complexity metrics identified in the trajr paper

Definition

Given the mean cosine $\bar{c}$ and mean sine $\bar{s}$ of turning angles, define the mean step rotation matrix:

$$\mathbf{M} = \begin{pmatrix} \bar{c} & -\bar{s} \ \bar{s} & \bar{c} \end{pmatrix}$$

Then:

$$E_{\max}^{(a)} = \lambda_{\max}\left[(\mathbf{I} - \mathbf{M})^{-1}\right]$$

where $\lambda_{\max}$ denotes the largest eigenvalue.

  • $E_{\max}^{(a)}$ is dimensionless (scale-independent).
  • $E_{\max}^{(b)} = E_{\max}^{(a)} \cdot \bar{p}$ gives the maximum expected displacement in spatial units (where $\bar{p}$ is the mean step length).

Range: $[0, \infty)$. Values near 0 indicate highly sinuous paths; larger values indicate straighter paths.

Alternative names

Also referred to as: maximum expected displacement, Cheung's Emax, Emax-a (dimensionless) / Emax-b (spatial).

Pseudocode

function compute_emax(data, emax_b=False, nan_policy="ffill"):
    # 1. Compute turning angles (depends on movement#833)
    theta = compute_turning_angle(data)
 
    # 2. Compute step lengths
    step_lengths = compute_norm(compute_forward_displacement(data))
 
    # 3. Handle NaN per nan_policy
 
    # 4. Compute mean cosine and sine of turning angles
    c_bar = nanmean(cos(theta))
    s_bar = nanmean(sin(theta))
 
    # 5. Build mean rotation matrix M
    M = [[c_bar, -s_bar],
         [s_bar,  c_bar]]
 
    # 6. Compute (I - M)^{-1}
    I_minus_M = eye(2) - M
    inv_matrix = inv(I_minus_M)
 
    # 7. Emax-a = largest eigenvalue of inv_matrix
    eigenvalues = eigvals(inv_matrix)
    emax_a = max(real(eigenvalues))
 
    # 8. Optionally scale by mean step length
    if emax_b:
        return emax_a * nanmean(step_lengths)
    return emax_a

Parameters:

  • emax_b: If True, return $E_{\max}^{(b)}$ (spatial units). Default False returns $E_{\max}^{(a)}$ (dimensionless).

Returns: A scalar per individual/keypoint, with time and space dimensions removed.

References

Context

Opened following discussion with @niksirbi on Zulip. Related to #406. Depends upon #833

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    πŸ€” Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions