Important
This release contains several breaking changes. Please read the notes below carefully before updating.
To update movement to the latest version, see the update guide.
What's Changed
⚡️ Highlight 1: New path analysis functions
- Add function for computing path straightness index by @isha822 in #831
- Implement
compute_directional_changefor path complexity by @vybhav72954 in #991 - Implement
compute_path_deviationby @Haris-bin-shakeel in #982 - Move compute_turning_angle from orientation to path by @isha822 in #1014
- Dropped
start/stopkwargsfromcompute_path_lengthandcompute_path_straightnessby @vybhav72954 in #987
Thanks to @isha822, @vybhav72954, and @Haris-bin-shakeel for contributing three new path analysis functions! The movement.kinematics.path sub-module now provides a comprehensive suite of trajectory metrics:
Note
By path we refer to the spatial trajectory of an individual over the time span of the data.
While these metrics can be computed based on any set of keypoints, they are most meaningful when applied to a single keypoint representing the individual's overall position (e.g., centroid).
-
compute_path_straightness()computes the straightness index of a path — the ratio of the Euclidean ("beeline") distance between start and end positions to the total path length. Values range from 0 (returned to start) to 1 (perfectly straight). -
compute_directional_change()computes the rate of heading change per time step — the absolute turning angle divided by the time interval. -
compute_path_deviation()computes the perpendicular distance of each position from the straight line connecting the first and last valid positions. Zero means the position lies exactly on the straight line; larger values indicate greater lateral excursion.
from movement.kinematics import (
compute_path_straightness,
compute_directional_change,
compute_path_deviation,
)
# Compute the path traced by each individual's centroid
centroid = ds.position.mean(dim="keypoint")
si = compute_path_straightness(centroid)
dc = compute_directional_change(centroid)
deviation = compute_path_deviation(centroid)
max_deviation = deviation.max(dim="time") Additionally, compute_turning_angle has been moved from movement.kinematics.orientation to movement.kinematics.path, alongside the other path metrics. It remains importable from movement.kinematics as before.
Warning
The start and stop keyword arguments have been removed from compute_path_length(). Use xarray's .sel() for time-windowing instead:
# Before
compute_path_length(position, start=0, stop=100)
# After
compute_path_length(position.sel(time=slice(0, 100)))⚡️ Highlight 2: Dimension names renamed from plural to singular
The xarray dimension names "keypoints" and "individuals" have been renamed to "keypoint" and "individual", following standard pandas/xarray conventions where dimensions represent variable names, not collections.
Warning
This is a breaking change. Any code that references these dimension names directly must be updated.
Migrating your code:
# Before (v0.16.0 and earlier)
ds.position.sel(keypoints="snout")
ds.position.sel(individuals="mouse1")
ds.sizes["keypoints"]
# After (v0.17.0)
ds.position.sel(keypoint="snout")
ds.position.sel(individual="mouse1")
ds.sizes["keypoint"]The dim parameter of movement.kinematics.compute_pairwise_distances() has also been updated:
# Before
compute_pairwise_distances(data, dim="keypoints", pairs="all")
# After
compute_pairwise_distances(data, dim="keypoint", pairs="all")Migrating netCDF files saved with previous versions:
If you have netCDF files saved with movement < 0.17.0, you can update them using the rename_legacy_dimensions() utility (available temporarily to help with the transition):
import xarray as xr
from movement.io.load import rename_legacy_dimensions
ds = xr.open_dataset("old_dataset.nc")
ds = rename_legacy_dimensions(ds)
ds.to_netcdf("new_dataset.nc")🔌 Interoperability
This helps developers of tools that depend on movement programmatically discover which tracking software formats are supported.
- Allow individual-wise confidence arrays by @ishan372or in #989
This paves the way for supporting more tracking software in the future.
🐛 Bug fixes
- Change ylabel from 'speed' to 'accel' by @yvonne0006 in #942
- Log default name assignment at INFO instead of WARNING level by @Tushar7012 in #832
- User warning by @lochhh in #976
- Enforce strict time alignment in load_multiview_dataset by @ishan372or in #898
🗑️ Removed functions
The following deprecated functions have been removed:
compute_displacement(deprecated since v0.9.1) — usecompute_forward_displacement()orcompute_backward_displacement()instead.load_poses.from_file(deprecated since v0.14.0) — useload_dataset()instead.load_bboxes.from_file(deprecated since v0.14.0) — useload_dataset()instead.load_poses.from_multiview_files(deprecated since v0.14.0) — useload_multiview_dataset()instead.
🤝 Improving the contributor experience
- Migrate
devanddocsfrom optional dependencies to PEP 735 dependency groups by @lochhh in #956 - Fix invalid --all-groups flag in contributing docs by @niksirbi in #979
- Add pre-commit hook to prevent hardcoded movement website references in docs by @lochhh in #1010
- Update bbox nan fixture by @anna-teruel in #1020
📚 Documentation
- Update and clarify the project's long-term vision by @niksirbi in #1019
- Show ABlog postcard in blog post sidebar by @niksirbi in #990
🧹 Housekeeping
- Use custom
typehints_formatterto handle PEP 695TypeAliasTypeby @lochhh in #969 - Pin
sphinx-autodoc-typehints>=3.10.4by @lochhh in #1016 - Use GitHub App token in contributors workflow by @niksirbi in #971
- Contributors-Readme-Action: Update contributors list by @github-actions[bot] in #970
- Bump conda-incubator/setup-miniconda from 3.3.0 to 4.0.1 by @dependabot[bot] in #972
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #974
- Contributors-Readme-Action: Update contributors list by @neuroinformatics-unit-bot[bot] in #1015
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #1018
New Contributors
- @yvonne0006 made their first contribution in #942
- @vybhav72954 made their first contribution in #987
- @neuroinformatics-unit-bot[bot] made their first contribution in #1015
- @anna-teruel made their first contribution in #1020
- @Haris-bin-shakeel made their first contribution in #982
Full Changelog: v0.16.0...v0.17.0