I would like to add a custom plt.colorbar
to a figure containing multiple healpy
plots. I have found many posts on how to do this for the usual case of multiple axes
objects, but the healpy
makes it difficult.
I have the following MWE so far:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import healpy as hp
rows, cols = 8, 8
nplots = rows * cols
npix = 48
data = np.random.uniform(size=(nplots, npix))
fig = plt.figure()
for i in range(len(data)):
hp.mollview(data[i, :], title='', cbar=False, fig=fig,
sub=(rows, cols, i+1), margins=(0, 0, 0, 0),
min=data.min(), max=data.max())
fig, ax = plt.gcf(), plt.gca()
image = ax.get_images()[0]
norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(ax)
cax = divider.new_vertical(size="5%", pad=0.7, pack_start=True)
fig.add_axes(cax)
fig.colorbar(image, cax=cax, norm=norm, orientation='horizontal',
label='colorbar')
plt.show()
As shown in the linked image I end up with a colorbar
attached to the last ax
rather than the entire fig
. I would like a simple colorbar
on the bottom (or right side) of the fig
, with a range specified through Normalize
as above. Again, it is the fact that I am using healpy
to produce the figure that rules out the usual solutions, at least to my knowledge.
I don't have healpy installed, but probably this library just creates its own axes. The code below emulates such a situation. You can get the axes from fig.axes
.
As in this tutorial, a default colorbar can be placed just by giving a list of all the 'axes' (an ax
is more or less matplotlib's name for a subplot): plt.colorbar(im, ax=fig.axes)
. If the colorbar would be too large, it has a shrink=0.6
parameter.
from matplotlib import pyplot as plt
import numpy as np
fig = plt.figure(figsize=(20, 6))
nrows = 4
ncols = 6
for i in range(1, nrows + 1):
for j in range(1, ncols + 1):
plt.subplot(nrows, ncols, (i - 1) * ncols + j, projection="mollweide")
arr = np.random.rand(18, 36)
Lon, Lat = np.meshgrid(np.linspace(-np.pi, np.pi, 36 + 1), np.linspace(-np.pi / 2., np.pi / 2., 18 + 1))
plt.pcolormesh(Lon, Lat, arr, cmap=plt.cm.hot)
im = fig.axes[0].collections[0] # or fig.axes[0].get_images()[0] when created as image
plt.colorbar(im, ax=fig.axes)
plt.show()
Note that in your code, fig
already points to the current figure, making fig = plt.gcf()
unnecessary. ax = plt.gca()
indicates the ax
that was last active. In the case of the example plot this seems to be the lower right one. So, this helps to find an example image, but not to position the colorbar next to all subplots.
If you need more control about the colorbar placement, you can also adopt the approach from this post:
fig.subplots_adjust(right=0.85)
cbar_ax = fig.add_axes([0.90, 0.15, 0.03, 0.7])
fig.colorbar(im, cax=cbar_ax)