I'm trying to add a colorbar to a plot consisting of two subplots with equal aspect ratios, i.e. with set_aspect('equal')
:
The code used to create this plot can be found in this IPython notebook.
The image created using the code shown below (and here in the notebook) is the best result I could get, but it is still not quite what I want.
plt.subplot(1,2,1)
plt.pcolormesh(rand1)
plt.gca().set_aspect('equal')
plt.subplot(1,2,2)
plt.pcolormesh(rand2)
plt.gca().set_aspect('equal')
plt.tight_layout()
from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(cax=cax)
This question seems related:
I'm still not sure what you exactly want but I guess you want to subplots using pcolormesh
to have the same size when you add a colorbar?
What I have now is a bit of a hack as I add a colorbar
for both subplots to ensure they have the same size. Afterwords I remove the first colorbar
. If the result is what you want I can look into a more pythonic way of achieving it. For now it is still a bit vague as to what you exactly want.
import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = numpy.random.random((10, 10))
fig = plt.figure()
ax1 = fig.add_subplot(1,2,1, aspect = "equal")
ax2 = fig.add_subplot(1,2,2, aspect = "equal")
im1 = ax1.pcolormesh(data)
im2 = ax2.pcolormesh(data)
divider1 = make_axes_locatable(ax1)
cax1 = divider1.append_axes("right", size="5%", pad=0.05)
divider2 = make_axes_locatable(ax2)
cax2 = divider2.append_axes("right", size="5%", pad=0.05)
#Create and remove the colorbar for the first subplot
cbar1 = fig.colorbar(im1, cax = cax1)
fig.delaxes(fig.axes[2])
#Create second colorbar
cbar2 = fig.colorbar(im2, cax = cax2)
plt.tight_layout()
plt.show()
This solution is similar to the one above, but does not require creating and discarding the colorbar.
Notice that there is a potential flaw in both solutions: the colorbar will use the colormap and normalization of one of the color meshes. If these are the same for both, it is not a problem.
The ImageGrid
class has something that looks like what you want:
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure(1, (4., 4.))
ax = plt.subplot(1,1,1)
divider = make_axes_locatable(ax)
cm = plt.pcolormesh(rand1)
ax.set_aspect('equal')
cax = divider.append_axes("right", size="100%", pad=0.4)
plt.pcolormesh(rand2)
cax.set_aspect('equal')
sm = plt.cm.ScalarMappable(cmap=cm.cmap, norm=cm.norm)
sm._A = []
cax = divider.append_axes("right", size="10%", pad=0.1)
plt.colorbar(sm, cax=cax)
None # Prevent text output
Although the accepted solution works, it is rather hacky. I think a cleaner approach is to use GridSpec. It also scales better to larger grids.
import numpy
import matplotlib.pyplot as plt
import matplotlib
nb_cols = 5
data = numpy.random.random((10, 10))
fig = plt.figure()
gs = matplotlib.gridspec.GridSpec(1, nb_cols)
axes = [fig.add_subplot(gs[0, col], aspect="equal") for col in range(nb_cols)]
for col, ax in enumerate(axes):
im = ax.pcolormesh(data, vmin=data.min(), vmax=data.max())
if col > 0:
ax.yaxis.set_visible(False)
fig.colorbar(im, ax=axes, pad=0.01, shrink=0.23)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With