Below is a simple introduction the the Python module Basemap. I only scratch the surface of Basemap's potential and the examples below serve to introduce students to ploting in Python (and reminders for myself!). While going through the introduction, please refer to the Basemap documenation. In the future I plan to add examples of how to collect data from EOL and GBIF using their APIs and generate plots in Basemap.
In [2]:
%matplotlib inline
import mpl_toolkits
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from matplotlib.patches import PathPatch
import numpy as np
In [9]:
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='robin',lon_0=0,resolution='i',area_thresh=10000)
map.drawmapboundary()
map.drawcoastlines(linewidth=0.5, color='black')
map.drawstates(linewidth=1, color='black')
plt.show()
The first two lines of code are to set up the figure using Matplotlib. More detail on this can be found here. Next, we make a variable called map
, which will be our map projection and the boundaries. The list of map projections and examples are located here. There are tons of parameters that can be used when making a variable with the Basemap class that can be found here. I will explore a few of these below with a specific example of South American cicadas. For now, lets explore some simple commands that add lines and colors to our map.
In [20]:
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='robin',lon_0=0,resolution='i',area_thresh=10000)
map.drawmapboundary(fill_color='#000000')
map.drawcoastlines(linewidth=0.75, color='#000000')
map.drawstates(linewidth=0.25, linestyle='-', color='#FFFFFF')
map.fillcontinents(color='#e41a1c',lake_color='#377eb8')
plt.show()
The continent colors, ocean colors, lake colors, line styles (e.g., solid or dashed), and line thickness can all be modified after a variable is created using the Basemap class (i.e., map = Basemap()
). In the example above, I first call map.drawmapboundary
. This colors the ocean and you can use any hex color you want or change the line style as I do below. Next I call map.drawcoastlines(linewidth=0.75, color='#000000')
, which draws the coastlines for the map. Again, it can be any combination of color, line size, and line style just by changing the parameter values. Next, I outline in the state boundaries with dashed white lines with a line thickness of 0.25 using map.drawstates(linewidth=0.25, linestyle='-', color='#FFFFFF')
. Note that only the US, South American and Australian states are outlined. If you want to color in specific states, you need to include a shape file. I will go over this in an example below. The last call to the map variable, map.fillcontinents(color='#e41a1c',lake_color='#377eb8')
, colors the continents red and the large lakes within the continents blue.
In [23]:
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='robin',lon_0=0,resolution='i',area_thresh=10000)
map.drawmapboundary(fill_color='#000000')
map.drawcoastlines(linewidth=0.75, color='#000000')
map.drawstates(linewidth=0.25, linestyle='-', color='#FFFFFF')
map.fillcontinents(color='#e41a1c',lake_color='#377eb8')
#Read shape file to color individual countries
shape_file = map.readshapefile('/Users/cowen/Documents/RV217/ne_10m_admin_0_countries_lakes/ne_10m_admin_0_countries_lakes', name='states', drawbounds=False)#drawbounds=True, color='black')
chile_patches = []
argentina_patches = []
for info, shape in zip(map.states_info, map.states):
if info['NAME'] == 'Chile':
chile_patches.append(Polygon(np.array(shape), True))
if info['NAME'] == 'Argentina':
argentina_patches.append(Polygon(np.array(shape), True))
ax.add_collection(PatchCollection(chile_patches, facecolor= '#4daf4a', edgecolor='#4daf4a', linewidths=0.5, zorder=2))
ax.add_collection(PatchCollection(argentina_patches, facecolor= '#ffff33', edgecolor='#ffff33', linewidths=0.5, zorder=2))
plt.show()
In order to color individual countries or territories in Basemap, you need to read in a shapfile. A shape file contains all of the boundary coordinates, which are used to color the polygons. There are lots of shapefiles on the internet and I usually use those located at Natural Earth. Once the shape file is read into Basemap, you have to search for the country name and add all of the coordinates to an empty list. In the example above, I created an empty lists for Chile and Argentina and add all coordinates in the shapefile to these empty lists. Once those coordinates are added to their respective lists, I plot them using add_collections
. It is here I can change the color, edge color, line width, etc.
In [28]:
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='robin',lon_0=0,resolution='i',area_thresh=10000)
map.drawmapboundary()
map.drawcoastlines(linewidth=0.5, color='#000000')
plt.show()
In [4]:
#Species coordinates
sp1_lon = [-70.70, -71.79, -71.07]#Species 1 Longitudes
sp1_lat = [-32.46, -35.62, -31.79]#Species 1 Latitudes
sp2_lon = [-70.71475, -70.49391667, -70.51766667, -71.79315, -70.43655, -70.54886667, -70.63473333]#Species 2 Longitudes
sp2_lat = [-32.58825, -33.40066667, -33.49263889, -35.62571667, -34.95656667, -34.86373333, -34.19561667]#Species 2 Latitudes
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='robin',lon_0=0,resolution='i',area_thresh=10000)
map.drawmapboundary()
map.drawcoastlines(linewidth=0.5, color='#000000')
#Add the occurrences to the map
x1,y1 = map(sp1_lon, sp1_lat)
map.plot(x1, y1, 'bo', markersize=12)
x2,y2 = map(sp2_lon, sp2_lat)
map.plot(x2, y2, 'ro', markersize=12)
plt.show()
In order to plot species occurences, the latitudes and longitudes need to be in list. Once they are in lists, the are made into tuples using the map
command and then the points are plotted using the plot
command. The parameters of the plot command can change the color, size, type of marker (e.g., circle, square, triangle, etc.), and marker edge color.
These points are in South American, but they are all on top of one another and we can not see exactly where they are; therefore, lets zoom in a bit by modifying the Basmap class command
In [41]:
#Species coordinates
sp1_lon = [-70.70, -71.79, -71.07]
sp1_lat = [-32.46, -35.62, -31.79]
sp2_lon = [-70.71475, -70.49391667, -70.51766667, -71.79315, -70.43655, -70.54886667, -70.63473333]
sp2_lat = [-32.58825, -33.40066667, -33.49263889, -35.62571667, -34.95656667, -34.86373333, -34.19561667]
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='merc',llcrnrlat=-56.0,urcrnrlat=14.50,llcrnrlon=-88.0,urcrnrlon=-32.0,lat_ts=-16.75,resolution='i',area_thresh=10000)
map.drawmapboundary()
map.drawcoastlines(linewidth=0.5, color='#000000')
#Add the occurrences to the map
x1,y1 = map(sp1_lon, sp1_lat)
map.plot(x1, y1, 'bo', markersize=12)
x2,y2 = map(sp2_lon, sp2_lat)
map.plot(x2, y2, 'ro', markersize=12)
plt.show()
In the above code, I changed the projection (preference, but not necessary) and altered the Basemap variable so that it focuses only on South America. It is much better now, but the points are still quite large and we do not have a good idea of where these are located. Lets see if we can improve this.
In [8]:
#Species coordinates
sp1_lon = [-70.70, -71.79, -71.07]
sp1_lat = [-32.46, -35.62, -31.79]
sp2_lon = [-70.71475, -70.49391667, -70.51766667, -71.79315, -70.43655, -70.54886667, -70.63473333]
sp2_lat = [-32.58825, -33.40066667, -33.49263889, -35.62571667, -34.95656667, -34.86373333, -34.19561667]
fig = plt.figure(figsize=(12,9))
ax = fig.add_subplot(111)
map = Basemap(projection='merc',llcrnrlat=-56.0,urcrnrlat=14.50,llcrnrlon=-88.0,urcrnrlon=-32.0,lat_ts=-16.75,resolution='i',area_thresh=10000)
map.drawmapboundary()
map.drawcoastlines(linewidth=0.5, color='#000000')
map.drawcountries()
#Add the occurrences to the map
x1,y1 = map(sp1_lon, sp1_lat)
map.plot(x1, y1, 'bo', markersize=5)
x2,y2 = map(sp2_lon, sp2_lat)
map.plot(x2, y2, 'ro', markersize=5)
plt.show()
In [6]:
import mpl_toolkits
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from matplotlib.patches import PathPatch
import numpy as np
%matplotlib inline
#Species coordinates
sp1_lon = [-70.70, -71.79, -71.07]
sp1_lat = [-32.46, -35.62, -31.79]
sp2_lon = [-70.71475, -70.49391667, -70.51766667, -71.79315, -70.43655, -70.54886667, -70.63473333]
sp2_lat = [-32.58825, -33.40066667, -33.49263889, -35.62571667, -34.95656667, -34.86373333, -34.19561667]
fig = plt.figure(figsize=(12,12))
ax = fig.add_subplot(111)
map = Basemap(projection='merc',llcrnrlat=-40.5,urcrnrlat=-25.5,llcrnrlon=-78.0,urcrnrlon=-65.0,lat_ts=-33.5,resolution=None,area_thresh=0.1)
map.bluemarble(scale=4.0)
#Add the occurrences to the map
x1,y1 = map(sp1_lon, sp1_lat)
ax.plot(x1, y1, 'bo', markersize=7)
x2,y2 = map(sp2_lon, sp2_lat)
ax.plot(x2, y2, 'ro', markersize=7)
plt.show()