I’m working with existing code that creates a matplotlib figure with one axes, and adds a colorbar to it after-the-fact using
append_axes. It works, but I want to subsequently change the vertical height of the colorbar. I’ve figured out that this is only possible if I call the
set_axes_locator(None) method on the colorbar axis (not 100% sure why) — if I don’t do that, any calls to
cax.set_position() silently do nothing. Here’s the setup; question below:
import numpy as np import matplotlib.pyplot as plt from matplotlib.colorbar import ColorbarBase from mpl_toolkits.axes_grid1 import make_axes_locatable def make_figure(n_levels, shrink=False): data = np.random.randint(n_levels, size=(5, 7)) fig, ax = plt.subplots() ax.imshow(data) divider = make_axes_locatable(ax) cax = divider.append_axes('right', size='5%', pad=0.1) cmap = ax.images.get_cmap() cmap = cmap._resample(n_levels) _ = ColorbarBase(cax, cmap=cmap, norm=None, orientation='vertical') if shrink: shrink_colorbar(cax, n_levels) return fig def shrink_colorbar(cax, n_levels): pos = cax.get_position().bounds height = pos[-2] * n_levels new_y = pos + (pos[-1] - height) / 2 newpos = (pos, new_y, pos, height) cax.set_axes_locator(None) cax.set_position(newpos)
If I do the colorbar resizing inside the function environment where the figure is created, I get the wrong result every time, whether I use regular Python REPL or iPython:
n_levels = 3 make_figure(n_levels, shrink=True)
If I create the figure first, then shrink the colorbar after the fact, it works how I want it to as long as these lines are run separately (either in regular Python REPL with
plt.ion(), or if each line is in a separate iPython cell):
fig = make_figure(n_levels) cax = fig.axes[-1] shrink_colorbar(cax, n_levels)
If those same lines are run as a single iPython cell, or if run with
plt.ioff() in a regular Python REPL and followed by
plt.show(), I get the same bad result as the first example above (with
shrink=True in the outer function).
How can I get the correct result while still doing the colorbar resizing inside the function (instead of in userland)?