我的问题是恢复matplotlib ArtistsAnimation

我的代码是:

def PlotFields(self):
    fig = plt.figure()
    axess = []
    for i in range(0,self.number_fields):
                  axess.append(fig.add_subplot((self.number_fields+1)//2,2,i+1))

    #find min and max in time
    mins = {}
    maxs = {}
    for key,field in self.fields.items():
        mins[key] = field[:,:,:,self.z_slice].min()
        maxs[key] = field[:,:,:,self.z_slice].max()
        if mins[key] == maxs[key]:#this fixes bug in imshow when vmin = vmax
            mins[key] = mins[key]-0.1
            maxs[key] = maxs[key]+0.1


    #set up list of images for animation
    movie = []
    images = []
    nt = self.fields[list(self.fields)[0]].shape[0] #number of time slices
    print('time slices = {}'.format(nt))
    first = 1
    for time in range(0,nt):

        images.clear()
        i = 0
        for key,field in self.fields.items():
            if self.cut == 'xy':
                images.append(axess[i].pcolor(field[time,:,:,self.z_slice].T, vmin = mins[key], vmax = maxs[key]))
                axess[i].set_xlabel('x')
                axess[i].set_ylabel('y')
            elif self.cut == 'xz':
                images.append(axess[i].pcolor(field[time,:,:,self.y_slice].T, vmin = mins[key], vmax = maxs[key]))
                axess[i].set_xlabel('x')
                axess[i].set_ylabel('z')
            else:
                print('unknown cut --- exiting !!')
                quit()
            axess[i].set_title(key)
            i = i + 1
        if first == 1:
            for i in range(0,self.number_fields):
                fig.colorbar(images[i], ax = axess[i])
                first = 0
    #    time_title.set_text('t={}'.format(t_array[time]))
        time_title = axess[0].annotate('t={}'.format(self.t_array[time]),xy = (0.1,1.2))
        collected_list = [*images] #apparently a bug in matplotlib forces this solution
        collected_list.append(time_title)
        movie.append(collected_list)

    #for i in range(0,number_fields):
    #    fig.colorbar(images[i], ax = axess[i])


    #run animation
    self.ani = anim.ArtistAnimation(fig, movie, interval=500, blit = False, repeat_delay = 1000)
    fig.canvas.mpl_connect('button_press_event', self.onClick)
    if self.save_movie == True:
        try:
            ani.save('xy_film.mp4')
            #ani.save('film.mp4',writer = FFwriter, fps=30, extra_args=['-vcodec', 'libx264'])
        except Exception:
            print("Save failed: Check ffmpeg path")
    plt.show()


def onClick(self, event):
    self.pause == True
    if self.pause == False:
        self.ani._stop()
        self.pause = True
        print('self pause = False')
    else:
        self.ani._start()
        self.pause = False
    #pause ^= True
        print('self pause = True')


动画停止onClick,但是在第二次点击时引发以下错误,该第二次点击应继续播放动画(如果可能):

  File "PlotFieldsFieldAligned.py", line 149, in onClick
self.ani._start()
File "/home/yolen/scicomp/anaconda3/lib/python3.5/site-    packages/matplotlib/animation.py", line 665, in _start
self.event_source.add_callback(self._step)
AttributeError: 'NoneType' object has no attribute 'add_callback'


任何帮助表示赞赏:-D

最佳答案

尽管在这种情况下,似乎FuncAnimationArtistAnimation更适合,但两者都可以
停止/开始的方式相同。参见问题stop / start / pause in python matplotlib animation

要点是,'private'ArtistAnimation._start()函数没有按照您认为的那样做。因此,使用ArtistAnimation.event_source.stop()ArtistAnimation.event_source.start()函数是明智的。

下面是一个最小的可运行示例,显示了如何通过使用鼠标按钮单击来启动/停止ArtistAnimation

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

class SomeClass():

    def __init__(self):
        self.pause = False

        self.fig, ax = plt.subplots()
        ax.set_aspect("equal")

        self.movie = []
        nt = 10
        X,Y = np.meshgrid(np.arange(16), np.arange(16))

        for t in range(nt):
            data = np.sin((X+t*1)/3.)**2+ 1.5*np.cos((Y+t*1)/3.)**2
            pc = ax.pcolor(data)
            self.movie.append([pc])

        self.ani = animation.ArtistAnimation(self.fig, self.movie, interval=100)
        self.fig.canvas.mpl_connect('button_press_event', self.onClick)
        plt.show()

    def onClick(self, event):
        if self.pause:
            self.ani.event_source.stop()
        else:
            self.ani.event_source.start()
        self.pause ^= True

a = SomeClass()

07-24 21:13