2

I want to have several subplots, two of which showing frames from a video feed, and a third showing computed results as a bar graph. After creating a matplotlib figure, I create several subplot2grids, which I then update with FuncAnimation.

The usual way I would create a bar graph (to be updated) is:

fig = plt.figure()
ax = plt.axes(xlim=(0, 9), ylim=(0, 100))
rects = plt.bar(res_x, res_y, color='b')

def animate(args):
    ...
    ...
    for rect, yi in zip(rects, results):
        rect.set_height(yi*100)
    return rects

anim = animation.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
plt.show()

I am now trying to add a bar graph along side the other subplots:

fig = plt.figure()
plt1 = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
plt2 = plt.subplot2grid((2, 2), (0, 1))

#Confusion with the following
bar_plot = plt.subplot2grid((2,2), (1,1))
ax = plt.axes(xlim=(0, 9), ylim=(0, 100))
rects = plt.bar(res_x, res_y, color='b')


def animate(args):
    ...
    ...

    im1 = plt1.imshow(...)
    im2 = plt2.imshow(...)

    for rect, yi in zip(rects, results):
        rect.set_height(yi*100)
    return im1, im2, rects

anim = animation.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
plt.show()

I get the following error: AttributeError: 'BarContainer' object has no attribute 'set_animated'

Any ideas how I can "place" a bar graph as a subplot, and have it update together with other data from subplots?

Thanks!

dtam
  • 241
  • 1
  • 5
  • 15

1 Answers1

3

The error comes from the line return im1, im2, rects.

While in the working solution, you have return rects, i.e. you return a list of artists which have a set_animated method. In the code that fails you have a tuple of one BarContainer and two artists. As the error suggests, AttributeError: 'BarContainer' object has no attribute 'set_animated'.

A solution might be to produce a list of the contents of the BarContainer which you can concatenate to the other two artists.

return [rect for rect in rects]+[im1, im2]

A full working example:

import matplotlib.pyplot as plt
import matplotlib.animation as animation

res_x, res_y = [1,2,3], [1,2,3]

fig = plt.figure()
ax = plt.subplot2grid((2, 2), (0, 0), rowspan=2)
ax2 = plt.subplot2grid((2, 2), (0, 1))
ax3 = plt.subplot2grid((2,2), (1,1))

rects = ax3.bar(res_x, res_y, color='b')
im1 = ax.imshow([[1,2],[2,3]], vmin=0)
im2 = ax2.imshow([[1,2],[2,3]], vmin=0)

def animate(i):

    im1.set_data([[1,2],[(i/100.),3]])
    im2.set_data([[(i/100.),2],[2.4,3]])

    for rect, yi in zip(rects, range(len(res_x))):
        rect.set_height((i/100.)*(yi+0.2))
    return [rect for rect in rects]+[im1, im2]

anim = animation.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • @dtam If this answers your question, you should consider [accepting](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) it. If it doesn't, you may provide further details by updating your question. You may also consider upvoting, if the answer is helpful (which it presumably is, if it solves the problem). Of course, the same holds for your older questions ([here](http://stackoverflow.com/questions/43099734/combining-cv2-imshow-with-matplotlib-plt-show-in-real-time) and [here](http://stackoverflow.com/questions/43372792/matplotlib-opencv-image-subplot)). – ImportanceOfBeingErnest Apr 12 '17 at 21:27
  • Using this solution I get the following error: "AttributeError: draw_artist can only be used after an initial draw which caches the render" Also, this opens up the plot for the bar graph, but covers the other two subplots, whereas I would like all three to be subplots and see them together. Any idea? I apologize for not accepting the previous ones, I will get to them now. – dtam Apr 13 '17 at 06:35
  • Since you do not show the complete code, it's impossible to know where this error comes from. But I added a [mcve] to my answer, which shows that it works as expected. – ImportanceOfBeingErnest Apr 13 '17 at 06:41
  • The example you provided allowed me to fix my issue, thank you! I have a follow up question: I was trying to define the bar graph axes like this: ax = plt.axes(xlim=(0, 9), ylim=(0, 100)) I've realized that I get errors when I run the animation with this line. Is there another way I can set my X-axes to go from 0-9 and Y-axes from 0-100? Cheers! – dtam Apr 13 '17 at 12:00
  • In order to set the limits of an existing axes `ax`, do `ax.set_xlim(0,9)` `ax.set_ylim(0,100)`. – ImportanceOfBeingErnest Apr 13 '17 at 12:28