python4oceanographers

Turning ripples into waves

Plotting an static image over an interactive map

I just read an issue at the folium issue tracker that gave me an idea. How can I hack folium's HTML to quickly test new leaflet features? Well... The answer is simple, inline modification of the HTML ;-)

I want to test the raster plotting feature. First, just to check the image, lets georeference it using cartopy.

In [3]:
%matplotlib inline

import matplotlib.pyplot as plt

import cartopy.crs as ccrs
from cartopy.io import shapereader
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER


def make_map(projection=ccrs.PlateCarree()):
    fig, ax = plt.subplots(figsize=(9, 13),
                           subplot_kw=dict(projection=projection))
    gl = ax.gridlines(draw_labels=True)
    gl.xlabels_top = gl.ylabels_right = False
    gl.xformatter = LONGITUDE_FORMATTER
    gl.yformatter = LATITUDE_FORMATTER
    return fig, ax
In [4]:
min_lon = -(45 + (58 + 32.27/60) / 60)  # 45°58'32.27"W
max_lon = -(45 + (57 + 54.54/60) / 60)  # 45°57'54.54"W
min_lat = -(23 + (47 +  7.65/60) / 60)  # 23°47' 7.65"S
max_lat = -(23 + (46 + 42.25/60) / 60)  # 23°46'42.25"S

fig, ax = make_map()
image = plt.imread('data/itaguare_cropped.jpg')
img = ax.imshow(image, origin='upper', alpha=0.75, extent=[min_lon, max_lon, min_lat, max_lat])

That looks about right. Now lets create a folium map instance for this area.

In [5]:
import folium


def inline_map(m):
    from folium import Map
    from IPython.display import HTML, IFrame
    if isinstance(m, Map):
        m._build_map()
        srcdoc = m.HTML.replace('"', '"')
        embed = HTML('<iframe srcdoc="{srcdoc}" '
                     'style="width: 100%; height: 500px; '
                     'border: none"></iframe>'.format(srcdoc=srcdoc))
    elif isinstance(m, str):
        embed = IFrame(m, width=750, height=500)
    return embed


width, height = 650, 500
mapa = folium.Map(location=[-47.563861111111109, -91.940780555555563],
                  min_lon=min_lon, max_lon=max_lon, min_lat=min_lat, max_lat=max_lat,
                  tiles='Stamen Toner', width=width, height=height, zoom_start=15)

inline_map(mapa)
Out[5]:

According to leafletjs manual we need to perform an imageoverlay.

In [6]:
extra = """
var imageUrl = 'https://raw.githubusercontent.com/ocefpaf/python4oceanographers/master/content/downloads/notebooks/data/itaguare_cropped.jpg',
imageBounds = [[-23.785458333333334, -45.975630555555554], [-23.778402777777778, -45.96515]];
L.imageOverlay(imageUrl, imageBounds).addTo(map);
"""

I know that the last line in the HTML file, before the final </script>, is map.addLayer(clusteredmarkers);, so this is how we can modify it in place:

In [7]:
import fileinput


mapa.create_map(path="mapa.html")

add_lines = False
for line in fileinput.input('mapa.html', inplace=True):
    if 'map.addLayer(clusteredmarkers);' in line:
        add_lines = True
    else:
        if add_lines:
            print(extra)
        add_lines = False
    print line,
In [8]:
inline_map("mapa.html")
Out[8]:
In [9]:
HTML(html)
Out[9]:

This post was written as an IPython notebook. It is available for download or as a static html.

Creative Commons License
python4oceanographers by Filipe Fernandes is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Based on a work at https://ocefpaf.github.io/.

Comments