Daniel Wehner
Daniel Wehner

Reputation: 2189

Adding a colorbar to two subplots with equal aspect ratios

I'm trying to add a colorbar to a plot consisting of two subplots with equal aspect ratios, i.e. with set_aspect('equal'):

enter image description here

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)

enter image description here

This question seems related:

Upvotes: 7

Views: 4800

Answers (3)

Christian O'Reilly
Christian O'Reilly

Reputation: 2054

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)

enter image description here

Upvotes: 1

fxmartins
fxmartins

Reputation: 41

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

Upvotes: 4

The Dude
The Dude

Reputation: 4005

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()

enter image description here

Upvotes: 8

Related Questions