Reputation: 143
Although hours of browsing stackoverflow definitely improved my python animate code, I could not quite figure out one thing and therefore I'm turning towards the kind souls of the community in the hope that someone might be able to shred some light.
In a nutshell, I have a background image that is about 2000 x 1000 pixels let's say, I need to scatter some points over this image and animate the process and save whole thing as a video. I'm able to update the scatterplot as needed only with the exception that I can't remove the precedent scatterplot. So the output is not what I would really want. I would be glad if someone could have a glance at the code and see where the glitch is. I've used scat.remove() which seems to be doing nothing.
Thank you in advance folks.
import matplotlib.pyplot as plt
import pylab as pl
import numpy as np
from pylab import savefig
from matplotlib import animation
import matplotlib
######################################################
fig = plt.figure()
ax = plt.axes()
a = plt.imread('background.jpg')
im = plt.imshow(a)
#######################################################
def randpair(n):
x,y=[],[]
for i in xrange(n):
x.append(np.random.randint(100,1900))
y.append(np.random.randint(100,900))
return x,y
def animate(i):
scat = ax.scatter(0,0,color='white')
points = np.random.randint(5,size=10)
for j in points:
xy = randpair(j)
x = xy[0]
y = xy[1]
print x,y
if len(x) > 0 :
scat.remove()
scat = ax.scatter(x,y,color='r',s=18)
plt.xticks([])
plt.yticks([])
return scat,ax, # ax returns the text to be updated and scat returns the scatterplot.
anim = animation.FuncAnimation(fig, animate, 49,interval=300, blit=True)
writer = animation.writers['ffmpeg']
anim.save('film_3.mp4')
#plt.show()
Upvotes: 2
Views: 4220
Reputation: 339610
In the code you already remove the last scatter before the loop is finished; so some scatter plots will be added and then removed immediately.
One can prevent this by collecting the scatters in a list, then removing the scatters in the list from the canvas using remove
and cleaning the list.
Apart from that, returning the complete ax
object is a little useless. So I would suggest to simply turn blitting off, since it will not matter for saving the animation.
Here is a complete code that worked for me:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation
fig = plt.figure()
ax = plt.axes()
scats = []
a = np.random.rand(8,18)
im = ax.imshow(a, cmap="YlGn", vmin=0, vmax=3, extent=[0,2000,0,1000])
plt.xticks([])
plt.yticks([])
def randpair(n):
x,y=[],[]
for i in xrange(n):
x.append(np.random.randint(100,1900))
y.append(np.random.randint(100,900))
return x,y
def animate(i):
global scats
# first remove all old scatters
for scat in scats:
scat.remove()
scats=[]
# now draw new scatters
points = np.random.randint(5,size=10)
for j in points:
x, y = randpair(j)
if len(x) > 0 :
scats.append(ax.scatter(x,y,color='r',s=18))
anim = matplotlib.animation.FuncAnimation(fig, animate, 50,
interval=1000, blit=False)
writer = matplotlib.animation.FFMpegWriter(fps=15,
codec="h264",
extra_args=["-preset", "veryslow","-crf","0"])
anim.save(__file__+".mp4", writer=writer)
plt.show()
Upvotes: 3