Search code examples
pythonanimationmatplotlibrestart

Python matplotlib Animation repeat


I made an animation using matplotlib.animation and FuncAnimation. I know that I can set repeat to True/False to replay the animation, but is there also a way to replay the animation after the FuncAnimation has returned?

anim = FuncAnimation(fig, update, frames= range(0,nr_samples_for_display), blit=USE_BLITTING, interval=5,repeat=False)

plt.show()
playvideo = messagebox.askyesno("What to do next?", "Play Video again?")

Can I use the anim object to replay the animation or do another plt.show()?

Thanks in advance for your answer with kind regards, Gerard


Solution

  • After the figure has been shown once, it cannot be shown a second time using plt.show().

    An option is to recreate the figure to show that new figure again.

    createfig():
        fig = ...
        # plot something
        def update(i):
            #animate
        anim = FuncAnimation(fig, update, ...)
    
    createfig()
    plt.show()
    
    while messagebox.askyesno(..):
        createfig()
        plt.show()
    

    Probably a better option to restart the animation is to integrate the user dialog into the GUI. That would mean that at the end of the animation you ask the user if he wants to replay the animation without actually closing the matplotlib window first. To reset the animation to the start, you'd use

    ani.frame_seq = ani.new_frame_seq() 
    

    Example:

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import numpy as np
    import Tkinter
    import tkMessageBox
    
    y = np.cumsum(np.random.normal(size=18))
    x = np.arange(len(y))
    
    fig, ax=plt.subplots()
    
    line, = ax.plot([],[], color="crimson")
    
    def update(i):
        line.set_data(x[:i],y[:i])
        ax.set_title("Frame {}".format(i))
        ax.relim()
        ax.autoscale_view()
        if i == len(x)-1:
            restart()
    
    ani = animation.FuncAnimation(fig,update, frames=len(x), repeat=False)
    
    def restart():
        root = Tkinter.Tk()
        root.withdraw()
        result = tkMessageBox.askyesno("Restart", "Do you want to restart animation?")
        if result:
            ani.frame_seq = ani.new_frame_seq() 
            ani.event_source.start()
        else:
            plt.close()
    
    plt.show()