Skip to main content

Biometrics

When a GPX file contains extension data (e.g., Garmin TrackPointExtension v1/v2), the CLI automatically extracts and computes biometric statistics.

Supported extensions

SourceData
Garmin TrackPointExtension v1/v2 (<gpxtpx:hr>)Heart rate (bpm)
Garmin TrackPointExtension v1/v2 (<gpxtpx:cad>)Cadence (rpm)
Garmin TrackPointExtension v1/v2 (<gpxtpx:atemp>)Air temperature (°C)
Garmin TrackPointExtension v2 (<gpxtpx:speed>)Device-reported speed (m/s)
Garmin TrackPointExtension v2 (<gpxtpx:wtemp>)Water temperature (°C)
Standard <power> elementPower (watts)

Computed biometric metrics

MetricStatistics
Heart RateAverage, max, min (bpm). HR zones (Z1-Z5) when --max-hr is set
PowerAverage, max (watts), normalized power (NP)
CadenceAverage, max (rpm)
Air TemperatureAverage, min, max (°C)
Water TemperatureAverage, min, max (°C) — present on aquatic activities recorded with a compatible Garmin device

GPS quality fields

Standard GPX 1.1 quality fields are parsed when present and stored per track point:

FieldDescription
<fix>Fix type: none, 2d, 3d, dgps, pps
<sat>Number of satellites used
<hdop>Horizontal dilution of precision
<vdop>Vertical dilution of precision
<pdop>Position dilution of precision

These fields are used by the anomaly detector to identify unreliable GPS points (e.g., hdop > 5 or sat < 4 can correlate with position spikes). They are not directly surfaced in the JSON output summary but influence anomaly detection and speed clamping behaviour.

Device speed vs. computed speed

When <gpxtpx:speed> is present, the device-reported speed (Doppler-derived, in m/s) is stored alongside the computed Haversine speed. The device speed is generally more reliable for instantaneous readings. Significant divergence between the two can indicate a GPS position anomaly.

HR zones

When --max-hr is provided, heart rate zones are computed based on percentage of max HR:

ZoneRangeDescription
Z150-60%Recovery
Z260-70%Endurance
Z370-80%Tempo
Z480-90%Threshold
Z590%+VO2max

Normalized Power (NP)

Computed using a 30-second rolling average of power data, raised to the 4th power, averaged, then taking the 4th root. This metric reflects the physiological cost of variable-intensity efforts.

Examples

Analyze a cycling ride with HR zones:

gpx-analyzer analyze ride.gpx --max-hr 185 --preset cycling

Extract biometrics in JSON:

gpx-analyzer analyze ride.gpx --max-hr 190 --format json | jq '.heart_rate'

Split a ride and track biometrics per segment:

gpx-analyzer split ride.gpx --interval 1h --max-hr 185 --preset cycling

If the GPX file does not contain extension data, biometric sections are simply omitted from the output (both text and JSON).