56

I want to make 4 imshow subplots but all of them share the same colormap. Matplotlib automatically adjusts the scale on the colormap depending on the entries of the matrices. For example, if one of my matrices has all entires as 10 and the other one has all entries equal to 5 and I use the Greys colormap then one of my subplots should be completely black and the other one should be completely grey. But both of them end up becoming completely black. How to make all the subplots share the same scale on the colormap?

lovespeed
  • 4,835
  • 15
  • 41
  • 54
  • It seems that this post have an answer that could help you. http://stackoverflow.com/questions/3373256/set-colorbar-range-in-matplotlib – bserra Aug 01 '13 at 09:33
  • possible duplicate of [Matplotlib 2 Subplots, 1 Colorbar](http://stackoverflow.com/questions/13784201/matplotlib-2-subplots-1-colorbar) – Ruggero Turra Mar 03 '15 at 16:51

3 Answers3

82

To get this right you need to have all the images with the same intensity scale, otherwise the colorbar() colours are meaningless. To do that, use the vmin and vmax arguments of imshow(), and make sure they are the same for all your images.

E.g., if the range of values you want to show goes from 0 to 10, you can use the following:

import pylab as plt
import numpy as np
my_image1 = np.linspace(0, 10, 10000).reshape(100,100)
my_image2 = np.sqrt(my_image1.T) + 3
plt.subplot(1, 2, 1)
plt.imshow(my_image1, vmin=0, vmax=10, cmap='jet', aspect='auto')
plt.subplot(1, 2, 2)
plt.imshow(my_image2, vmin=0, vmax=10, cmap='jet', aspect='auto')
plt.colorbar()

enter image description here

Basj
  • 41,386
  • 99
  • 383
  • 673
tiago
  • 22,602
  • 12
  • 72
  • 88
  • 8
    not very beautiful since second axis is narrower, see http://stackoverflow.com/questions/13784201/matplotlib-2-subplots-1-colorbar instead – Ruggero Turra Mar 03 '15 at 16:17
  • @RuggeroTurra True, but that is because `aspect='auto'` and can in any case be adjusted by changing the subplot spaces (or e.g. gridspec). In the accepted answer that you link the colorbar is also not as tall as the axes, so still some adjustments are necessary. – tiago Mar 04 '15 at 09:15
18

When the ranges of data (data1 and data2) sets are unknown and you want to use the same colour bar for both/all plots, find the overall minimum and maximum to use as vmin and vmax in the call to imshow:

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=1, ncols=2)

# generate randomly populated arrays
data1 = np.random.rand(10,10)*10 
data2 = np.random.rand(10,10)*10 -7.5

# find minimum of minima & maximum of maxima
minmin = np.min([np.min(data1), np.min(data2)])
maxmax = np.max([np.max(data1), np.max(data2)])

im1 = axes[0].imshow(data1, vmin=minmin, vmax=maxmax,
                     extent=(-5,5,-5,5), aspect='auto', cmap='viridis')
im2 = axes[1].imshow(data2, vmin=minmin, vmax=maxmax,
                     extent=(-5,5,-5,5), aspect='auto', cmap='viridis')

# add space for colour bar
fig.subplots_adjust(right=0.85)
cbar_ax = fig.add_axes([0.88, 0.15, 0.04, 0.7])
fig.colorbar(im2, cax=cbar_ax)

Double imshow plot with single colourbar

naught101
  • 18,687
  • 19
  • 90
  • 138
airdas
  • 872
  • 2
  • 11
  • 19
6

It may be that you don't know beforehand the ranges of your data, but you may know that somehow they are compatible. In that case, you may prefer to let matplotlib choose those ranges for the first plot and use the same range for the remaining plots. Here is how you can do it. The key is to get the limits with properties()['clim']

import numpy as np
import matplotlib.pyplot as plt

my_image1 = np.linspace(0, 10, 10000).reshape(100,100)
my_image2 = np.sqrt(my_image1.T) + 3

fig, axes = plt.subplots(nrows=1, ncols=2)
im = axes[0].imshow(my_image1)
clim=im.properties()['clim']
axes[1].imshow(my_image2, clim=clim)

fig.colorbar(im, ax=axes.ravel().tolist(), shrink=0.5)

plt.show()
Ramon Crehuet
  • 3,679
  • 1
  • 22
  • 37
  • 1
    That's not going to work if the range of values in the first plot are smaller than the range in the second plot. – naught101 Jan 15 '18 at 04:03
  • Agreed. But that is what I explained in the text. This will work if you don't know the best ranges but you assume that the automatic ranges for the first plot will fit the remaining ones. – Ramon Crehuet Jan 19 '18 at 11:12
  • @naught101 Only ~3 years late but below is my solution to that issue: find overall min and max to use as `vmin` and `vmax` in imshow. – airdas Dec 21 '20 at 13:23