How to use OpenStreetMap background on Matplotlib Basemap

22,749

Solution 1

I would suggest not to try to make something work, which is not made (yet) to work together. There is a simple way to achieve what you want with Mplleaflet. https://github.com/jwass/mplleaflet The library allows you to visualize geographic data on a beautiful interactive openstreetmap. Map projection of data in long lat format is automatically performed.

Installation in windows and ubuntu is easy:

pip install mplleaflet

You can start with the provided examples and go from there.

Solution 2

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...

Solution 3

You can download the necessary tiles yourself from one of the tile servers. The OSM wiki explains the technical details behind slippy map tilenames and also includes examples for various programming and scripting languages.

Please also read about the tile usage policy and keep in mind that different tile serves may have different policies.

Solution 4

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

Share:
22,749
iury simoes-sousa
Author by

iury simoes-sousa

Updated on November 29, 2021

Comments

  • iury simoes-sousa
    iury simoes-sousa over 2 years

    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.