Utility functions for animal-movement data stored as move2 objects. A home for a handful of ports from the legacy move package, together with a small amount of novel scientific machinery described in a companion paper.
What’s in the package
| Topic | Functions | Provenance |
|---|---|---|
| Utilisation distributions & variance |
mt_dbbmm_variance(), mt_dbbmm_ud(), mt_dbgb_variance(), mt_dbgb_ud(), mt_motion_variance(), mt_suggest_dbbmm_window(), ud_volume(), ud_outer_probability(), emd()
|
Ported from move. C kernels kept; deprecated sp dependencies dropped in favour of sf/terra. |
| Corridor detection | mt_corridor() |
Ported from move::corridor() (LaPoint et al. 2013). Spatial-indexing (sf R-tree) replaces the old sp/rgeos path. |
| Outlier detection — four primitives + unified entry-point |
mt_clean_track() (unified entry-point), mt_flag_outliers_bridge(), mt_flag_outliers_detour(), mt_flag_outliers(), mt_flag_speed_cap(), mt_peel_speed(), v_phys_estimate(), mt_suggest_speed_cap(), mt_diagnose_clean_track(), mt_flag_consensus()
|
New. Four complementary primitives (geometric bridge-residual, path-vs-displacement detour ratio, probabilistic movement-metric, step-level speed cap) composable individually or through mt_clean_track() which iterates them under the class-aware consensus rule (configurable via consensus =) plus topological block-expansion. Described in the companion paper. |
| Outlier detection — state-aware bridge variants (standalone) |
mt_flag_outliers_dbgb(), mt_flag_outliers_dbbmm()
|
Estimate per-axis bridge motion variance and flag fixes via an envelope rule across three Z channels (bridge_z_class taxonomy); useful when behavioural states make a single global threshold over- or under-flag. Currently exported as standalone primitives, not wired into the cascade. |
| Outlier detection — alternative strategies |
mt_sequential_outliers(), mt_combined_outliers()
|
Voting/scanning alternatives on the probability surface. See ?mt_clean_track’s @seealso for when to reach for each. |
| Outlier detection — multi-scale persistence annotation | mt_persistence_score() |
Detector-agnostic confidence helper. Annotates any flagger’s output with a per-flag persistence score across temporal scales; recommended use is class-aware filtering on cascade output. See vignette("OUTLIER_5_persistence_score"). |
| Pre-cleaning helpers |
mt_filter_gps_quality(), mt_mask_segments()
|
Drop fixes whose GPS geometry is unreliable; mask track segments by predicate. |
| Trajectory utilities |
mt_thin_distance(), mt_thin_time()
|
Distance- and time-based thinning, preserving track IDs. |
All functions operate directly on move2 objects and preserve CRS, track IDs, timestamps, and metadata.
Installation
# install.packages("remotes")
# MPCDF GitLab (the canonical home; CI builds the docs site here)
remotes::install_gitlab("anenvi/r-packages/move2utils", host = "gitlab.mpcdf.mpg.de", build_vignettes=TRUE)-
Required:
move2,sf,terra,units. -
Suggested:
circular,geosphere,MASS,lwgeom,lubridate,dplyr,parallel,testthat,knitr.
Quick tour
Utilisation distributions
library(move2)
library(move2utils)
fishers <- mt_read(mt_example())
fishers <- fishers[!sf::st_is_empty(fishers), ]
leroy <- fishers[mt_track_id(fishers) == "M1", ]
var <- mt_dbbmm_variance(leroy) # scalar dynamic Brownian bridge
ud <- mt_dbbmm_ud(var) # UD on a common grid
var_d <- mt_dbgb_variance(leroy) # bivariate (directional) bridge
ud_d <- mt_dbgb_ud(var_d)Corridor detection
leroy_ll <- sf::st_transform(leroy, 4326)
out <- mt_corridor(leroy_ll)
table(out$corridor)Outlier detection
## One-call unified detector -- iterates the four primitives with
## class-aware flagging plus topological block expansion, auto-
## projects lon/lat internally, returns in the original CRS.
clean <- mt_clean_track(fishers)
## Or use the primitives individually:
flagged_b <- mt_flag_outliers_bridge(fishers) # geometric (bridge residual)
flagged_t <- mt_flag_outliers_detour(fishers) # geometric (path/displacement)
flagged_p <- mt_flag_outliers(fishers) # probabilistic
flagged_s <- mt_flag_speed_cap(fishers) # step-level speed
## Directional bridge variant -- classify errors into parallel vs
## perpendicular residuals (error-morphology classification)
flagged_d <- mt_flag_outliers_bridge(fishers, method = "directional")
## State-aware bridge primitive -- per-axis envelope rule with the
## bridge_z_class diagnostic taxonomy. Standalone (not wired into
## the cascade); useful when behavioural states make a global
## threshold over- or under-flag.
flagged_z <- mt_flag_outliers_dbgb(fishers)Which function should I use?
| Task | Function |
|---|---|
| Estimate dynamic motion variance |
mt_dbbmm_variance() / mt_dbgb_variance()
|
| Compute a utilisation distribution |
mt_dbbmm_ud() / mt_dbgb_ud()
|
| Flag corridor segments | mt_corridor() |
| One-call outlier cleanup | mt_clean_track() |
Post-run health check on mt_clean_track() output |
mt_diagnose_clean_track() |
| Geometric per-fix outlier detection (leverage-immune) | mt_flag_outliers_bridge() |
| Geometric, time-insensitive (path/displacement ratio) | mt_flag_outliers_detour() |
| Probabilistic per-fix outlier detection | mt_flag_outliers() |
| Step-level impossible-speed outlier detection | mt_flag_speed_cap() |
| Iterative speed peel for coherent multi-fix error clusters | mt_peel_speed() |
Allometric physiological speed cap from (mass, mode)
|
v_phys_estimate() |
| Inspect a track’s speed distribution and suggest a cap | mt_suggest_speed_cap() |
| Classify the kind of error at each flagged location (directional residual) | mt_flag_outliers_bridge(method = "directional") |
State-aware bridge primitive with per-axis envelope rule + bridge_z_class taxonomy |
mt_flag_outliers_dbgb() |
| Isotropic state-aware bridge primitive (faster; one Z channel) | mt_flag_outliers_dbbmm() |
| Sequential scan from confirmed-good fixes (alternative strategy) | mt_sequential_outliers() |
| Majority vote across gap / entropy / sequential strategies | mt_combined_outliers() |
| Per-flag confidence via multi-scale persistence (cascade or any flagger) | mt_persistence_score() |
| Short track with a longer clean reference | mt_flag_outliers(x, reference = long) |
| Pre-cleaning: drop fixes with bad GPS geometry | mt_filter_gps_quality() |
Vignettes
The cleaning workflow has its own ordered set of vignettes; readers new to the package should walk them in this order.
Outlier cleaning (workflow order):
-
vignettes/OUTLIER_1_getting_started.Rmd— the one-callmt_clean_track()workflow on a bundled synthetic track with known outliers, then a brief tour of each primitive for users who want finer control. -
vignettes/OUTLIER_4_outlier_bridge.Rmd— the geometric bridge-residual primitive in depth (combined / isotropic / directional methods, error-morphology classification). -
vignettes/OUTLIER_example_outlier_whitestork.Rmd— a worked example on a real white-stork track with multi-state behaviour and migration spikes. -
vignettes/OUTLIER_2_diagnose_clean_track.Rmd— post-run health check. Six diagnostic panels analogous toplot.lm()for a GLM; tells you when the cleaner over-flagged and points at the remedy. Read this if yourmt_clean_track()result looks suspicious. -
vignettes/OUTLIER_3_state_conditional.Rmd— recipe for the multi-state failure mode the diagnostic flags. The supported manual path until a first-class state-conditional API ships.
Other utilities:
-
vignettes/OUTLIER_example_leo_migration.Rmd— worked outlier-detection example on long-distance migration data. -
vignettes/UD_dbbmm_ud.Rmd/vignettes/UD_dbgb_ud.Rmd/vignettes/UD_ud_comparison.Rmd— utilisation-distribution workflows. -
vignettes/UD_bursted_uds.Rmd— context-aware (per-burst) dBBMM/dBGB using thedplyridiom that replacesmove::burst. -
vignettes/corridor.Rmd— corridor detection on a raw track. -
vignettes/UD_gap_aware_ud.Rmd/vignettes/interpolate_and_thin.Rmd— supporting workflows.
When the cleaner over-flags (and when to supply (mass, mode))
mt_clean_track() has two failure modes the user should recognise. Both are documented by empirical benchmarks committed in this repo and are signalled by the diagnostic suite at run time.
Failure mode 1 — multi-state behaviour with no real outliers
On tracks where the animal has very different speed regimes (resting at colony + flight, wintering + migration, perched + foraging), per-fix detectors threshold against the dominant baseline distribution and flag the minority state’s fixes as anomalous — even when none are GPS errors.
Empirical example: Columba livia Saline-20160803-048308 (homing pigeon, n = 5479). The pigeon has two modes — perched at the loft (0.10 m/s) and racing flight (15.2 m/s). With naive defaults mt_clean_track() flags 696 fixes (12.7 %) — all of which are racing flight, not GPS errors. Naive speed cap and atlastools correctly flag 0 on this track because the racing flight is biologically below the 30 m/s physiological cap.
Symptoms: very high flag rate (>5 %) on a track with no visible off-trajectory fixes; mt_diagnose_clean_track() Panel 1 shows multiple substantive modes; Panel 2 shows a sustained band of elevated flag rate corresponding to the minority state.
What to do: see vignette(“OUTLIER_3_state_conditional”) — segment by speed mode, run mt_clean_track() per segment, recombine. Or filter the track to one state before cleaning.
Failure mode 2 — block-shaped contamination at naive defaults
On tracks with sustained contaminated trains (GPS spoofs, deployment confusion, multi-fix data corruption) the auto-cap can land at biologically absurd values (the data’s own outliers define a “gap” the auto-cap finds). The speed primitive then doesn’t fire on the spoof boundaries reliably enough for block expansion to seed, so the contaminated train is silently kept.
Empirical example: K02 golden eagle (real Movebank study 2830439412, n = 851 k, 175-fix spoof in 2025-06-14). With naive defaults mt_clean_track() recovers 0 / 175 spoof fixes (auto-cap landed at 88 m/s, far above any biological eagle speed). With (mass = 4.5, mode = "flying") the same wrapper recovers 175 / 175 via block expansion.
Symptoms: very few final flags despite a track that obviously has contaminated regions; the wrapper now prints a “primitive-disagreement signature” warning when bridge caught flags the conjunction dropped — supplying mass+mode resolves this.
What to do: supply (mass, mode) to mt_clean_track() (auto-derives a Hirt 2017 physiological cap), or pass v_max = <published_value> for sprint-mode-aware species. The wrapper also warns when the auto-cap lands above 50 m/s.
Empirical evidence
-
65-individual stratified Movebank audit (
audits/2026-04-29-stratified-movebank/findings.md): 75 % PASS, 95 % defensible, 0 crashes on naive defaults; the 5 % OVER_FLAG cases all hit Failure mode 1. -
Three head-to-head benchmarks (
benchmarks/2026-XX-XX-vs-competitors/):- Phase 1 (synthetic): mt_clean F1 = 0.98, atlastools F1 = 0.74, naive F1 = 0.76, trip::sda F1 = 0.04.
- Phase 2 (K02 spoof): mt_clean tier 1 (mass+mode) recovers 175/175; per-fix competitors recover 2/175 (boundaries only).
- Phase 3 (audit subset, real multi-state): mt_clean over-flags 5892 multi-state behaviour fixes; naive and atlastools correctly flag 0.
Each adjustable parameter targets a specific empirically-distinguishable failure mode. The diagnostic suite tells the user which knob to reach for.
Companion projects
- MEE Application Note (multi-author, package overview): https://gitlab.mpcdf.mpg.de/macroeco/move2utils_mee_note
- MEE Application paper (single-author, outlier-detection methodology): https://gitlab.mpcdf.mpg.de/macroeco/outlier_mee_paper
The two manuscripts evolve at their own cadences and live in their own GitLab repositories; this package no longer carries them as submodules.
Background
The corridor concept follows LaPoint, Gallery, Wikelski & Kays (2013) Landscape Ecology 28: 1615–1630.
The outlier-detection framework — four complementary primitives (geometric bridge residual, path-vs-displacement detour ratio, probabilistic movement-metric, step-level speed cap) sharing a gap-aware non-parametric normalisation and combinable through an iterative unified detector with class-aware flagging plus topological block expansion — is the novel scientific content of the package and is described in the companion paper (in preparation, Methods in Ecology and Evolution).
Citation
Safi K (2026). move2utils: Utility Functions for Movement Data Based on move2.
R package version 0.3.2. https://gitlab.mpcdf.mpg.de/anenvi/r-packages/move2utils