Each Answer to this Q is separated by one/two green lines.
all. I want to update the colorbar of a figure when the imagedata is changed. So something like:
img = misc.lena() fig = plt.figure() ax = plt.imshow(im) plt.colorbar(ax) newimg = img+10*np.randn(512,512) def update_colorbar(fig,ax,newimg): cbar = fig.axes ax.set_data(newimg) cbar.update_normal(ax) plt.draw()
but it seems that returned results from fig.axes() does not have the colorbar instance like I expected. I can probably just pass the colorbar instance as an argument to the update function, but I thought just passing one fig parameter may be good enough. Can anyone explain a little bit on how to retrieve the colorbar from the figure? Or why ‘fig.axes()’ doesn’t return the AxesImage or Colobar instance but just the Axes or AxesSubplot? I think I just need more understanding of the Axes/Figure stuff.Thank you!
Sometimes it can be useful to retrieve a colorbar even if it was not held in a variable.
In this case, it is possible to retrieve the colorbar from the plot with:
# Create an example image and colourbar img = np.arange(20).reshape(5,4) plt.imshow(img) plt.colorbar() # Get the current axis ax = plt.gca() # Get the images on an axis im = ax.images # Assume colorbar was plotted last one plotted last cb = im[-1].colorbar # Do any actions on the colorbar object (e.g. remove it) cb.remove()
or, equivalently, the one liner:
N.B.: see also comments for the use of
ax.collections[-1] instead of
ax.images[-1]. For me it always worked only the first way, I don’t know what depends on, maybe the type of data or plot.
Now you can operate on
cb as if it were stored using commands described in the colorbar API. For instance you could change
xlim or call update as explained in other comments. You could remove it with
cb.remove() and recreate it with
show should be called after to update plot.
As the image is the mappable associated to the colorbar and can be obtained with
First off, I think you’re getting a bit confused between the axes (basically, the plot), the figure, the scalar mappable (the image, in this case), and the colorbar instance.
figure is the window that the plot is in. It’s the top-level container.
Each figure usually has one or more
axes. These are the plots/subplots.
Colorbars are also inside the figure. Adding a colorbar creates a new axes (unless you specify otherwise) for the colorbar to be displayed in. (It can’t normally be displayed in the same axes as the image, because the colorbar needs to have its own x and y limits, etc.)
Some of your confusion is due to the fact that you’re mixing the state-machine interface and the OO interface. It’s fine to do this, but you need to understand the OO interface.
fig.axes isn’t the colorbar instance. It’s the axes that the colorbar is plotted in. (Also,
fig.axes is just the second axes in the figure. It happens to be the axes that the colorbar is in for a figure with one subplot and one colorbar, but that won’t generally be the case.)
If you want to update the colorbar, you’ll need to hold on to the colorbar instance that
Here’s an example of how you’d normally approach things:
import matplotlib.pyplot as plt import numpy as np data = np.random.random((10,10)) # Generate some random data to plot fig, ax = plt.subplots() # Create a figure with a single axes. im = ax.imshow(data) # Display the image data cbar = fig.colorbar(im) # Add a colorbar to the figure based on the image
If you’re going to use
update_normal to update the colorbar, it expects a
ScalarMappable (e.g. an image created by
imshow, the collection that
scatter creates, the
contour creates, etc) to be passed in. (There are other ways to do it, as well. Often you just want to update the limits, rather than the whole thing.) In the case of the code above, you’d call
However, you haven’t created a new
AxesImage, you’ve just changed it’s data. Therefore, you probably just want to do: