In [ ]:
%matplotlib inline
The aim of the cartopy course is to introduce the cartopy library and highlight of some of its features.
The learning outcomes of the cartopy course are as follows. By the end of the course, you will be able to:
cartopy.crs
module,projection
and transform
keyword arguments, andIn order to create a map with cartopy and matplotlib, we typically need to import pyplot from matplotlib and cartopy's crs (coordinate reference system) submodule. These are typically imported as follows:
In [ ]:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
Cartopy's matplotlib interface is set up via the projection
keyword when constructing a matplotlib Axes
/ SubAxes
instance. The resulting axes instance has new methods, such as the coastlines()
method, which are specific to drawing cartographic data:
In [ ]:
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
plt.show()
A full list of Cartopy projections is available at http://scitools.org.uk/cartopy/docs/latest/crs/projections.html.
In [ ]:
#
# EDIT for user code ...
#
SAMPLE SOLUTION:
Un-comment and execute the following, to view a possible code solution.
Then run it ...
In [ ]:
# %load solutions/cartopy_exercise_1
Let's compare the Plate Carree projection to another projection from the projection list; being the Orthographic projection. We'll do that by plotting two subplots next to each other at the same time:
In [ ]:
# Make sure the figure is a decent size when plotted.
fig = plt.figure(figsize=(14, 7))
# Left plot.
ax1 = fig.add_subplot(1, 2, 1, projection=ccrs.PlateCarree())
ax1.coastlines()
# Right plot.
ax2 = fig.add_subplot(1, 2, 2, projection=ccrs.Orthographic())
ax2.coastlines()
# Show both subplots on the same figure.
plt.show()
To draw cartographic data, we use the standard matplotlib plotting routines with an additional transform
keyword argument. The value of the transform
argument should be the cartopy coordinate reference system of the data being plotted.
First let's plot a line on a PlateCarree projection.
In [ ]:
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
x0, y0 = -50, -30
x1, y1 = 10, 55
plt.plot([x0, x1], [y0, y1], linewidth=4)
plt.show()
Now let's try plotting the same line on an EquidistantConic
projection.
In [ ]:
proj = ccrs.EquidistantConic()
ax = plt.axes(projection=proj)
ax.coastlines()
plt.plot([x0, x1], [y0, y1], linewidth=4)
plt.show()
The above plot is not what we intended.
We have set up the axes to be in the Equidistant Conic projection, but we have not told Cartopy that the coordinates of the line are "in PlateCarree".
To do this, we use the transform
keyword in the plt.plot function :
In [ ]:
ax = plt.axes(projection=proj)
ax.coastlines()
plt.plot([x0, x1], [y0, y1], linewidth=4, transform=ccrs.PlateCarree())
plt.show()
Notice that the plotted line is bent : It is a straight line in the coordinate system it is defined in, so that makes it a curved line on this map.
Also note that, unless we specify a map extent, the map zooms to contain just the plotted data.
A very simple alternative to that is to plot the 'full map', by calling the set_global
method on the Axes, as in this case :
In [ ]:
ax = plt.axes(projection=proj)
ax.coastlines()
ax.set_global()
plt.plot([x0, x1], [y0, y1], linewidth=4, transform=ccrs.PlateCarree())
plt.show()
In [ ]:
#
# edit space for user code ...
#
In [ ]:
# SAMPLE SOLUTION
# %load solutions/cartopy_exercise_2
In [ ]:
#
# edit space for user code ...
#
In [ ]:
# SAMPLE SOLUTION
# %load solutions/cartopy_exercise_3
We can add features from the Natural Earth database to maps we produce. Natural Earth datasets are downloaded and cached when they are first used, so you need an internet connection to use them, and you may encounter warnings when you first download them.
We add features to maps via the cartopy feature interface.
For example, let's add political borders to a map:
In [ ]:
import cartopy.feature as cfeat
fig = plt.figure(figsize=(14, 7))
ax = plt.axes(projection=ccrs.Miller())
ax.coastlines('50m')
# ax.add_feature(cfeat.BORDERS, edgecolor='b')
political_bdrys = cfeat.NaturalEarthFeature(category='cultural',
name='admin_0_countries',
scale='50m')
ax.add_feature(political_bdrys,
edgecolor='b', facecolor='none',
linestyle='--', zorder=-1)
plt.show()
We can add graticule lines and tick labels to the map using the gridlines method (this currently is limited to just a few coordinate reference systems):
In [ ]:
ax = plt.axes(projection=ccrs.Mercator())
ax.coastlines()
gl = ax.gridlines(draw_labels=True)
plt.show()
We can control the specific tick values by using matplotlib's locator object, and the formatting can be controlled with matplotlib formatters:
In [ ]:
import matplotlib.ticker as mticker
from cartopy.mpl.gridliner import LATITUDE_FORMATTER
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
gl = ax.gridlines(draw_labels=True)
gl.xlocator = mticker.FixedLocator([-180, -45, 0, 45, 180])
gl.yformatter = LATITUDE_FORMATTER
plt.show()
Cartopy cannot currently label all types of projection, though more work is intended on this functionality in the future.
The following snippet of code produces coordinate arrays and some data in a rotated pole coordinate system. The coordinate system for the x
and y
values, which is similar to that found in the some limited area models of Europe, has a projection "north pole" at 193.0 degrees longitude and 41.0 degrees latitude.
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
x = np.linspace(337, 377, 25)
y = np.linspace(-18.7, 25.3, 35)
x2d, y2d = np.meshgrid(x, y)
data = np.cos(np.deg2rad(y2d) * 4) + np.sin(np.deg2rad(x2d) * 4)
Part 1
Define a cartopy coordinate reference system which represents a rotated pole with a pole latitude of 41.0 and a pole longitude of 193.0.
In [ ]:
Part 2
Produce a map, with coastlines, using the coordinate reference system created in Part 1.
In [ ]:
Part 3
Produce a map, with coastlines, in a Plate Carree projection with a pcolormesh of the data generated by the code snippet provided at the beginning of the exercise. Remember that the data is supplied in the rotated coordinate system defined in Part 1.
In [ ]:
NOTE:
For a worked solution, see this example notebook
In [ ]: