Skip to content

Commit 4566fbc

Browse files
authored
Merge pull request #2502 from rcomer/map-latitude
DOC: add example aligning Cartopy and Matplotlib axes
2 parents 7c66fd5 + 24dad77 commit 4566fbc

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""
2+
Aligning Cartopy and Matplotlib axes
3+
====================================
4+
5+
Sometimes it is useful to line up a standard Matplotlib axes with a Cartopy map, for
6+
example when plotting zonal mean data next to a global contour plot. This example
7+
demonstrates one way to do that for projections where latitude lines are horizontal.
8+
9+
"""
10+
11+
# sphinx_gallery_multi_image = "single"
12+
13+
import matplotlib.pyplot as plt
14+
import numpy as np
15+
16+
import cartopy.crs as ccrs
17+
18+
19+
PC_PROJ = ccrs.PlateCarree()
20+
21+
def map_and_latitudes(map_proj):
22+
"""
23+
Create a map with the given projection, together with a rectangular axes
24+
whose y-axis matches the map.
25+
"""
26+
27+
fig = plt.figure(figsize=(12, 5), layout='compressed')
28+
29+
# Create the map.
30+
map_ax = fig.add_subplot(projection=map_proj)
31+
map_ax.set_global()
32+
gl = map_ax.gridlines(draw_labels=True)
33+
map_ax.coastlines()
34+
35+
# Add the rectangular axes to the right of the map.
36+
rect_ax = map_ax.inset_axes([1.1, 0, 0.3, 1])
37+
38+
# Set up scaling for the rectangular axes latitudes. This part is
39+
# necessary for projections with uneven latitude spacing, such as Mercator,
40+
# but can be skipped for PlateCarree for example.
41+
# Create functions to map between latitude and the projection's y values.
42+
# Assume these are not x-dependent so we can just set x/longitude to zero.
43+
44+
def to_map(lat):
45+
"""Transform latitudes to projection's y-values."""
46+
dummy_lon = np.zeros_like(lat)
47+
projected = map_proj.transform_points(PC_PROJ, dummy_lon, lat)
48+
return np.take(projected, 1, axis=-1)
49+
50+
def from_map(y):
51+
"""Transform projection's y-values to latitude."""
52+
dummy_x = np.zeros_like(y)
53+
projected = PC_PROJ.transform_points(map_proj, dummy_x, y)
54+
return np.take(projected, 1, axis=-1)
55+
56+
# Use these function to define the y-scale on the rectangular axes.
57+
rect_ax.set_yscale('function', functions=(to_map, from_map))
58+
# Convert the map's y-limits to latitudes and set the y-limits.
59+
rect_ax.set_ylim(from_map(np.array(map_ax.get_ylim())))
60+
61+
# y-axis visual choices.
62+
rect_ax.grid(axis='y')
63+
rect_ax.yaxis.tick_right()
64+
rect_ax.yaxis.set_major_locator(gl.ylocator)
65+
rect_ax.yaxis.set_major_formatter(gl.yformatter)
66+
67+
# Plot some dummy data.
68+
y = np.linspace(-90, 90, 21)
69+
y_rad = np.deg2rad(y)
70+
rect_ax.plot(np.sin(y_rad), y, label='sine')
71+
rect_ax.plot(np.cos(y_rad), y, label='cosine')
72+
rect_ax.legend()
73+
74+
# Add the projection name as the title.
75+
fig.suptitle(type(map_proj).__name__)
76+
77+
78+
if __name__ == '__main__':
79+
for map_proj in [ccrs.PlateCarree(), ccrs.Mercator(), ccrs.Robinson()]:
80+
map_and_latitudes(map_proj)
81+
82+
plt.show()

0 commit comments

Comments
 (0)