2014-11-03 73 views
0

我试图实现一个在非确定性区间上重绘的动画。我的想法是添加两个线程,一个打开图形,另一个线程处理从主线程推送的更新。Matplotlib动画TclError:堆栈空间不足(无限循环?)

import threading 
import matplotlib.pyplot as plt 
from Queue import Queue 
import numpy 
import time 


class JobPlotter(object): 
    def __init__(self, log=None, **kwargs): 
     self.axes = None 
     self.lines = None 
     self.queue = Queue(maxsize=1) 
     self.fig = None 

    def update(self, data): 
     print 'Update' 
     self.queue.put(data) 

    def _draw_plot(self, labels, data): 
     self.fig = plt.figure() 
     self.axes = [] 

     plt.ion() 

     for idx in range(len(labels)): 
      ax = self.fig.add_subplot(len(labels), 1, idx) 
      ax.plot(range(len(data[idx])), data[idx], label=labels[idx]) 

      self.axes.append(ax) 


     print 'show' 
     self.fig.canvas.draw() 

    def setup(self): 
     print 'Setup: Start' 
     data = self.queue.get() 

     print 'Setup: Got Data' 

     labels = data[0] 
     data = numpy.array(data[1:]).T 

     data_plot = threading.Thread(None, self._draw_plot, 'PlotDraw', (labels, data)) 
     data_plot.daemon = True 
     data_plot.start() 

     print 'Setup: Done' 

     while True: 
      self.loop() 

    def loop(self): 
     data = self.queue.get() 

     print 'Loop: Got Data' 

     labels = data[0] 
     data = numpy.array(data[1:]).T 

     for idx in range(len(labels)): 
      self.axes[idx].plot(range(len(data[idx])), data[idx], label=labels[idx]) 
     self.fig.canvas.draw() 

     print 'Loop: Done' 



if __name__ == '__main__': 
    foo = JobPlotter() 
    data_plot = threading.Thread(None, foo.setup, 'PlotDraw',()) 
    data_plot.daemon = True 
    data_plot.start() 

    data = [['test'], [1], [2], [3], [4], [5], [6]] 
    while True: 
     temp = [[(x[0]*3) % 8] for x in data[1:]] 
     data = [data[0]] 
     data.extend(temp) 

     foo.update(data) 

     time.sleep(5) 

代码运行,但死亡的第二呼叫的抽奖请求,以更新:

Setup: StartUpdate 

Setup: Got Data 
Setup: Done 
show 
Update 
Loop: Got Data 
Exception in thread PlotDraw: 
Traceback (most recent call last): 
    File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner 
    self.run() 
    File "C:\Python27\lib\threading.py", line 763, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "D:/src/EE_EVT_Scripts/Sensors/PrintWeld/aniator.py", line 50, in setup 
    self.loop() 
    File "D:/src/EE_EVT_Scripts/Sensors/PrintWeld/aniator.py", line 62, in loop 
    plt.draw() 
    File "C:\Python27\lib\site-packages\matplotlib\pyplot.py", line 555, in draw 
    get_current_fig_manager().canvas.draw() 
    File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 349, in draw 
    tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2) 
    File "C:\Python27\lib\site-packages\matplotlib\backends\tkagg.py", line 20, in blit 
    tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array)) 
TclError: out of stack space (infinite loop?) 

Update 
Update 

有什么我错过了什么?

回答

0

我认为这个问题有两个问题。我需要将pyplt置于交互模式,然后才能使用plt.ion()创建图形,然后用draw()替换show()的调用。这个电话会在交互模式下打开数字。

import threading 
import matplotlib.pyplot as plt 
from Queue import Queue 
import numpy 
import time 


class JobPlotter(object): 
    def __init__(self, log=None, **kwargs): 
     self.axes = None 
     self.lines = None 
     self.queue = Queue(maxsize=1) 
     self.fig = None 

    def update(self, data): 
     print 'Update' 
     self.queue.put(data) 

    def _draw_plot(self, labels, data): 
     plt.ion() 
     self.fig = plt.figure() 
     self.axes = [] 

     for idx in range(len(labels)): 
      ax = self.fig.add_subplot(len(labels), 1, idx) 
      ax.plot(range(len(data[idx])), data[idx], label=labels[idx]) 

      self.axes.append(ax) 


     print 'show' 
     self.fig.canvas.draw() 

    def setup(self): 
     print 'Setup: Start' 
     data = self.queue.get() 

     print 'Setup: Got Data' 

     labels = data[0] 
     data = numpy.array(data[1:]).T 

     self._draw_plot(labels,data) 
     # data_plot = threading.Thread(None, self._draw_plot, 'PlotDraw', (labels, data)) 
     # data_plot.daemon = True 
     # data_plot.start() 

     print 'Setup: Done' 

     while True: 
      self.loop() 

    def loop(self): 
     data = self.queue.get() 

     print 'Loop: Got Data' 

     labels = data[0] 
     data = numpy.array(data[1:]).T 

     for idx in range(len(labels)): 
      self.axes[idx].plot(range(len(data[idx])), data[idx], label=labels[idx]) 
     self.fig.canvas.draw() 

     print 'Loop: Done' 



if __name__ == '__main__': 
    foo = JobPlotter() 
    data_plot = threading.Thread(None, foo.setup, 'PlotDraw',()) 
    data_plot.daemon = True 
    data_plot.start() 

    data = [['test','bar'], [1,2], [2,6], [3,7], [4,8], [5,8], [6,5]] 
    while True: 
     # temp = [[(i*3) % 16] for x in data[1:] for i in x] 
     # data = [data[0]] 
     # data.extend(temp) 

     foo.update(data) 

     time.sleep(5)