Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating Matplotlib panel - blit leaves old frames behind

I have a wxPython application which contains a matplotlib panel (courtesy of wxmpl, though I've seen the same with a plain FigureCanvasWxAgg canvas).

I'd want to animate one of the plots in the panel, and in the past I've made similar things happen. The way I'm doing it is the suggested:

  • copy the background
  • plot
  • [...]
  • restore background
  • update line data
  • draw artist
  • blit

The problem is that the plots, instead of being "overwritten" by the background restoring, stay there and the whole things understandably looks a mess.

Some (simplified) code:

fig = self.myPanel.get_figure()
ax_top = fig.add_subplot(211)
ax_bottom = self.fig.add_subplot(212)
canvas = fig.canvas
canvas.draw()
bg_top = canvas.copy_from_bbox(ax_top.bbox)
bg_bottom = canvas.copy_from_bbox(ax_bottom.bbox)
line, = ax_bottom.plot(x, y, 'k', animated=True)

Then, on update:

canvas.restore_region(bg_bottom)
line.set_ydata(new_y)
ax_bottom.draw_artist(line)
canvas.blit(ax_bottom.bbox)

The new line gets drawn (and very fast! :), but for some reason it happens over the old line. Can anybody guess why?

like image 500
Agos Avatar asked Apr 19 '26 02:04

Agos


2 Answers

Added as an answer, by request :)

Try calling fig.canvas.draw() before calling fig.canvas.copy_from_bbox. The exact behavior depends on the backend, so it will be different on different platforms, but generally speaking you need to draw the canvas before trying to copy things from it.

like image 175
Joe Kington Avatar answered Apr 20 '26 14:04

Joe Kington


Tested with FigureCanvasWxAgg. I think what happens is that between you initializing the panel and axes and then drawing the axis is moved or resized or something. Try waiting to get those backgrounds until you actually draw, i.e. when you initialize frame/panel:

...
bg_top = None
bg_bottom = None
line, = ax_bottom.plot(x, y, 'k', animated=True)
...

The when you update:

def update(self, evt):
    if bf_top is None:
        bg_top = canvas.copy_from_bbox(ax_top.bbox)
        bg_bottom = canvas.copy_from_bbox(ax_bottom.bbox)
    canvas.restore_region(bg_bottom)
    line.set_ydata(new_y)
    ax_bottom.draw_artist(line)
    canvas.blit(ax_bottom.bbox)
like image 43
simonb Avatar answered Apr 20 '26 16:04

simonb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!