Source code for movement.analysis.kinematics

"""Compute kinematic variables like velocity and acceleration."""

import xarray as xr

from movement.utils.logging import log_error


[docs] def compute_displacement(data: xr.DataArray) -> xr.DataArray: """Compute displacement array in cartesian coordinates. The displacement array is defined as the difference between the position array at time point ``t`` and the position array at time point ``t-1``. As a result, for a given individual and keypoint, the displacement vector at time point ``t``, is the vector pointing from the previous ``(t-1)`` to the current ``(t)`` position, in cartesian coordinates. Parameters ---------- data : xarray.DataArray The input data array containing position vectors in cartesian coordinates, with ``time`` as a dimension. Returns ------- xarray.DataArray An xarray DataArray containing displacement vectors in cartesian coordinates. Notes ----- For the ``position`` array of a ``poses`` dataset, the ``displacement`` array will hold the displacement vectors for every keypoint and every individual. For the ``position`` array of a ``bboxes`` dataset, the ``displacement`` array will hold the displacement vectors for the centroid of every individual bounding box. For the ``shape`` array of a ``bboxes`` dataset, the ``displacement`` array will hold vectors with the change in width and height per bounding box, between consecutive time points. """ _validate_time_dimension(data) result = data.diff(dim="time") result = result.reindex(data.coords, fill_value=0) return result
[docs] def compute_velocity(data: xr.DataArray) -> xr.DataArray: """Compute velocity array in cartesian coordinates. The velocity array is the first time-derivative of the position array. It is computed by applying the second-order accurate central differences method on the position array. Parameters ---------- data : xarray.DataArray The input data array containing position vectors in cartesian coordinates, with ``time`` as a dimension. Returns ------- xarray.DataArray An xarray DataArray containing velocity vectors in cartesian coordinates. Notes ----- For the ``position`` array of a ``poses`` dataset, the ``velocity`` array will hold the velocity vectors for every keypoint and every individual. For the ``position`` array of a ``bboxes`` dataset, the ``velocity`` array will hold the velocity vectors for the centroid of every individual bounding box. See Also -------- :meth:`xarray.DataArray.differentiate` : The underlying method used. """ return _compute_approximate_time_derivative(data, order=1)
[docs] def compute_acceleration(data: xr.DataArray) -> xr.DataArray: """Compute acceleration array in cartesian coordinates. The acceleration array is the second time-derivative of the position array. It is computed by applying the second-order accurate central differences method on the velocity array. Parameters ---------- data : xarray.DataArray The input data array containing position vectors in cartesian coordinates, with``time`` as a dimension. Returns ------- xarray.DataArray An xarray DataArray containing acceleration vectors in cartesian coordinates. Notes ----- For the ``position`` array of a ``poses`` dataset, the ``acceleration`` array will hold the acceleration vectors for every keypoint and every individual. For the ``position`` array of a ``bboxes`` dataset, the ``acceleration`` array will hold the acceleration vectors for the centroid of every individual bounding box. See Also -------- :meth:`xarray.DataArray.differentiate` : The underlying method used. """ return _compute_approximate_time_derivative(data, order=2)
def _compute_approximate_time_derivative( data: xr.DataArray, order: int ) -> xr.DataArray: """Compute the time-derivative of an array using numerical differentiation. This function uses :meth:`xarray.DataArray.differentiate`, which differentiates the array with the second-order accurate central differences method. Parameters ---------- data : xarray.DataArray The input data array containing ``time`` as a dimension. order : int The order of the time-derivative. For an input containing position data, use 1 to compute velocity, and 2 to compute acceleration. Value must be a positive integer. Returns ------- xarray.DataArray An xarray DataArray containing the time-derivative of the input data. """ if not isinstance(order, int): raise log_error( TypeError, f"Order must be an integer, but got {type(order)}." ) if order <= 0: raise log_error(ValueError, "Order must be a positive integer.") _validate_time_dimension(data) result = data for _ in range(order): result = result.differentiate("time") return result def _validate_time_dimension(data: xr.DataArray) -> None: """Validate the input data contains a ``time`` dimension. Parameters ---------- data : xarray.DataArray The input data to validate. Raises ------ ValueError If the input data does not contain a ``time`` dimension. """ if "time" not in data.dims: raise log_error( ValueError, "Input data must contain 'time' as a dimension." )