{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Happy 2017\n", "We have some GPX files which we want to plot on a nice map.\n", "A lot of the the code below is based on [this python4oceanographers blog post](https://ocefpaf.github.io/python4oceanographers/blog/2014/08/18/gpx/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First we import some packages necessary to achieve what we want." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import numpy\n", "import gpxpy\n", "import mplleaflet\n", "import glob\n", "import os\n", "import pandas\n", "\n", "plt.rcParams['figure.figsize'] = (16, 9) # Size up figures a bit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To quickly ingest the GPX files, we write (or actually copy from the aforementioned blog post) a parsing function." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def load_run_data(gpx_path, filter=\"\"):\n", " gpx_files = glob.glob(os.path.join(gpx_path, filter + \"*.gpx\"))\n", " run_data = []\n", " for file_idx, gpx_file in enumerate(gpx_files): \n", " gpx = gpxpy.parse(open(gpx_file, 'r'))\n", " # Loop through tracks\n", " for track_idx, track in enumerate(gpx.tracks):\n", " track_name = track.name\n", " track_time = track.get_time_bounds().start_time\n", " track_length = track.length_3d()\n", " track_duration = track.get_duration()\n", " track_speed = track.get_moving_data().max_speed\n", " \n", " for seg_idx, segment in enumerate(track.segments):\n", " segment_length = segment.length_3d()\n", " for point_idx, point in enumerate(segment.points):\n", " run_data.append([file_idx, os.path.basename(gpx_file), track_idx, track_name, \n", " track_time, track_length, track_duration, track_speed, \n", " seg_idx, segment_length, point.time, point.latitude, \n", " point.longitude, point.elevation, segment.get_speed(point_idx)])\n", " return run_data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For easy handling, we load the GPX tracks in their subfolder to a [Pandas](https://pypi.python.org/pypi/pandas) `dataframe` and display the first few entries of the data frame." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
File_IndexFile_NameIndexNameTimeLengthDurationMax_SpeedSegment_IndexSegment_LengthPoint_TimePoint_LatitudePoint_LongitudePoint_ElevationPoint_Speed
000.gpx02016-12-09 13:57:012016-12-09 12:57:012865.8368364839.25116802865.8368362016-12-09 12:57:0146.9450077.429614536.564941NaN
100.gpx02016-12-09 13:57:012016-12-09 12:57:012865.8368364839.25116802865.8368362016-12-09 12:57:0246.9450557.429586540.6445319.099847
200.gpx02016-12-09 13:57:012016-12-09 12:57:012865.8368364839.25116802865.8368362016-12-09 12:57:0346.9451517.429544541.27368210.243475
300.gpx02016-12-09 13:57:012016-12-09 12:57:012865.8368364839.25116802865.8368362016-12-09 12:57:0446.9452237.429530536.5500498.525432
400.gpx02016-12-09 13:57:012016-12-09 12:57:012865.8368364839.25116802865.8368362016-12-09 12:57:0546.9452877.429538539.3811046.911977
\n", "
" ], "text/plain": [ " File_Index File_Name Index Name Time \\\n", "0 0 0.gpx 0 2016-12-09 13:57:01 2016-12-09 12:57:01 \n", "1 0 0.gpx 0 2016-12-09 13:57:01 2016-12-09 12:57:01 \n", "2 0 0.gpx 0 2016-12-09 13:57:01 2016-12-09 12:57:01 \n", "3 0 0.gpx 0 2016-12-09 13:57:01 2016-12-09 12:57:01 \n", "4 0 0.gpx 0 2016-12-09 13:57:01 2016-12-09 12:57:01 \n", "\n", " Length Duration Max_Speed Segment_Index Segment_Length \\\n", "0 2865.836836 483 9.251168 0 2865.836836 \n", "1 2865.836836 483 9.251168 0 2865.836836 \n", "2 2865.836836 483 9.251168 0 2865.836836 \n", "3 2865.836836 483 9.251168 0 2865.836836 \n", "4 2865.836836 483 9.251168 0 2865.836836 \n", "\n", " Point_Time Point_Latitude Point_Longitude Point_Elevation \\\n", "0 2016-12-09 12:57:01 46.945007 7.429614 536.564941 \n", "1 2016-12-09 12:57:02 46.945055 7.429586 540.644531 \n", "2 2016-12-09 12:57:03 46.945151 7.429544 541.273682 \n", "3 2016-12-09 12:57:04 46.945223 7.429530 536.550049 \n", "4 2016-12-09 12:57:05 46.945287 7.429538 539.381104 \n", "\n", " Point_Speed \n", "0 NaN \n", "1 9.099847 \n", "2 10.243475 \n", "3 8.525432 \n", "4 6.911977 " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = load_run_data(gpx_path='gpxtracks', filter=\"\")\n", "df = pandas.DataFrame(data, columns=['File_Index', 'File_Name', 'Index', 'Name',\n", " 'Time', 'Length', 'Duration', 'Max_Speed',\n", " 'Segment_Index', 'Segment_Length', 'Point_Time', 'Point_Latitude',\n", " 'Point_Longitude', 'Point_Elevation', 'Point_Speed'])\n", "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At last we plot the tracks on top of the *awesome* [Stamen watercolor maps](http://maps.stamen.com/watercolor/#12/46.9413/7.4310). " ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "for i in range(max(df['File_Index'])+1):\n", " plt.plot(df['Point_Longitude'][df['File_Index']==i],\n", " df['Point_Latitude'][df['File_Index']==i],\n", " color='black', linewidth=7)\n", "mplleaflet.display(tiles='stamen_wc')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Save as HTML page, so we can print the image big...\n", "for i in range(max(df['File_Index'])+1):\n", " plt.plot(df['Point_Longitude'][df['File_Index']==i],\n", " df['Point_Latitude'][df['File_Index']==i],\n", " color='black', linewidth=7)\n", "mplleaflet.save_html(tiles='stamen_wc', fileobj='2017.html')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.11" } }, "nbformat": 4, "nbformat_minor": 2 }