Here is an Import function I made for my GPX files that computes various quantities:
ClearAll[ImportGarminGPX,DuplicatePositions]
DuplicatePositions[x_List]:=Module[{nums},
nums=Select[Tally[x],Last[#]>1&][[All,1]];
Flatten[Rest/@(Position[x,#]&/@nums)]
]
ImportGarminGPX[fn_String,ignorepts:{n_Integer,m_Integer}:{0,0},timezone_:2]:=Module[{data,hr,trail,rawtrail,elevation,elevationunits,abstime,time,date,dups,distances,distance,speed,slen,smoothspeed,avgspeeds,avgspeed,laf,lof,trailfunction,elevationgain,maxhr,hb,avghr,runningmin,runningmax,biggestclimb,biggestdrop},
data=Import[fn,"XML"];
data=Cases[data,XMLElement["trkpt",{"lat"->lat_,"lon"->lon_},other_]:>{ToExpression/@{lat,lon},other},\[Infinity]];
data=Drop[Drop[data,n],-m];
trail=rawtrail=data[[All,1]];
trail=GeoPosition/@trail;
data=data[[All,2]];
abstime=time=Map[FirstCase[#,XMLElement["time",{},{time_}]:>AbsoluteTime[time]+timezone 3600,Missing[],\[Infinity]]&,data];
date=DateObject[First[time]];
time-=First[time];
dups=List/@DuplicatePositions[time]; (* delete duplicate times *)
If[dups=!={},
Print["duplicate time detected removing indices:",dups];
time=Delete[time,dups];
abstime=Delete[abstime,dups];
trail=Delete[trail,dups];
rawtrail=Delete[rawtrail,dups];
data=Delete[data,dups];
];
elevationunits=elevation=Map[FirstCase[#,XMLElement["ele",{},{ele_}]:>ToExpression[ele],Missing[],\[Infinity]]&,data];
elevationunits=Quantity[elevation,"Meters"];
runningmin=FoldList[Min,First[elevation],elevation];
runningmax=Reverse[FoldList[Max,First[Reverse[elevation]],Reverse[elevation]]];
biggestclimb=Max[runningmax-runningmin];
runningmin=Reverse[FoldList[Min,First[Reverse[elevation]],Reverse[elevation]]];
runningmax=FoldList[Max,First[elevation],elevation];
biggestdrop=Max[runningmax-runningmin];
hr=Map[FirstCase[#,XMLElement[{"http://www.garmin.com/xmlschemas/TrackPointExtension/v1","hr"},{},{hr_}]:>ToExpression[hr],Missing[],\[Infinity]]&,data];
distances=BlockMap[GeoDistance@@#&,trail,2,1];
distances=Prepend[QuantityMagnitude[distances,"Meters"],0.0];
distance=Accumulate[distances];
speed=Differences[distance]/Differences[time];
speed=Join[{speed[[1]]},MovingAverage[speed,2],{speed[[-1]]}];
slen=3;
smoothspeed=Join[Accumulate[speed[[;;slen]]]/Range[slen],MovingAverage[speed,2slen+1],Reverse[Accumulate[Reverse[speed[[-slen;;]]]]/Range[slen]]];
avgspeeds=Prepend[Rest[distance]/Rest[time],0];
avgspeed=Last[avgspeeds];
laf=Interpolation[{time,rawtrail[[All,1]]}\[Transpose],InterpolationOrder->1];
lof=Interpolation[{time,rawtrail[[All,2]]}\[Transpose],InterpolationOrder->1];
trailfunction=Function[t,GeoPosition[{laf[t],lof[t]}]];
elevationgain=Total[Select[Differences[elevation],Positive]];
If[Length[DeleteMissing[hr]]>0,
maxhr=Max[DeleteMissing[hr]];
hb=Interpolation[DeleteMissing[{time,hr/60.0}\[Transpose],1,2],InterpolationOrder->1];
hb=Integrate[hb[t],{t,Min[time],Max[time]}];
avghr=60hb/(Max[time]-Min[time]);
,
maxhr=Missing[];
hb=Missing[];
avghr=Missing[];
];
<|
"AbsoluteTime"->abstime,
"AverageHeartRate"->Round[avghr,0.1],
"AverageSpeed"->avgspeed,
"AverageSpeeds"->avgspeeds,
"BiggestClimb"->biggestclimb,
"BiggestDrop"->biggestdrop,
"Date"->date,
"DateString"->DateString[date,{"Day"," ","MonthName"," ","Year"}],
"Distance"->distance,
"DistanceFunction"->Interpolation[{time,distance}\[Transpose],InterpolationOrder->1],
"Distances"->distances,
"Elevation"->elevation,
"ElevationGain"->elevationgain,
"ElevationUnits"->elevationunits,
"Heartbeats"->hb,
"HeartRate"->hr,
"InverseDistanceFunction"->Interpolation[DeleteDuplicatesBy[{distance,time}\[Transpose],First],InterpolationOrder->1],
"MaximumHeartRate"->maxhr,
"MaxTime"->Max[time],
"RawTrail"->rawtrail,
"SmoothSpeed"->smoothspeed,
"Speed"->speed,
"SpeedFunction"->Interpolation[{time,speed}\[Transpose],InterpolationOrder->1],
"Speedkmh"->3.6 speed,
"Time"->time,
"TotalDistance"->Last[distance],
"Trail"->trail,
"TrailFunction"->trailfunction
|>
]
Here it also calculates various other properties:
AbsoluteTime
AverageHeartRate
AverageSpeed
AverageSpeeds
BiggestClimb
BiggestDrop
Date
DateString
Distance
DistanceFunction
Distances
Elevation
ElevationGain
ElevationUnits
Heartbeats
HeartRate
InverseDistanceFunction
MaximumHeartRate
MaxTime
RawTrail
SmoothSpeed
Speed
SpeedFunction
Speedkmh
Time
TotalDistance
Trail
TrailFunction
Note that the GPX format has a lot of variations and extensions and I can't guarantee it works on your particular GPX file. I have several GPX files from different devices or applications (from e.g. a smart phone), and they are all structurally a little bit different. I tried using FirstCase[....Missing[]..]
everywhere, and I built in some safe-guards but it not completely hooligan-proof! You might have to change the code slightly to adapt it to your files.