Running FuncAnimation multiple times with different parameters in a for loop

前端 未结 1 577
孤城傲影
孤城傲影 2021-01-25 22:30

I\'m trying to run FuncAnimation multiple times with different parameters but every time it gets through the first run of the simulation, the entire program stops. It won\'t eve

相关标签:
1条回答
  • 2021-01-25 23:15

    Closing figure at the end of animation

    You could in principle create a new figure inside the loop. Then closing one figure will allow the program to continue and create the next figure and show it. The figure can be closed automatically at the end of the animation.

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.animation import FuncAnimation
    
    def createanimatedfig(omega):
        fig, ax = plt.subplots()
        ax.axis([0,2*np.pi,-1,1])
        ax.set_title(u"animated sin(${:g}\cdot t$)".format(omega))
        t = np.linspace(0,2*np.pi)
        x = np.sin(omega*t)
        line, = ax.plot([],[], lw=3)
        ani = FuncAnimation(fig,animate, len(t), repeat=False,
                            fargs=(t,x,line, len(t)), interval=20)
        plt.show()
    
        
    def animate(i, t,x, line, maxsteps):
        line.set_data(t[:i],x[:i])
        if i >= maxsteps-1:
            plt.close(line.axes.figure)
            
    
    omegas= [1,2,4,5]
    for omega in omegas:
        createanimatedfig(omega)
    

    Note that the above will produce an error when run with the TkAgg backend. In this case you need to postpone the figure closing to after the animation has truely stopped. To this end a timer may be used.

    def animate(i, t,x, line, maxsteps):
        line.set_data(t[:i],x[:i])
        if i >= maxsteps-1:
            timer = line.axes.figure.canvas.new_timer(interval=10)
            timer.single_shot = True
            timer.add_callback(lambda : plt.close(line.axes.figure))
            timer.start()
    

    Run animations within single figure

    Alternatively you may use a single figure to show all animations one after the other. This would require to have some control over when which animation stops and so the use of a class to handle the steps is useful.

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.animation import FuncAnimation
    
    class Ani():
        def __init__(self,omegas, nsteps, line):
            self.nsteps = nsteps
            self.omegas = omegas
            self.line=line
            self.step = 0
            self.i = 0
        
        def getdata(self,j):
            t = np.arange(0,j)/float(self.nsteps)*2*np.pi
            x = np.sin(self.omegas[self.step]*t)
            return t,x
            
        def gen(self):
            for i in range(len(self.omegas)):
                tit = u"animated sin(${:g}\cdot t$)".format(self.omegas[self.step])
                self.line.axes.set_title(tit)
                for j in range(self.nsteps):
                    yield j
                self.step += 1
                
        def animate(self,j):
            x,y = self.getdata(j)
            self.line.set_data(x,y)
           
    fig, ax = plt.subplots()
    ax.axis([0,2*np.pi,-1,1])
    title = ax.set_title(u"")
    line, = ax.plot([],[], lw=3)
    
    omegas= [1,2,4,5]
    a = Ani(omegas,50,line)
    ani = FuncAnimation(fig,a.animate, a.gen, repeat=False, interval=60)
    plt.show()
    
    0 讨论(0)
提交回复
热议问题