Search code examples
matplotlibcartopy

How to append axes in Matplotlib but not inherit axis type (Cartopy type, to be specific)


I use Basemap to plot, which doesn't introduce its own axis type and rather does some extreme math to make its geographic plotting. That let this work:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(); #use instead of fig because it inits an axis too
divider = make_axes_locatable(ax); #prep to add an axis
cax = divider.append_axes('right', size='2.0%', pad=0.15); #make a color bar axis

I preferred this because it kept the new axis within the original axis bounds, which made lining up other subplots (by using an identical divider.append_axes(...) call with them as well) easy and making sure the new colorbar axis didn't clip off the plot easy as well.

But since Basemap is depreciated, I'm trying to move to Cartopy. Unfortunately similar code with Cartopy:

import matplotlib.pyplot as plt
import cartopy as cartopy
fig, ax = plt.subplots(); #use instead of fig because it inits an axis too
ax = plt.axes(projection=cartopy.crs.PlateCarree()); #redefine the axis to be a geographical axis
divider = make_axes_locatable(ax); #prep to add an axis
cax = divider.append_axes('right', size='2.0%', pad=0.15); #make a color bar axis

Gives the error:

KeyError: 'map_projection'

Since under Cartopy the axis ax is changed to a Cartopy axis, the appended axis cax is also a Cartopy axis. If I provide a map_projection=cartopy.crs.PlateCarree() the code runs, but I don't want it to be a Cartopy axis, I want it to be a colorbar (and the Cartopy axis errors if I use it as a colorbar).

How can I append_axes but not inherit the Cartopy axis type?

Additionally, I found not-quite-good-enough work-around using:

import matplotlib.pyplot as plt
import cartopy as cartopy
fig, ax = plt.subplots(); #use instead of fig because it inits an axis too
ax = plt.axes(projection=cartopy.crs.PlateCarree()); #redefine the axis to be a geographical axis
cax = ax.inset_axes((1.02, 0, 0.02, 1)); #make a color bar axis

But that cax is not part of the original axis bounds, which makes it useless for lining up other subplots that use the divider.append_axes() method and the colorbar can clip off the edge of the plot since it is floating in "white space".


Solution

  • I found the answer in this post: https://stackoverflow.com/a/52447676/21257881:

    import matplotlib.axes as maxes
    cax = divider.append_axes("top", size="5%", axes_class=maxes.Axes)