Reputation: 430
I am trying to use matplotlib
's FuncAnimation
to make an animated video. Each frame is just a boolean n
x n
array visualised as white/black squares. I can do this successfully by defining all the arrays in advance and then going through them one by one. This uses code similar to matplotlib
's example.
My items are rather large and I want to run the simulation for a long time. I thus don't want to create the entire list of arrays then go through them one by one. Instead, I want to define the animate
function to do each step. Let me explain with a minimal non-working example. My actual example includes far larger arrays!
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def create_video(n):
global X
X = np.random.binomial(1, 0.3, size = (n,n))
fig = plt.figure()
im = plt.imshow(X, cmap = plt.cm.gray)
def animate(t):
global X
X = np.roll(X, +1, axis = 0)
im.set_array(X)
anim = FuncAnimation(
fig,
animate,
frames = 100,
interval = 1000 / 30,
blit = True
)
return anim
anim = create_video(10)
This initialises some random 10
x 10
set of 0
/1
s then just 'rolls' it at each step. I get an error.
RuntimeError: The animation function must return a sequence of Artist objects.
If I remove the return anim
, replacing it with pass
, and replacing anim = create_video(10)
with create_video(10)
, then I get a warning.
UserWarning: Animation was deleted without rendering anything. This is most likely unintended. To prevent deletion, assign the Animation to a variable that exists for as long as you need the Animation.
Clearly, I don't understand well enough FuncAnimation
. What I want to happen is for the function animate
to update the array X
, by 'rolling' it one step, as well as doing im.set_array(X)
.
Upvotes: 2
Views: 18549
Reputation: 12496
As explained in this answer:
As the error suggests, and as can be seen e.g. in the
simple_animation
example, but also from theFuncAnimation
documentation, theinit_func
as well as the updatingfunc
are supposed to return an iterable of artists to animate.The documentation does not say that this is actually only needed when using
blit=True
, but since you are using blitting here, it is definitely needed.
So you have two ways:
add
return im,
to animate
function
set blit = False
in FuncAnimation
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def create_video(n):
global X
X = np.random.binomial(1, 0.3, size = (n, n))
fig = plt.figure()
im = plt.imshow(X, cmap = plt.cm.gray)
def animate(t):
global X
X = np.roll(X, +1, axis = 0)
im.set_array(X)
return im,
anim = FuncAnimation(
fig,
animate,
frames = 100,
interval = 1000/30,
blit = True
)
plt.show()
return anim
anim = create_video(10)
Upvotes: 2