How Is the Transfer Threshold Calculated in Google Timeline Visualizer?
The transfer threshold in Google Timeline Visualizer uses a robust statistical approach based on median leg length and dispersion, clamped between 60–120 km, to automatically detect journey segments that qualify as transfers.
The transfer threshold determines when a journey segment is long enough to be considered a transfer — a point where the visualizer pauses or adjusts camera behavior. This calculation lives in web/src/camera.ts and adapts dynamically to each journey's travel pattern. Understanding how the transfer threshold is calculated helps you debug camera transitions and customize the visualization for different trip types.
Where the Transfer Threshold Calculation Lives
The core logic resides in web/src/camera.ts, specifically within the transferThreshold function (lines 19–29). This module also contains buildLegs, which consumes the computed threshold to classify journey segments.
Supporting type definitions appear in web/src/types.ts (CameraJourney, JourneyLeg), while web/src/renderer.ts executes the camera animations based on leg classifications. Unit tests in tests/test_camera.py validate the threshold behavior.
How the Transfer Threshold Is Calculated: Step by Step
The algorithm follows five distinct phases to produce a journey-specific threshold.
Step 1: Filter Ordinary Leg Distances
The function first extracts consecutive leg distances from cumulativeDistanceKm:
// distances[i] = cumulativeDistanceKm[i] - cumulativeDistanceKm[i-1]
Only positive distances under 120 km are retained. This filtering excludes:
- Negative values (data errors)
- Zero-length segments
- Extreme outliers (very long jumps that would skew statistics)
Step 2: Compute the Typical Leg Length
The retained distances are sorted, and the median is taken as typical:
- The median is robust against irregularities
- It represents the "normal" leg length for this specific journey
Step 3: Measure Dispersion
For each ordinary distance, the absolute deviation from typical is calculated. The median of these deviations becomes deviation — a robust estimate of how much leg lengths typically vary.
Step 4: Calculate Raw Threshold Candidates
Two candidate values are computed:
| Candidate | Formula | Purpose |
|---|---|---|
| Multiple-based | typical × 3 |
Catches legs significantly longer than normal |
| Deviation-based | typical + deviation × 6 |
Accounts for high-variance journeys |
The larger of these two values is selected as the raw threshold.
Step 5: Clamp to Valid Bounds
The raw threshold is forced into the range 60 km … 120 km using Math.max/Math.min or a clamp helper. If no ordinary legs exist (all jumps exceed 120 km), the function falls back to 120 km.
Applying the Transfer Threshold in Practice
The computed threshold drives segment classification in buildLegs:
const threshold = transferThreshold(journey.cumulativeDistanceKm);
if (endKm - startKm < Math.max(1, threshold)) continue; // skip tiny legs
Segments shorter than the threshold are treated as continuous motion; longer segments trigger transfer behavior (camera pause, view reset, etc.).
Complete Usage Example
import { buildLegs, transferThreshold } from './camera';
// Example journey with cumulative distances in km
const journey = {
worldPoints: [...], // coordinates
cumulativeDistanceKm: [0, 5, 12, 18, 25, 45, 120, 125]
};
// Compute threshold for this specific journey
const thresh = transferThreshold(journey.cumulativeDistanceKm);
console.log(`Transfer threshold: ${thresh} km`);
// Output: threshold between 60–120 km based on median leg patterns
// Build classified legs
const legs = buildLegs(journey);
/* legs contains:
{
startKm: number,
endKm: number,
isTransfer: boolean // true if segment exceeds threshold
}
*/
Why This Statistical Approach Works
The transfer threshold calculation uses median-based robust statistics rather than mean-based methods for good reason:
- Median resists influence from occasional very long or very short legs
- Median absolute deviation (MAD) provides stable spread estimation
- The max-of-two-candidates strategy handles both consistent and variable journey patterns
- Hard bounds (60–120 km) prevent pathological thresholds on unusual journeys
This design ensures the visualizer behaves reasonably across diverse travel types — from dense urban commutes with 2 km legs to cross-country road trips with 80 km stretches.
Key Files and Functions
| File | Key Elements |
|---|---|
web/src/camera.ts |
transferThreshold() (lines 19–29), buildLegs() |
web/src/types.ts |
CameraJourney, JourneyLeg interfaces |
web/src/renderer.ts |
Consumes leg data for camera animation |
tests/test_camera.py |
Unit tests for threshold and leg logic |
Summary
- The transfer threshold is calculated in
web/src/camera.tsusing median-based robust statistics - Only ordinary legs under 120 km inform the calculation, filtering outliers
- Two candidates (
typical × 3vs.typical + deviation × 6) compete; the larger wins - Final threshold is clamped to 60–120 km, with 120 km as fallback
buildLegsuses this threshold to mark segments as transfers viaisTransfer
Frequently Asked Questions
What happens if a journey has no legs under 120 km?
The transferThreshold function detects this edge case and returns 120 km as the fallback value. All segments then qualify for potential transfer detection, preventing division by zero or empty-array errors in the median calculations.
Why use median instead of mean for the typical leg length?
The median is robust against outliers. A single 500 km flight segment among city hops would wildly skew a mean-based threshold, whereas the median remains representative of the typical travel pattern. This matches the visualizer's goal of adapting to common journey characteristics.
Can I override the 60–120 km clamp bounds?
The bounds are hardcoded in camera.ts. To customize them, you would modify the clamp call within transferThreshold or post-process the returned value in your own wrapper. The repository does not expose these as configuration parameters.
How does buildLegs use the threshold differently for walking vs. driving journeys?
It doesn't — the threshold adapts automatically. A walking journey with 1 km median legs yields a threshold near 60 km (the floor), while a driving journey with 30 km median legs likely hits typical × 3 = 90 km. The statistical method self-tunes to each journey's scale without mode-specific logic.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →