First set of (scatter) plot data remains on the graph during animation with Python's matplotlib

StackOverflow https://stackoverflow.com/questions/19470324

Question

I'm trying to animate a line and 3 scatter points on a graph. Everything seems to be working except the first set of scatter points don't get removed on the graph.

Here is the code, you can try setting n equal to 1, 2 or 3

import numpy as np
from math import *
from pylab import *
from matplotlib import pyplot as plt
from matplotlib import animation

# Constants
isqrt = 2**(-0.5)
omega = np.sqrt(2-np.sqrt(2))   #Angular velocity
L=4                             #Length of the system

n = 1                         #Normal mode number  
if n==1:
    z = [isqrt,1,isqrt]             #mode 1
elif n==2:
    z = [1,0,-1]                   #mode 2
elif n==3:
    z = [isqrt,-1,isqrt]           #mode 3

ex = [1,2,3]                    #x-coordinates of scatter points

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, L), ylim=(-1.1, 1.1))

line, = ax.plot([], [], lw=2)
scat = ax.scatter([],[])
# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    scat.set_array(None)
    return [scat,line,]

# animation function.  This is called sequentially
def animate(t):
    xinterval = np.arange(0,10,0.05)
    wave = np.cos(0.1*omega*t)*np.sin(n*xinterval*np.pi/L)
    line.set_data(xinterval, wave)
    dots = z*real(np.exp(0+(omega*0.1*t)*1j))

    scat = plt.scatter(ex, dots, s=50)
    return [scat,line,]

# call the animator. 
anim = animation.FuncAnimation(fig, animate,init_func=init, frames=200, interval=20,     blit=True)
plt.grid(True)
plt.show()
Était-ce utile?

La solution

import numpy as np
from math import *
from pylab import *
from matplotlib import pyplot as plt
from matplotlib import animation

# Constants
isqrt = 2**(-0.5)
omega = np.sqrt(2-np.sqrt(2))   #Angular velocity
L=4                             #Length of the system

n = 1                         #Normal mode number  
if n==1:
    z = [isqrt,1,isqrt]             #mode 1
elif n==2:
    z = [1,0,-1]                   #mode 2
elif n==3:
    z = [isqrt,-1,isqrt]           #mode 3

ex = [1,2,3]                    #x-coordinates of scatter points

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, L), ylim=(-1.1, 1.1))

line, = ax.plot([], [], lw=2, color='b')
scat, = ax.plot([],[], linestyle='', marker='o', color='b')
# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    scat.set_data([], [])
    return [scat,line,]

# animation function.  This is called sequentially
def animate(t):
    xinterval = np.arange(0,10,0.05)
    wave = np.cos(0.1*omega*t)*np.sin(n*xinterval*np.pi/L)
    line.set_data(xinterval, wave)
    dots = z*real(np.exp(0+(omega*0.1*t)*1j))

    scat.set_data(ex, dots)
    return [scat,line,]

# call the animator. 
anim = animation.FuncAnimation(fig, animate,init_func=init, frames=range(200), interval=20,     blit=True)
plt.grid(True)
plt.show()

Unless you have a complelling reason to use scatter (which is you want each marker to be a different color or size, which your example code does not show) the above will generate the same animation much more efficiently.

The issue with your original code is that you are not updating the scatter artist each time through, you are adding a new artist which interacts with the blitting code in strange ways (on my machine, all of the previous dots randomly were visible or not).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top