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.ts using median-based robust statistics
  • Only ordinary legs under 120 km inform the calculation, filtering outliers
  • Two candidates (typical × 3 vs. typical + deviation × 6) compete; the larger wins
  • Final threshold is clamped to 60–120 km, with 120 km as fallback
  • buildLegs uses this threshold to mark segments as transfers via isTransfer

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →