stop / start / pause in python matplotlib animation
Question:
I’m using FuncAnimation in matplotlib’s animation module for some basic animation. This function perpetually loops through the animation. Is there a way by which I can pause and restart the animation by, say, mouse clicks?
Answers:
Here is a FuncAnimation example which I modified to pause on mouse clicks.
Since the animation is driven by a generator function, simData
, when the global variable pause
is True, yielding the same data makes the animation appear paused.
The value of paused
is toggled by setting up an event callback:
def onClick(event):
global pause
pause ^= True
fig.canvas.mpl_connect('button_press_event', onClick)
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
pause = False
def simData():
t_max = 10.0
dt = 0.05
x = 0.0
t = 0.0
while t < t_max:
if not pause:
x = np.sin(np.pi*t)
t = t + dt
yield x, t
def onClick(event):
global pause
pause ^= True
def simPoints(simData):
x, t = simData[0], simData[1]
time_text.set_text(time_template%(t))
line.set_data(t, x)
return line, time_text
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([], [], 'bo', ms=10)
ax.set_ylim(-1, 1)
ax.set_xlim(0, 10)
time_template = 'Time = %.1f s'
time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)
fig.canvas.mpl_connect('button_press_event', onClick)
ani = animation.FuncAnimation(fig, simPoints, simData, blit=False, interval=10,
repeat=True)
fig.show()
This works…
anim = animation.FuncAnimation(fig, animfunc[,..other args])
#pause
anim.event_source.stop()
#unpause
anim.event_source.start()
Combining both the answers from @fred and @unutbu here, we can add an onClick function after creating the animation:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def run_animation():
anim_running = True
def onClick(event):
nonlocal anim_running
if anim_running:
anim.event_source.stop()
anim_running = False
else:
anim.event_source.start()
anim_running = True
def animFunc( ...args... ):
# Animation update function here
fig.canvas.mpl_connect('button_press_event', onClick)
anim = animation.FuncAnimation(fig, animFunc[,...other args])
run_animation()
Now we can simply stop or start the animation with clicks.
I landed on this page trying to implement the same functionality, pausing matplotlibs animation. The other answers are great, but in addition I wanted to be able to manually loop through the frames using the arrow keys. For anyone looking for the same functionality, here’s my implementation:
import matplotlib.pyplot as plt
import matplotlib.animation as ani
fig, ax = plt.subplots()
txt = fig.text(0.5,0.5,'0')
def update_time():
t = 0
t_max = 10
while t<t_max:
t += anim.direction
yield t
def update_plot(t):
txt.set_text('%s'%t)
return txt
def on_press(event):
if event.key.isspace():
if anim.running:
anim.event_source.stop()
else:
anim.event_source.start()
anim.running ^= True
elif event.key == 'left':
anim.direction = -1
elif event.key == 'right':
anim.direction = +1
# Manually update the plot
if event.key in ['left','right']:
t = anim.frame_seq.next()
update_plot(t)
plt.draw()
fig.canvas.mpl_connect('key_press_event', on_press)
anim = ani.FuncAnimation(fig, update_plot, frames=update_time,
interval=1000, repeat=True)
anim.running = True
anim.direction = +1
plt.show()
Some notes:
- To be able to modify the values of
running
and direction
, I assigned them to anim
. It avoids using nonlocal (not avaible in Python2.7) or global (not desirable since I’m running this code within another function). Not sure whether this is good practice, but I found it quite elegant.
- For the manual update, I’m accessing
anim
‘s generator object that FuncAnimation uses to update the plot. This ensures that when I resume the animation, it starts from the active frame rather than from where it was originally paused.
Since there are quite a few comments on different answers asking for documented feature, I dug deeper based on fred’s answer. It seems to work, but since matplotlib 3.4.0 there are new functions to pause and resume plotting: pause()
and resume()
. They call event_source.stop()
and start()
internally, but they also pause animation altogether, which may reduce the hardware strain.
They can be called on any matplotlib.animation.Animation
object, including FuncAnimation
subclass.
I’m using FuncAnimation in matplotlib’s animation module for some basic animation. This function perpetually loops through the animation. Is there a way by which I can pause and restart the animation by, say, mouse clicks?
Here is a FuncAnimation example which I modified to pause on mouse clicks.
Since the animation is driven by a generator function, simData
, when the global variable pause
is True, yielding the same data makes the animation appear paused.
The value of paused
is toggled by setting up an event callback:
def onClick(event):
global pause
pause ^= True
fig.canvas.mpl_connect('button_press_event', onClick)
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
pause = False
def simData():
t_max = 10.0
dt = 0.05
x = 0.0
t = 0.0
while t < t_max:
if not pause:
x = np.sin(np.pi*t)
t = t + dt
yield x, t
def onClick(event):
global pause
pause ^= True
def simPoints(simData):
x, t = simData[0], simData[1]
time_text.set_text(time_template%(t))
line.set_data(t, x)
return line, time_text
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot([], [], 'bo', ms=10)
ax.set_ylim(-1, 1)
ax.set_xlim(0, 10)
time_template = 'Time = %.1f s'
time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)
fig.canvas.mpl_connect('button_press_event', onClick)
ani = animation.FuncAnimation(fig, simPoints, simData, blit=False, interval=10,
repeat=True)
fig.show()
This works…
anim = animation.FuncAnimation(fig, animfunc[,..other args])
#pause
anim.event_source.stop()
#unpause
anim.event_source.start()
Combining both the answers from @fred and @unutbu here, we can add an onClick function after creating the animation:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def run_animation():
anim_running = True
def onClick(event):
nonlocal anim_running
if anim_running:
anim.event_source.stop()
anim_running = False
else:
anim.event_source.start()
anim_running = True
def animFunc( ...args... ):
# Animation update function here
fig.canvas.mpl_connect('button_press_event', onClick)
anim = animation.FuncAnimation(fig, animFunc[,...other args])
run_animation()
Now we can simply stop or start the animation with clicks.
I landed on this page trying to implement the same functionality, pausing matplotlibs animation. The other answers are great, but in addition I wanted to be able to manually loop through the frames using the arrow keys. For anyone looking for the same functionality, here’s my implementation:
import matplotlib.pyplot as plt
import matplotlib.animation as ani
fig, ax = plt.subplots()
txt = fig.text(0.5,0.5,'0')
def update_time():
t = 0
t_max = 10
while t<t_max:
t += anim.direction
yield t
def update_plot(t):
txt.set_text('%s'%t)
return txt
def on_press(event):
if event.key.isspace():
if anim.running:
anim.event_source.stop()
else:
anim.event_source.start()
anim.running ^= True
elif event.key == 'left':
anim.direction = -1
elif event.key == 'right':
anim.direction = +1
# Manually update the plot
if event.key in ['left','right']:
t = anim.frame_seq.next()
update_plot(t)
plt.draw()
fig.canvas.mpl_connect('key_press_event', on_press)
anim = ani.FuncAnimation(fig, update_plot, frames=update_time,
interval=1000, repeat=True)
anim.running = True
anim.direction = +1
plt.show()
Some notes:
- To be able to modify the values of
running
anddirection
, I assigned them toanim
. It avoids using nonlocal (not avaible in Python2.7) or global (not desirable since I’m running this code within another function). Not sure whether this is good practice, but I found it quite elegant. - For the manual update, I’m accessing
anim
‘s generator object that FuncAnimation uses to update the plot. This ensures that when I resume the animation, it starts from the active frame rather than from where it was originally paused.
Since there are quite a few comments on different answers asking for documented feature, I dug deeper based on fred’s answer. It seems to work, but since matplotlib 3.4.0 there are new functions to pause and resume plotting: pause()
and resume()
. They call event_source.stop()
and start()
internally, but they also pause animation altogether, which may reduce the hardware strain.
They can be called on any matplotlib.animation.Animation
object, including FuncAnimation
subclass.