How to use FuncAnimation to display one scatter marker per frame
Asked Answered
C

2

9

I am trying to use the FuncAnimation of Matplotlib to animate the display of one dot per frame of animation.

# modules
#------------------------------------------------------------------------------
import numpy as np
import matplotlib.pyplot as py
from matplotlib import animation

py.close('all') # close all previous plots

# create a random line to plot
#------------------------------------------------------------------------------

x = np.random.rand(40)
y = np.random.rand(40)

py.figure(1)
py.scatter(x, y, s=60)
py.axis([0, 1, 0, 1])
py.show()

# animation of a scatter plot using x, y from above
#------------------------------------------------------------------------------

fig = py.figure(2)
ax = py.axes(xlim=(0, 1), ylim=(0, 1))
scat = ax.scatter([], [], s=60)

def init():
    scat.set_offsets([])
    return scat,

def animate(i):
    scat.set_offsets([x[:i], y[:i]])
    return scat,

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=len(x)+1, 
                               interval=200, blit=False, repeat=False)

Unfortunately, the final animated plot is not the same as original plot. The animated plot also flashes several dots during each frame of animation. Any suggestions on how to correctly animate a scatter plot using the animation package?

Colpin answered 12/11, 2014 at 17:0 Comment(0)
C
18

The only problem with your example is how you fill the new coordinates in the animate function. set_offsets expects a Nx2 ndarray and you provide a tuple of two 1d arrays.

So just use this:

def animate(i):
    data = np.hstack((x[:i,np.newaxis], y[:i, np.newaxis]))
    scat.set_offsets(data)
    return scat,

And to save the animation you might want to call:

anim.save('animation.mp4')
Complimentary answered 12/11, 2014 at 17:29 Comment(2)
That works great. Thank you for the help. I didn't realize the requirements of the set_offsets function.Colpin
My x and y values were a Pythonic list of numbers, thus scat.set_offsets(np.c_[x, y]) worked for me.Entourage
C
6

Disclaimer, I wrote a library to try and make this easy but using ArtistAnimation, called celluloid. You basically write your visualization code as normal and simply take pictures after each frame is drawn. Here's a complete example:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
from celluloid import Camera

fig = plt.figure()
camera = Camera(fig)

dots = 40
X, Y = np.random.rand(2, dots)
plt.xlim(X.min(), X.max())
plt.ylim(Y.min(), Y.max())
for x, y in zip(X, Y):
    plt.scatter(x, y)
    camera.snap()
anim = camera.animate(blit=True)
anim.save('dots.gif', writer='imagemagick')

enter image description here

Cipango answered 21/11, 2018 at 17:29 Comment(5)
Except that not using this library would save you three lines of code. So it seems of rather limited scope.Pallua
I'm not sure how you counted 3 lines, but I don't disagree with you. I wrote the library because I would spend at least an hour each time I would try to use FuncAnimation. For me it was more about saving time than lines of code :)Cipango
Sure just be aware that ArtistAnimation is pretty costly. A 2 minutes animation at 20 fps creates 2400 artists in memory, quite a lot, compared to a single artist needed for FuncAnimation. It's ok if you are aware of the implications, but maybe a new user would benefit more from understanding the differences between Func- and ArtistAnimation and how to use them, instead of using a blackbox tool that might cause trouble later on. I'm saying that also with respect to e.g. drawnow, which is meant to simplify things, yet causes problems for almost anyone not understanding what it does.Pallua
I agree with your points. I figured that it used more memory but I wasn't sure how to quantify it. I need to add in more disclaimers about those sorts of things. I need to think more about the beginner to advanced transition. This package probably shouldn't be used by someone looking to advance past a beginner user of matplotlib's animation api.Cipango
Holy crap this is incredible. It works with seaborn plots too. Thanks so much. Glad I found this post.Gladis

© 2022 - 2024 — McMap. All rights reserved.