Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use OpenStreetMap background on Matplotlib Basemap

This should be simple, but when I look for it I just find web packages. I need something better than as oriented on This Blog. Maybe using .oms file or shapefiles. Some way to give bbox and get the OpenStreetMap background on Basemap map.

I found some questions like this on Stack, but the answers directs to, or download the .png file on OpenStreetMap website, or to use some web package.

like image 653
iury simoes-sousa Avatar asked May 05 '15 12:05

iury simoes-sousa


People also ask

What is Contextily?

contextily is a small Python 3 (3.7 and above) package to retrieve tile maps from the internet. It can add those tiles as basemap to matplotlib figures or write tile maps to disk into geospatial raster files. Bounding boxes can be passed in both WGS84 ( EPSG:4326 ) and Spheric Mercator ( EPSG:3857 ).

What is matplotlib basemap?

The matplotlib basemap toolkit is a library for plotting 2D data on maps in Python. It is similar in functionality to the matlab mapping toolbox, the IDL mapping facilities, GrADS, or the Generic Mapping Tools. PyNGL and CDAT are other libraries that provide similar capabilities in Python.


2 Answers

For those who are using Cartopy, this is relatively simple:

import matplotlib.pyplot as pl
import numpy as np

import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt

request = cimgt.OSM()

# Bounds: (lon_min, lon_max, lat_min, lat_max):
extent = [1, 13, 45, 53]

ax = pl.axes(projection=request.crs)
ax.set_extent(extent)
ax.add_image(request, 5)    # 5 = zoom level

# Just some random points/lines:
pl.scatter(4.92, 51.97, transform=ccrs.PlateCarree())
pl.plot([4.92, 9], [51.97, 47], transform=ccrs.PlateCarree())

This produces:

enter image description here

like image 158
Bart Avatar answered Oct 20 '22 11:10

Bart


There are many libraries today that can do this for you - smopy, folium and tilemapbase are three examples from my recent use.

Each of these tools fetch map tiles from the one of several servers that host OSM or other (Stamen, Carto, etc) map tiles and then allows you to display and plot on them using matplotlib. Tilemapbase also caches the tiles locally so that they are not fetched again the next time.

But there does not seem to be a readily available tool yet, based on my recent experience, to use offline tilesets (such as a compressed .mbtiles file) as background for matplotlib plotting.

This link contains a survey of the above tools and more - https://github.com/ispmarin/maps

EDIT

I had mentioned in my previous answer that Tilemapbase did not work for some geographical locations in the world, and hence explicitly recommended not to use it. But it turns out I was wrong, and I apologize for that. It actually works great! The problem in my case was embarrassingly simple - I had reversed the order or lat and lon while fetching tiles, and hence it always fetched blank tiles for certain geographical locations, leading me to assume that it did not work for those locations.

I had raised the issue in github and it was immediately resolved by the developers. See it here - https://github.com/MatthewDaws/TileMapBase/issues/7

Note the responses:

Coordinates are to be provided in order (1) longitude, (2) latitude. If you copied them from Google Maps, they will be in lat/lon order and you have to flip them. So your map image is not empty, it's just a location in the ocean north of Norway.

And from the developer himself:

Yes, when I wrote the code, it seemed that there wasn't a universal standard for ordering. So I chose the one which is different to Google Maps. The method name from_lonlat should give a hint as to the correct ordering...

like image 39
Shiva Avatar answered Oct 20 '22 10:10

Shiva