Matplotlib Basemap Tutorial: Plotting points on a simple map

Update:

This tutorial has been updated and moved to http://introtopython.org/visualization_earthquakes.html.

In this part of the tutorial, we will see how to plot points on a map.  We will start out by plotting some communities on Baranof Island in southeast Alaska. Here is our code so far, which creates a map of Baranof Island:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135,
    resolut   ion = 'h', area_thresh = 0.1,
    llcrnrlon=-136.25, llcrnrlat=56.0,
    urcrnrlon=-134.25, urcrnrlat=57.75)

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color = 'coral')
map.drawmapboundary()

plt.show()

and here is the map we have:

Baranof Island high resolution

A map of Baranof Island, at high resolution, showing details larger than 0.1 square kilometers.

It is a testament to the hard work of many other people that we can create a map like this in less than 15 lines of code!  Now let’s add some points to this map.  I live in Sitka, the largest community on Baranof Island, so let’s add a point showing Sitka’s location.  Add the following lines just before plt.show():

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135,
    resolut   ion = 'h', area_thresh = 0.1,
    llcrnrlon=-136.25, llcrnrlat=56.0,
    urcrnrlon=-134.25, urcrnrlat=57.75)

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color = 'coral')
map.drawmapboundary()

lon = -135.3318
lat = 57.0799
x,y = map(lon, lat)
map.plot(x, y, 'bo', markersize=24)

plt.show()

The only non-obvious line here is the ‘bo’ argument, which tells basemap to use a blue circle for the point.  There are quite a number of colors and symbols you can use.  For more choices, see the documentation for the matplotlib.pyplot.plot function.  The default marker size is 6, but that was too small on this particular map.  A markersize of 24 shows up nicely on this map:

Baranof Island map

Baranof Island, with a larger blue dot showing the location of Sitka.

Plotting a single point is nice, but we often want to plot a large set of points on a map.  There are two other communities on Baranof Island, so let’s show where those two communities are on this map.  We store the latitudes and longitudes of our points in two separate lists, map those to x and y coordinates, and plot those points on the map.  With more dots on the map, we also want to reduce the marker size a little:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135,
    resolut   ion = 'h', area_thresh = 0.1,
    llcrnrlon=-136.25, llcrnrlat=56.0,
    urcrnrlon=-134.25, urcrnrlat=57.75)

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color = 'coral')
map.drawmapboundary()

lons = [-135.3318, -134.8331, -134.6572]
lats = [57.0799, 57.0894, 56.2399]
x,y = map(lons, lats)
map.plot(x, y, 'bo', markersize=18)

plt.show()
Baranof Island's communities

The three communities on Baranof Island.

Now let’s label these three points.  We make a list of our labels, and loop through that list.  We need to include the x and y values for each point in this loop, so Basemap can figure out where to place each label.

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135,
    resolut   ion = 'h', area_thresh = 0.1,
    llcrnrlon=-136.25, llcrnrlat=56.0,
    urcrnrlon=-134.25, urcrnrlat=57.75)

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color = 'coral')
map.drawmapboundary()

lons = [-135.3318, -134.8331, -134.6572]
lats = [57.0799, 57.0894, 56.2399]
x,y = map(lons, lats)
map.plot(x, y, 'bo', markersize=18)

labels = ['Sitka', 'Baranof Warm Springs', 'Port Alexander']
for label, xpt, ypt in zip(labels, x, y):
    plt.text(xpt, ypt, label)

plt.show()

Our towns are now labeled, but the labels start right on top of our points:

Baranof Island, with the communities labeled.

Baranof Island, with the communities labeled.

We can add offsets to these points, so they are not right on top of the points.  Let’s move all of the labels a little up and to the right.  (If you are curious, these offsets are in “map projection coordinates“, which are measured in meters.  This means our code actually places the labels 10 km to the east and 5 km to the north of the actual townsites.)

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135,
    resolut   ion = 'h', area_thresh = 0.1,
    llcrnrlon=-136.25, llcrnrlat=56.0,
    urcrnrlon=-134.25, urcrnrlat=57.75)

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color = 'coral')
map.drawmapboundary()

lons = [-135.3318, -134.8331, -134.6572]
lats = [57.0799, 57.0894, 56.2399]
x,y = map(lons, lats)
map.plot(x, y, 'bo', markersize=18)

labels = ['Sitka', 'Baranof Warm Springs', 'Port Alexander']
for label, xpt, ypt in zip(labels, x, y):
    plt.text(xpt+10000, ypt+5000, label)

plt.show()
The communities on Barnaof Island, with the labels placed a little more legibly.

The communities on Barnaof Island, with the labels placed a little more legibly.

This is better, but on a map of this scale the same offset does not work well for all points.  We could plot each label individually, but it is easier to make two lists to store our offsets:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

map = Basemap(projection='merc', lat_0 = 57, lon_0 = -135,
    resolut   ion = 'h', area_thresh = 0.1,
    llcrnrlon=-136.25, llcrnrlat=56.0,
    urcrnrlon=-134.25, urcrnrlat=57.75)

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color = 'coral')
map.drawmapboundary()

lons = [-135.3318, -134.8331, -134.6572]
lats = [57.0799, 57.0894, 56.2399]
x,y = map(lons, lats)
map.plot(x, y, 'bo', markersize=18)

labels = ['Sitka', 'Baranof\n  Warm Springs', 'Port Alexander']
x_offsets = [10000, -30000, -25000]
y_offsets = [5000, -25000, -25000]

for label, xpt, ypt, x_offset, y_offset in zip(labels, x, y, x_offsets, y_offsets):
    plt.text(xpt+x_offset, ypt+y_offset, label)

plt.show()
Baranof Island, with each community's label placed more appropriately on the map.

Baranof Island, with each community’s label placed more appropriately on the map.

There is no easy way to keep “Baranof Warm Springs” from crossing a border, but the use of newlines within a label makes it reasonably legible. Now that we know how to add points to a map, we will move on to larger data sets.

Next:  Plotting global earthquake activity

Back to Tutorial contents

Advertisements

About ehmatthes

Teacher, hacker, new dad, outdoor guy
This entry was posted in programming and tagged , , , , . Bookmark the permalink.

5 Responses to Matplotlib Basemap Tutorial: Plotting points on a simple map

  1. Thanks for the tutorial, it was very helpful in building my map today!

  2. Thank You, your tutorial very helpul.

  3. moeabdol says:

    Great tutorial. Thank you so much.

  4. Anonymous says:

    You can improve your source code by not overriding builtins. In this case map keyword was overriden and this fragment become weird for me:
    lon = -135.3318
    lat = 57.0799
    x,y = map(lon, lat)
    Because I assumed traditional meaning of map.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s