Matplotlib动画TclError:堆栈空间不足(无限循环?)

时间:2014-11-03 21:25:53

标签: python matplotlib

我试图实现在非确定性间隔上重绘的动画。我的想法是添加两个线程,一个用于打开图形,另一个用于处理从主线程推送的更新。

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

我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

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

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)