mpl_toolkits
namespace.
Admittedly, Basemap feels a bit clunky to use, and often even simple visualizations take much longer to render than you might hope.
More modern solutions such as leaflet or the Google Maps API may be a better choice for more intensive map visualizations.
Still, Basemap is a useful tool for Python users to have in their virtual toolbelts.
In this section, we'll show several examples of the type of map visualization that is possible with this toolkit.$ conda install basemap
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
PIL
package in Python 2, or the pillow
package in Python 3):plt.figure(figsize=(8, 8))
m = Basemap(projection='ortho', resolution=None, lat_0=50, lon_0=-100)
m.bluemarble(scale=0.5);
Basemap
will be discussed momentarily.fig = plt.figure(figsize=(8, 8))
m = Basemap(projection='lcc', resolution=None,
width=8E6, height=8E6,
lat_0=45, lon_0=-100,)
m.etopo(scale=0.5, alpha=0.5)
# Map (long, lat) to (x, y) for plotting
x, y = m(-122.3, 47.6)
plt.plot(x, y, 'ok', markersize=5)
plt.text(x, y, ' Seattle', fontsize=12);
from itertools import chain
def draw_map(m, scale=0.2):
# draw a shaded-relief image
m.shadedrelief(scale=scale)
# lats and longs are returned as a dictionary
lats = m.drawparallels(np.linspace(-90, 90, 13))
lons = m.drawmeridians(np.linspace(-180, 180, 13))
# keys contain the plt.Line2D instances
lat_lines = chain(*(tup[1][0] for tup in lats.items()))
lon_lines = chain(*(tup[1][0] for tup in lons.items()))
all_lines = chain(lat_lines, lon_lines)
# cycle through these lines and set the desired style
for line in all_lines:
line.set(linestyle='-', alpha=0.3, color='w')
projection='merc'
) and the cylindrical equal area (projection='cea'
) projections.fig = plt.figure(figsize=(8, 6), edgecolor='w')
m = Basemap(projection='cyl', resolution=None,
llcrnrlat=-90, urcrnrlat=90,
llcrnrlon=-180, urcrnrlon=180, )
draw_map(m)
lat
) and longitude (lon
) of the lower-left corner (llcrnr
) and upper-right corner (urcrnr
) for the desired map, in units of degrees.projection='moll'
) is one common example of this, in which all meridians are elliptical arcs.
It is constructed so as to preserve area across the map: though there are distortions near the poles, the area of small patches reflects the true area.
Other pseudo-cylindrical projections are the sinusoidal (projection='sinu'
) and Robinson (projection='robin'
) projections.fig = plt.figure(figsize=(8, 6), edgecolor='w')
m = Basemap(projection='moll', resolution=None,
lat_0=0, lon_0=0)
draw_map(m)
lat_0
) and longitude (lon_0
) for the desired map.projection='ortho'
), which shows one side of the globe as seen from a viewer at a very long distance. As such, it can show only half the globe at a time.
Other perspective-based projections include the gnomonic projection (projection='gnom'
) and stereographic projection (projection='stere'
).
These are often the most useful for showing small portions of the map.fig = plt.figure(figsize=(8, 8))
m = Basemap(projection='ortho', resolution=None,
lat_0=50, lon_0=0)
draw_map(m);
projection='lcc'
), which we saw earlier in the map of North America.
It projects the map onto a cone arranged in such a way that two standard parallels (specified in Basemap by lat_1
and lat_2
) have well-represented distances, with scale decreasing between them and increasing outside of them.
Other useful conic projections are the equidistant conic projection (projection='eqdc'
) and the Albers equal-area projection (projection='aea'
).
Conic projections, like perspective projections, tend to be good choices for representing small to medium patches of the globe.fig = plt.figure(figsize=(8, 8))
m = Basemap(projection='lcc', resolution=None,
lon_0=0, lat_0=50, lat_1=45, lat_2=55,
width=1.6E7, height=1.2E7)
draw_map(m)
bluemarble()
and shadedrelief()
methods for projecting global images on the map, as well as the drawparallels()
and drawmeridians()
methods for drawing lines of constant latitude and longitude.
The Basemap package contains a range of useful functions for drawing borders of physical features like continents, oceans, lakes, and rivers, as well as political boundaries such as countries and US states and counties.
The following are some of the available drawing functions that you may wish to explore using IPython's help features:drawcoastlines()
: Draw continental coast linesdrawlsmask()
: Draw a mask between the land and sea, for use with projecting images on one or the otherdrawmapboundary()
: Draw the map boundary, including the fill color for oceans.drawrivers()
: Draw rivers on the mapfillcontinents()
: Fill the continents with a given color; optionally fill lakes with another colordrawcountries()
: Draw country boundariesdrawstates()
: Draw US state boundariesdrawcounties()
: Draw US county boundariesdrawgreatcircle()
: Draw a great circle between two pointsdrawparallels()
: Draw lines of constant latitudedrawmeridians()
: Draw lines of constant longitudedrawmapscale()
: Draw a linear scale on the mapbluemarble()
: Project NASA's blue marble image onto the mapshadedrelief()
: Project a shaded relief image onto the mapetopo()
: Draw an etopo relief image onto the mapwarpimage()
: Project a user-provided image onto the mapresolution
argument of the Basemap
class sets the level of detail in boundaries, either 'c'
(crude), 'l'
(low), 'i'
(intermediate), 'h'
(high), 'f'
(full), or None
if no boundaries will be used.
This choice is important: setting high-resolution boundaries on a global map, for example, can be very slow.fig, ax = plt.subplots(1, 2, figsize=(12, 8))
for i, res in enumerate(['l', 'h']):
m = Basemap(projection='gnom', lat_0=57.3, lon_0=-6.2,
width=90000, height=120000, resolution=res, ax=ax[i])
m.fillcontinents(color="#FFDDCC", lake_color='#DDEEFF')
m.drawmapboundary(fill_color="#DDEEFF")
m.drawcoastlines()
ax[i].set_title("resolution='{0}'".format(res));
plt
function works on the map; you can use the Basemap
instance to project latitude and longitude coordinates to (x, y)
coordinates for plotting with plt
, as we saw earlier in the Seattle example.Basemap
instance.
These work very similarly to their standard Matplotlib counterparts, but have an additional Boolean argument latlon
, which if set to True
allows you to pass raw latitudes and longitudes to the method, rather than projected (x, y)
coordinates.contour()
/contourf()
: Draw contour lines or filled contoursimshow()
: Draw an imagepcolor()
/pcolormesh()
: Draw a pseudocolor plot for irregular/regular meshesplot()
: Draw lines and/or markers.scatter()
: Draw points with markers.quiver()
: Draw vectors.barbs()
: Draw wind barbs.drawgreatcircle()
: Draw a great circle.import pandas as pd
cities = pd.read_csv('data/california_cities.csv')
# Extract the data we're interested in
lat = cities['latd'].values
lon = cities['longd'].values
population = cities['population_total'].values
area = cities['area_total_km2'].values
# 1. Draw the map background
fig = plt.figure(figsize=(8, 8))
m = Basemap(projection='lcc', resolution='h',
lat_0=37.5, lon_0=-119,
width=1E6, height=1.2E6)
m.shadedrelief()
m.drawcoastlines(color='gray')
m.drawcountries(color='gray')
m.drawstates(color='gray')
# 2. scatter city data, with color reflecting population
# and size reflecting area
m.scatter(lon, lat, latlon=True,
c=np.log10(population), s=area,
cmap='Reds', alpha=0.5)
# 3. create colorbar and legend
plt.colorbar(label=r'$\log_{10}({\rm population})$')
plt.clim(3, 7)
# make legend with dummy points
for a in [100, 300, 500]:
plt.scatter([], [], c='k', alpha=0.5, s=a,
label=str(a) + ' km$^2$')
plt.legend(scatterpoints=1, frameon=False,
labelspacing=1, loc='lower left');
# !curl -O http://data.giss.nasa.gov/pub/gistemp/gistemp250.nc.gz
# !gunzip gistemp250.nc.gz
netCDF4
library.
You can install this library as shown here$ conda install netcdf4
from netCDF4 import Dataset
data = Dataset('gistemp250.nc')
from netCDF4 import date2index
from datetime import datetime
timeindex = date2index(datetime(2014, 1, 15),
data.variables['time'])
lat = data.variables['lat'][:]
lon = data.variables['lon'][:]
lon, lat = np.meshgrid(lon, lat)
temp_anomaly = data.variables['tempanomaly'][timeindex]
pcolormesh()
method to draw a color mesh of the data.
We'll look at North America, and use a shaded relief map in the background.
Note that for this data we specifically chose a divergent colormap, which has a neutral color at zero and two contrasting colors at negative and positive values.
We'll also lightly draw the coastlines over the colors for reference:fig = plt.figure(figsize=(10, 8))
m = Basemap(projection='lcc', resolution='c',
width=8E6, height=8E6,
lat_0=45, lon_0=-100,)
m.shadedrelief(scale=0.5)
m.pcolormesh(lon, lat, temp_anomaly,
latlon=True, cmap='RdBu_r')
plt.clim(-8, 8)
m.drawcoastlines(color='lightgray')
plt.title('January 2014 Temperature Anomaly')
plt.colorbar(label='temperature anomaly (°C)');