Plotting data on a map using Basemap

Probably the best geospatial visualizations are done by overlaying the data over the map. Whether the whole globe, a continent, a state, or even the sky, it is one of the easiest ways for a viewer to comprehend the relationship between the data and the geography it has displayed.

In this recipe, you will learn how to project data on a map using matplotlib's Basemap toolkit.

Getting ready

As we are already familiar with matplotlib as our plotting engine, we can extend that to matplotlib's capability to use other toolkits, one such example being the Basemap mapping toolkit.

Basemap itself doesn't do any plotting. It just transforms given geospatial coordinates to map projection and gives that data to matplotlib for plotting.

First, we need to install the Basemap toolkit. If you are using EPD, Basemap is already installed. If you are on Linux, it is best to use native package managers to install the package containing Basemap. On Ubuntu, for example, the package is called python-mpltoolkits.basemap and can be installed using standard package manager:

$ sudo apt-get install python-mpltoolkits.basemap

On Mac OS X, it is recommended to use EPD, although installation using popular package managers such as Homebrew, Fink, and pip is also possible.

How to do it...

Here is an example of how to use the Basemap toolkit to plot simple Mercator projection within a specific region, specified by longitude, latitude coordinate pairs:

  1. We instantiate Basemap defining the projection to be used (merc for Mercator).
  2. We define (in the same Basemap constructor) longitude and latitude for the lower-left and upper-right corners of a map.
  3. We set up the Basemap instance map, to draw coastlines and countries.
  4. We set up the Basemap instance map to fill continents and draw the map boundary.
  5. We instruct the Basemap instance map to draw meridians and parallels.

The following code shows how to use Basemap toolkit to plot a simple Mercator projection:

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

map = Basemap(projection='merc', 
              resolution = 'h', 
              area_thresh = 0.1,
    llcrnrlon=-126.619875, llcrnrlat=31.354158,
    urcrnrlon=-59.647219, urcrnrlat=47.517613)
map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color='coral', lake_color='aqua')
map.drawmapboundary(fill_color='aqua')

map.drawmeridians(np.arange(0, 360, 30))
map.drawparallels(np.arange(-90, 90, 30))

plt.show()

This will give a recognizable portion of our globe:

How to do it...

Now that we know how to plot a map, we need to know how to plot data on top of this map. If we recall that Basemap is a big transcoder of longitude and latitude pairs into current map projections, we will recognize that all we need is a dataset that contains longitude and latitude that we can pass to Basemap for projecting, before plotting over with matplotlib. We use the cities.shp and cities.shx files to load the coordinates of US cities and project them onto the map.

The file is provided in the Chapter06 folder of the code repository. Here's the example of how to achieve this:

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

map = Basemap(projection='merc', 
              resolution = 'h', 
              area_thresh = 100,
    llcrnrlon=-126.619875, llcrnrlat=25,
    urcrnrlon=-59.647219, urcrnrlat=55)
 
shapeinfo = map.readshapefile('cities','cities')
x, y = zip(*map.cities)

# build a list of US cities
city_names = []
for each in map.cities_info:
    if each['COUNTRY'] != 'US':
        city_names.append("")
    else:
        city_names.append(each['NAME'])

map.drawcoastlines()
map.drawcountries()
map.fillcontinents(color='coral', lake_color='aqua')
map.drawmapboundary(fill_color='aqua')
map.drawmeridians(np.arange(0, 360, 30))
map.drawparallels(np.arange(-90, 90, 30))

# draw city markers
map.scatter(x,y,25, marker='o',zorder=10)

# plot labels at City coords.
for city_label, city_x, city_y in zip(city_names, x, y):
    plt.text(city_x, city_y, city_label)

plt.title('Cities in USA') 

plt.show()

How it works...

The basics of Basemap usage consists of importing the main module and instantiating a Basemap class with desired properties. What we must specify during instantiations are the projections to be used and the portion of the globe that we want to work with.

Additional configuration can be applied before drawing the map and displaying the figure window with matplotlib.pyplot.show().

More than a dozen (or 32, to be precise) different projections are supported in Basemap. Most of them are very narrow-usage oriented, but some are more general and apply to most common map visualizations.

We can easily see what projections are available by asking the Basemap module itself:

import mpl_toolkits.basemap
print mpl_toolkits.basemap.supported_projections

mbtfpq

McBryde-Thomas Flat-Polar Quartic

aeqd

Azimuthal Equidistant

sinu

Sinusoidal

poly

Polyconic

omerc

Oblique Mercator

gnom

Gnomonic

moll

Mollweide

lcc

Lambert Conformal

tmerc

Transverse Mercator

nplaea

North-Polar Lambert Azimuthal

gall

Gall Stereographic Cylindrical

npaeqd

North-Polar Azimuthal Equidistant

mill

Miller Cylindrical

merc

Mercator

stere

Stereographic

eqdc

Equidistant Conic

cyl

Cylindrical Equidistant

npstere

North-Polar Stereographic

spstere

South-Polar Stereographic

hammer

Hammer

geos

Geostationary

nsper

Near-Sided Perspective

eck4

Eckert IV

aea

Albers Equal Area

kav7

Kavrayskiy VII

spaeqd

South-Polar Azimuthal Equidistant

ortho

Orthographic

cass

Cassini-Soldner

vandg

van der Grinten

laea

Lambert Azimuthal Equal Area

splaea

South-Polar Lambert Azimuthal

robin

Robinson

Usually, we plot the whole projection, if nothing is specified, and some reasonable defaults are used.

To zoom in on a specific region of the map, we specify the latitude and longitude of the lower-left and upper-right corners of the region you want to show. For this example, we will use the Mercator projection.

Tip

Here we see how the arguments' names are shortened descriptions:

llcrnrlon: This is lower-left corner longitude

llcrnrlat: This is lower-left corner latitude

urcrnrlon: This is upper-right corner longitude

urcrnrlat: This is upper-right corner latitude

There's more...

We have just scratched the surface of the capabilities of Basemap toolkit. More examples can be found in the official documentation at http://matplotlib.org/basemap/users/examples.html.

Most of the data used in the examples in the official Basemap documentation is located on remote servers and in a specific format. To efficiently fetch this data, NetCDF data format is used. NetCDF is a common data format designed with network efficiency in mind. It allows a program to fetch as much data as is needed, even when the whole dataset is very large, which makes using this format very practical. We don't have to download and store large datasets locally every time we want to use them and every time they change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.170.63