In [1]:
import os
import folium

print(folium.__version__)
0.5.0+27.g2d457b0.dirty
In [2]:
import gpxpy

fname = os.path.join('data', '2014_08_05_farol.gpx')
gpx = gpxpy.parse(open(fname))

print('{} track(s)'.format(len(gpx.tracks)))
track = gpx.tracks[0]

print('{} segment(s)'.format(len(track.segments)))
segment = track.segments[0]

print('{} point(s)'.format(len(segment.points)))
1 track(s)
1 segment(s)
1027 point(s)
In [3]:
data = []
segment_length = segment.length_3d()
for point_idx, point in enumerate(segment.points):
    data.append(
        [
            point.longitude,
            point.latitude,
            point.elevation,
            point.time,
            segment.get_speed(point_idx)
        ]
    )
In [4]:
from pandas import DataFrame

columns = ['Longitude', 'Latitude', 'Altitude', 'Time', 'Speed']
df = DataFrame(data, columns=columns)
df.head()
Out[4]:
Longitude Latitude Altitude Time Speed
0 -38.502595 -13.005390 10.9 2014-08-05 17:52:49 NaN
1 -38.502605 -13.005415 11.8 2014-08-05 17:52:49 2.138361
2 -38.502575 -13.005507 11.7 2014-08-05 17:52:54 2.792437
3 -38.502545 -13.005595 11.6 2014-08-05 17:52:57 3.388271
4 -38.502515 -13.005680 11.4 2014-08-05 17:53:00 3.107460
In [5]:
import numpy as np
from geographiclib.geodesic import Geodesic

angles = [90]
for i in range(len(df) - 1):
    info = Geodesic.WGS84.Inverse(
        df.iloc[i, 1], df.iloc[i, 0],
        df.iloc[i + 1, 1], df.iloc[i + 1, 0]
    )
    angles.append(info['azi2'])

# Change from CW-from-North to CCW-from-East.
angles = np.deg2rad(450 - np.array(angles))

# Normalize the speed to use as the length of the arrows.
r = df['Speed'] / df['Speed'].max()
df['u'] = r * np.cos(angles)
df['v'] = r * np.sin(angles)
In [6]:
import mplleaflet
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
df = df.dropna()

# This style was lost below.
ax.plot(
    df['Longitude'],
    df['Latitude'],
    color='darkorange',
    linewidth=5,
    alpha=0.5
)

# This is preserved in the SVG icon.
sub = 10
kw = {'color': 'deepskyblue', 'alpha': 0.8, 'scale': 10}
ax.quiver(df['Longitude'][::sub],
          df['Latitude'][::sub],
          df['u'][::sub],
          df['v'][::sub], **kw)

gj = mplleaflet.fig_to_geojson(fig=fig)
In [7]:
import folium

lon, lat = -38.51386097, -13.00868051
zoom_start = 14

m = folium.Map(
    location=[lat, lon],
    tiles='Cartodb Positron',
    zoom_start=zoom_start
)

# The first geometry is a lineString.
line_string = gj['features'][0]
gjson = folium.features.GeoJson(line_string)

m.add_child(gjson)
m.save(os.path.join('results', 'Folium_and_mplleaflet_0.html'))

m
Out[7]:
In [8]:
line_string['properties']
Out[8]:
{'color': '#FF8C00',
 'highlight': {},
 'opacity': 0.5,
 'style': {},
 'weight': 5.0}
In [9]:
from IPython.display import HTML

msg = '<font color="{}">This should be darkorange!</font>'.format
HTML(msg(line_string['properties']['color']))
Out[9]:
This should be darkorange!
In [10]:
m = folium.Map(
    location=[lat, lon],
    tiles='Cartodb Positron',
    zoom_start=zoom_start
)

icon_size = (14, 14)

for feature in gj['features']:
    if feature['geometry']['type'] == 'LineString':
        continue
    elif feature['geometry']['type'] == 'Point':
        lon, lat = feature['geometry']['coordinates']
        html = feature['properties']['html']

        icon_anchor = (feature['properties']['anchor_x'],
                       feature['properties']['anchor_y'])

        icon = folium.features.DivIcon(html=html,
                                       icon_size=(14, 14),
                                       icon_anchor=icon_anchor)
        marker = folium.map.Marker([lat, lon], icon=icon)
        m.add_child(marker)
    else:
        msg = 'Unexpected geometry {}'.format
        raise ValueError(msg(feature['geometry']))

m.save(os.path.join('results', 'Folium_and_mplleaflet_1.html'))

m
Out[10]: