Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • Matplotlib 2 Subplots, 1 Colorbar
like image 352
Daniel Wehner Avatar asked Apr 24 '14 13:04

Daniel Wehner


3 Answers

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

like image 106
The Dude Avatar answered Sep 24 '22 15:09

The Dude


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
like image 23
fxmartins Avatar answered Sep 23 '22 15:09

fxmartins


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

like image 34
Christian O'Reilly Avatar answered Sep 20 '22 15:09

Christian O'Reilly