Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save andrewmichaelsmith/9ac3624ae3279c01c057550d3708a946 to your computer and use it in GitHub Desktop.
Save andrewmichaelsmith/9ac3624ae3279c01c057550d3708a946 to your computer and use it in GitHub Desktop.
GPX analysis, including gpx to elevation profile chart
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "76a8bc7b",
"metadata": {},
"source": [
"# Some notes on some GPX tinkering and analysis for a blog post\n",
"\n",
"Compared to some other notebooks out there I think this simplifies the charting of an elevation profile from a GPX file a fair bit. Though I had a slightly odd use case (charting gaps when there were large jumps in distance) that might not be suitable for everyone.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f157fe84",
"metadata": {},
"outputs": [],
"source": [
"!pip install gpxpy\n",
"!pip install geopy\n",
"!pip install plotly\n",
"!pip install kaleido"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "060968f3",
"metadata": {},
"outputs": [],
"source": [
"# Pre-work was to use GPSBabel to merge all of the gpx files in to 1\n",
"# https://stackoverflow.com/questions/38554131/merge-all-gpx-files-within-a-folder-into-one-file-with-gpsbabel\n",
"# This produces All.gpx\n",
"# As an optimisation for graphing I grep'd out the time/speed elements and produced `All-notimeorspeed.gpx`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b00abf84",
"metadata": {},
"outputs": [],
"source": [
"# Produce high level stats\n",
"#sudo apt-get install -y gpxinfo\n",
"#gpxinfo -m All.gpx > stats"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "06f8684e",
"metadata": {},
"outputs": [],
"source": [
"import gpxpy\n",
"import gpxpy.gpx\n",
"import math\n",
"import geopy.distance\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import pandas as pd\n",
"\n",
"with open('All.gpx', 'r') as gpx_file:\n",
" gpx = gpxpy.parse(gpx_file)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "230574b1",
"metadata": {},
"outputs": [],
"source": [
"elevation = []\n",
"is_real = []\n",
"distance = []\n",
"\n",
"prev_lat = None\n",
"prev_lon = None\n",
"\n",
"new_track = False\n",
"\n",
"for track in gpx.tracks:\n",
" \n",
"\n",
" for segment in track.segments:\n",
" for point in segment.points:\n",
" if point.elevation:\n",
" \n",
" if(prev_lat is not None):\n",
" diff = geopy.distance.geodesic((prev_lat, prev_lon), (point.latitude, point.longitude)).km\n",
" prev_distance = distance[-1]\n",
" else:\n",
" diff = 0\n",
" prev_distance = 0\n",
" \n",
" # I want to add NaN values for the chart below so that it shows when I jumped (e.g. taking a bus),\n",
" # this is the hack to do that.\n",
" if new_track:\n",
" if diff > 5:\n",
" elevation.append(point.elevation)\n",
" distance.append(prev_distance + 2) \n",
" is_real.append(False)\n",
" \n",
" elevation.append(point.elevation)\n",
" distance.append(prev_distance + diff)\n",
" is_real.append(True) \n",
" \n",
" prev_lat = point.latitude\n",
" prev_lon = point.longitude\n",
"\n",
" \n",
" new_track = True\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3b429505",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"df = pd.DataFrame({\n",
" 'distance': distance,\n",
" 'elevation': elevation,\n",
" 'is_real': is_real\n",
"})\n",
"\n",
"df = df.set_index('distance')\n",
"\n",
"df['elevation'][df.is_real == False] = pd.NA\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "69efac43",
"metadata": {},
"outputs": [],
"source": [
"import plotly.express as px\n",
"\n",
"fig = px.line(\n",
" df,\n",
" y=\"elevation\",\n",
" labels={\"elevation\": \"Elevation (m)\", \"distance\": \"Distance (km)\"},\n",
")\n",
"\n",
"fig.write_image('/home/andy/git/blog/content/images/vancouver-to-tijuana-elevation-main.png', format=\"png\", width=4000, height=450, scale=1)\n",
"fig.write_image('/home/andy/git/blog/content/images/vancouver-to-tijuana-elevation-thumb.png', format=\"png\", width=700, height=250, scale=1)\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment