我试图实现在非确定性间隔上重绘的动画。我的想法是添加两个线程,一个用于打开图形,另一个用于处理从主线程推送的更新。
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 :(得分: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)