Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib animation: first frame remains in canvas when using blit

I'm trying to plot two rotating ellipses using the Matplotlib animation library, and I managed to get it working (more or less). The problem is that the first frame that is being rendered does not update, so while I got two rotating ellipses in my canvas, I also have the ellipses in their original position/orientation. Check out my simple piece of code:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)

def init():
    ax.add_patch(e1)
    ax.add_patch(e2)
    return [e1,e2]

def animate(i):
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

Any idea how to fix this? I could of course turn off blit, but that makes it horribly slow, so that's not really an option.

EDIT: Final (working) Code

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)
ax.add_patch(e1)
ax.add_patch(e2)

def init():
    e1.set_visible(False)
    e2.set_visible(False)
    return [e1,e2]

def animate(i):
    if i == 1:
        e1.set_visible(True)
        e2.set_visible(True)
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()
like image 292
MPA Avatar asked Jan 29 '14 18:01

MPA


People also ask

What does PLT show () do?

plt. show() starts an event loop, looks for all currently active figure objects, and opens one or more interactive windows that display your figure or figures. The plt. show() command does a lot under the hood, as it must interact with your system's interactive graphical backend.

What does blit do matplotlib?

Blitting is a standard technique in raster graphics that, in the context of Matplotlib, can be used to (drastically) improve performance of interactive figures. For example, the animation and widgets modules use blitting internally. Here, we demonstrate how to implement your own blitting, outside of these classes.


1 Answers

Try this:

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
e2 = Ellipse(xy=(0.8, 0.8), width=0.5, height=0.2, angle=100)


def init():
    return [ax]

def animate(i):
    if i==0:
        ax.add_patch(e1)
        ax.add_patch(e2)    
    e1.angle = e1.angle + 0.5
    e2.angle = e2.angle + 0.5
    return [e1,e2]

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()

Screen-shot showing the correct behavior

Try this other approach (not I've used only one ellipse just for testing, it also renders fine here):

import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
from matplotlib import animation

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
e1 = Ellipse(xy=(0.5, 0.5), width=0.5, height=0.2, angle=60)
ax.add_patch(e1)

def init():
    e1.set_visible(False)
    return e1,

def animate(i):
    if i==0:
        e1.set_visible(True)
    e1.angle = e1.angle + 0.5
    return e1,

anim = animation.FuncAnimation(fig, animate, init_func=init, interval=1, blit=True)
plt.show()
like image 76
Alvaro Fuentes Avatar answered Sep 22 '22 02:09

Alvaro Fuentes