48

The following code fails to run on Python 2.5.4:

from matplotlib import pylab as pl
import numpy as np

data = np.random.rand(6,6)
fig = pl.figure(1)
fig.clf()
ax = fig.add_subplot(1,1,1)
ax.imshow(data, interpolation='nearest', vmin=0.5, vmax=0.99)
pl.colorbar()

pl.show()

The error message is

C:\temp>python z.py
Traceback (most recent call last):
  File "z.py", line 10, in <module>
    pl.colorbar()
  File "C:\Python25\lib\site-packages\matplotlib\pyplot.py", line 1369, in colorbar
    ret = gcf().colorbar(mappable, cax = cax, ax=ax, **kw)
  File "C:\Python25\lib\site-packages\matplotlib\figure.py", line 1046, in colorbar
    cb = cbar.Colorbar(cax, mappable, **kw)
  File "C:\Python25\lib\site-packages\matplotlib\colorbar.py", line 622, in __init__
    mappable.autoscale_None() # Ensure mappable.norm.vmin, vmax
AttributeError: 'NoneType' object has no attribute 'autoscale_None'

How can I add colorbar to this code?

Following is the interpreter information:

Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
Boris Gorelik
  • 29,945
  • 39
  • 128
  • 170

4 Answers4

89

(This is a very old question I know) The reason you are seeing this issue is because you have mixed the use of the state machine (matplotlib.pyplot) with the OO approach of adding images to an axes.

The plt.imshow function differs from the ax.imshow method in just one subtly different way. The method ax.imshow:

  • creates and returns an Image which has been added to the axes

The function plt.imshow:

  • creates and returns an Image which has been added to the current axes, and sets the image to be the "current" image/mappable (which can then be automatically picked up by the plt.colorbar function).

If you want to be able to use the plt.colorbar (which in all but the most extreme cases, you do) with the ax.imshow method, you will need to pass the returned image (which is an instance of a ScalarMappable) to plt.colorbar as the first argument:

plt.imshow(image_file)
plt.colorbar()

is equivalent (without using the state machine) to:

img = ax.imshow(image_file)
plt.colorbar(img, ax=ax)

If ax is the current axes in pyplot, then the kwarg ax=ax is not needed.

pelson
  • 21,252
  • 4
  • 92
  • 99
  • 2
    Is there a way to access the image from the axes object itself? Say you are writing a function that gets passed an axes object that already has an image plotted to it, and you want your function to add a colorbar. I would like to do something like plt.colorbar(ax.image,ax=ax). – Emma Nov 04 '13 at 22:14
  • You could use the ``images`` attribute on the axes to get a list of images within the Axes. Alternatively, the "active" image on the axes is available with ``gci`` (from memory). – pelson Nov 05 '13 at 11:07
  • would it work the same changing `plt.colorbar()` by `fig.colorbar()` ? – Manuel Pena Apr 17 '20 at 17:33
31

Note: I am using python 2.6.2. The same error was raised with your code and the following modification solved the problem.

I read the following colorbar example: http://matplotlib.sourceforge.net/examples/pylab_examples/colorbar_tick_labelling_demo.html

from matplotlib import pylab as pl
import numpy as np

data = np.random.rand(6,6)
fig = pl.figure(1)
fig.clf()
ax = fig.add_subplot(1,1,1)
img = ax.imshow(data, interpolation='nearest', vmin=0.5, vmax=0.99)
fig.colorbar(img)

pl.show()

Not sure why your example didn't work. I'm not that familiar with matplotlib.

Michele
  • 2,796
  • 2
  • 21
  • 29
Gary Kerr
  • 13,650
  • 4
  • 48
  • 51
1

I found another solution to this problem in a tutorial.

The code below, will work well for the plt.imshow() method:

def colorbar(Mappable, Orientation='vertical', Extend='both'):
    Ax = Mappable.axes
    fig = Ax.figure
    divider = make_axes_locatable(Ax)
    Cax = divider.append_axes("right", size="5%", pad=0.05)
    return fig.colorbar(
        mappable=Mappable, 
        cax=Cax,
        use_gridspec=True, 
        extend=Extend,  # mostra um colorbar full resolution de z
        orientation=Orientation
    )

fig, ax = plt.subplots(ncols=2)

img1 = ax[0].imshow(data)
colorbar(img1)

img2 = ax[1].imshow(-data)
colorbar(img2)

fig.tight_layout(h_pad=1)
plt.show()

It may not work well with other plotting methods. For example, it did not work with Geopandas Geodataframe plot.

roob
  • 2,419
  • 3
  • 29
  • 45
Philipe Riskalla Leal
  • 954
  • 1
  • 10
  • 28
  • 3
    Since you mention an external source (a tutorial) it would be useful to include a link to this source. – roob Jul 31 '18 at 21:37
  • `ax.figure` is an amazing tool to know about. It allows much functionality without having to pass fig directly to functions. – akozi Jan 24 '19 at 14:51
0

Add/edit the following lines to your code

plot = ax.imshow(data, interpolation='nearest', vmin=0.5, vmax=0.99)
pl.colorbar(plot)
Ishan Tomar
  • 1,488
  • 1
  • 16
  • 20
  • doesn't answer the question – invictus Jul 14 '17 at 00:01
  • @invictus The answer is similar to what Gary has given. It answers satisfactorily if you put some effort to TRY and EDIT the code using whatever I have written. The questioner's code doesn't work because pl.colorbar() is given wrong instance to plot. 'ax' defined in the code is a window instance by default. pl.colorbar() has to be directed to the plot instance. In my case 'plot' is what is required to be given to pl.colorbar() which is similar to 'cax' given by Gary – Ishan Tomar Jul 18 '17 at 07:31