%matplotlib inline
import contextily
import geopandas
Using the New York boroughs as example
df = geopandas.read_file(geopandas.datasets.get_path('nybb'))
df = df.to_crs(epsg=3857)
Plotting a first time takes a bit more than a second:
%%time
ax = df.plot()
contextily.add_basemap(ax)
CPU times: user 472 ms, sys: 268 ms, total: 740 ms Wall time: 1.08 s
Doing it a second time (with a patched version of contextily to cache the web tiles, see below for the implementation), it takes 1/4 th of a second:
%%time
ax = df.plot()
contextily.add_basemap(ax)
CPU times: user 316 ms, sys: 192 ms, total: 508 ms Wall time: 259 ms
ax = df.plot()
xmin, xmax, ymin, ymax = ax.axis()
left, right, bottom, top = xmin, xmax, ymin, ymax
# Zoom
min_ll = contextily.plotting._sm2ll(left, bottom)
max_ll = contextily.plotting._sm2ll(right, top)
zoom = contextily.plotting._calculate_zoom(*min_ll, *max_ll)
%%timeit
image, extent = contextily.plotting.bounds2img(left, bottom, right, top,
zoom=zoom, url=contextily.sources.ST_TERRAIN, ll=False)
1.22 s ± 56.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%load_ext snakeviz
%%snakeviz
image, extent = contextily.plotting.bounds2img(left, bottom, right, top,
zoom=zoom, url=contextily.sources.ST_TERRAIN, ll=False)
*** Profile stats marshalled to file '/tmp/tmpyq1rty49'.
requests-cache
¶import requests_cache
import requests
requests_cache.install_cache('demo_cache')
import mercantile as mt
from contextily.tile import _sm2ll, _calculate_zoom, merge_tiles
from PIL import Image
import numpy as np
from six.moves.urllib.request import urlopen
import six
def bounds2img(w, s, e, n, zoom='auto', url=contextily.sources.ST_TERRAIN, ll=False):
if not ll:
# Convert w, s, e, n into lon/lat
w, s = _sm2ll(w, s)
e, n = _sm2ll(e, n)
if zoom == 'auto':
zoom = _calculate_zoom(w, e, s, n)
tiles = []
for t in mt.tiles(w, s, e, n, [zoom]):
x, y, z = t.x, t.y, t.z
tile_url = url.replace('tileX', str(x)).replace('tileY', str(y)).replace('tileZ', str(z))
#---
r = requests.get(tile_url)
imgr = Image.open(six.BytesIO(r.content))
r.close()
#fh = urlopen(tile_url)
#im_data = six.BytesIO(fh.read())
#fh.close()
#imgr = Image.open(im_data)
imgr = imgr.convert('RGB')
#---
img = np.array(imgr)
wt, st, et, nt = mt.bounds(t)
xr = np.linspace(wt, et, img.shape[0])
yr = np.linspace(st, nt, img.shape[1])
tiles.append([img, xr, yr, 'lower'])
merged, extent = merge_tiles(tiles)[:2]
# lon/lat extent --> Spheric Mercator
minX, maxX, minY, maxY = extent
w, s = mt.xy(minX, minY)
e, n = mt.xy(maxX, maxY)
extent = w, e, s, n
return merged[::-1], extent
%%timeit
image, extent = bounds2img(left, bottom, right, top,
zoom=zoom, url=contextily.sources.ST_TERRAIN, ll=False)
94.2 ms ± 14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
import joblib
mem = joblib.Memory(cachedir='/tmp', verbose=1)
import requests
@mem.cache
def _get(tile_url):
r = requests.get(tile_url)
content = r.content
r.close()
return content
import mercantile as mt
from contextily.tile import _sm2ll, _calculate_zoom, merge_tiles
from PIL import Image
import numpy as np
from six.moves.urllib.request import urlopen
import six
def bounds2img(w, s, e, n, zoom='auto', url=contextily.sources.ST_TERRAIN, ll=False):
if not ll:
# Convert w, s, e, n into lon/lat
w, s = _sm2ll(w, s)
e, n = _sm2ll(e, n)
if zoom == 'auto':
zoom = _calculate_zoom(w, e, s, n)
tiles = []
for t in mt.tiles(w, s, e, n, [zoom]):
x, y, z = t.x, t.y, t.z
tile_url = url.replace('tileX', str(x)).replace('tileY', str(y)).replace('tileZ', str(z))
#---
content = _get(tile_url)
imgr = Image.open(six.BytesIO(content))
#fh = urlopen(tile_url)
#im_data = six.BytesIO(fh.read())
#fh.close()
#imgr = Image.open(im_data)
imgr = imgr.convert('RGB')
#---
img = np.array(imgr)
wt, st, et, nt = mt.bounds(t)
xr = np.linspace(wt, et, img.shape[0])
yr = np.linspace(st, nt, img.shape[1])
tiles.append([img, xr, yr, 'lower'])
merged, extent = merge_tiles(tiles)[:2]
# lon/lat extent --> Spheric Mercator
minX, maxX, minY, maxY = extent
w, s = mt.xy(minX, minY)
e, n = mt.xy(maxX, maxY)
extent = w, e, s, n
return merged[::-1], extent
%%timeit
image, extent = bounds2img(left, bottom, right, top,
zoom=zoom, url=contextily.sources.ST_TERRAIN, ll=False)
________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/601/768.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/601/769.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/601/770.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/601/771.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/602/768.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/602/769.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/602/770.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/602/771.png') ______________________________________________________________get - 0.0s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/603/768.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/603/769.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/603/770.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/603/771.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/604/768.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/604/769.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/604/770.png') ______________________________________________________________get - 0.1s, 0.0min ________________________________________________________________________________ [Memory] Calling __main__--home-joris-scipy-__ipython-input__._get... _get('http://tile.stamen.com/terrain/11/604/771.png') ______________________________________________________________get - 0.1s, 0.0min 68.6 ms ± 7.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)