2017-01-09 176 views
2

我的问题是恢复的matplotlib ArtistsAnimation如何暂停/恢复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

回答

1

尽管看起来在这种情况下FuncAnimation可能比ArtistAnimation更适合,但两者都可以是 以同样的方式停止/启动。看到这个问题stop/start/pause in python matplotlib animation

重点是'私人'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() 
+0

谢谢。它的工作原理:-D –