mt_corridor() identifies segments of a track where the
animal was moving quickly in a spatially consistent direction. It is a
port of the legacy move::corridor() function (LaPoint et
al. 2013) to the modern move2 / sf stack — the
concept is unchanged.
When to use corridor detection
The typical context is a migratory or commuting animal that travels between two (or several) regions via recognisable routes. Within those routes, successive segments point the same way and are traversed at speed; elsewhere on the track the animal forages or rests at slow, directionally inconsistent speeds. Corridor detection asks: which segments of the track belong to the route, and which belong to the foraging / resting stretches at each end?
The algorithm in one paragraph
For each segment i of the track, compute its speed and
azimuth. Build a search circle centred at the segment midpoint with
radius equal to half the segment length. Collect all other segment
midpoints inside that circle. Compute the circular variance of
pseudo-azimuths
((180 + azimuth) * 2 mod 360) within the neighbourhood —
the doubling is what lets two animals walking the same corridor in
opposite directions count as consistent. A segment is classified as
corridor if (a) its speed exceeds the global
speed_quantile, (b) its neighbourhood’s circular variance
is below the global circ_quantile, and (c) the
neighbourhood contains at least min_segments qualifying
neighbours, which must outnumber the non-qualifying ones.
Load data
The function requires geographic coordinates
(EPSG:4326) so that the search radius can be computed in metres on the
sphere with geosphere. Re-project if necessary.
library(move2)
library(sf)
library(move2utils)
## fisher data (already in WGS84)
fishers <- mt_read(mt_example())
fishers <- fishers[!st_is_empty(fishers), ]
leroy <- filter_track_data(fishers, .track_id = "M1")
st_crs(leroy)$input
#> [1] "EPSG:4326"Run corridor detection on a fisher
out <- mt_corridor(leroy)
#> Found 22 corridor segments (2.4% of 918 segments).
table(out$corridor)
#>
#> corridor not corridor
#> 22 897Five columns are added to the input move2:
-
corridor— factor with levels"corridor"and"not corridor". -
corridor_speed— per-segment speed (m/s), last rowNA. -
corridor_azimuth— per-segment azimuth (degrees), last rowNA. -
corridor_circvar— circular variance of pseudo-azimuths within the segment’s neighbourhood. -
corridor_n_neighbours— number of segments found within the search radius.
A quick map
corr <- as.character(out$corridor)
out$segments <- mt_segments(out)
plot(out$segments, col = c("firebrick","grey80")[as.factor(out$corridor)], asp = 1,
lwd=c(2,0.7)[as.factor(out$corridor)],
main = sprintf("Leroy (fisher): %d corridor segments of %d",
sum(corr == "corridor"), length(corr)))
points(out, col = c("firebrick","grey40")[as.factor(out$corridor)], pch = 16,
cex = c(0.6,0.3)[as.factor(out$corridor)])
legend("topright", pch = 16, col = c("grey40", "firebrick"),
legend = c("not corridor", "corridor"), bty = "n")
Leroy’s track with the minority of segments that meet the default corridor criteria (fast, directionally consistent) highlighted in firebrick. Most of the track — slower, tightly looping foraging movement — stays grey. The corridor segments here are the sparse commuting segments between forage patches.
Tightening speed_quantile and circ_quantile
makes the detector more conservative — only the fastest, most
directionally consistent portions qualify.
Tuning
| Argument | Default | What to tune it for |
|---|---|---|
speed_quantile |
0.75 | Raise for stricter speed cutoff (more conservative). Lower to catch slower but directionally consistent travel (e.g. a plodding long-distance walker). |
circ_quantile |
0.25 | Lower for tighter directional consistency. Raise if the corridor genuinely winds. |
min_segments |
2 | Minimum neighbourhood support. Raise if you want only well-populated corridor stretches. |
Further reading
- LaPoint, S., Gallery, P., Wikelski, M., & Kays, R. (2013). Animal behavior, cost-based corridor models, and real corridors. Landscape Ecology, 28, 1615–1630. https://doi.org/10.1007/s10980-013-9910-0
-
?mt_corridorfor the full argument reference.