绘制在Python的串行数据如何暂停matplotlib的数字? [英] Plotting Serial data in Python how to pause matplotlib figure?
本文介绍了绘制在Python的串行数据如何暂停matplotlib的数字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
基本上我想暂停实时情节,我在这里有设置:
Basically I want to pause the live plot that I have setup here:
import serial
import numpy as np
from matplotlib import pyplot as plt
ser = serial.Serial('/dev/tty.usbmodemfa131', 9600)
#Setting up the animated plot
plt.ion() # set plot to animated
fig = plt.figure()
ydata = [0] * 100
ax1=plt.axes()
# make plot
line, = plt.plot(ydata)
plt.ylim([24,29])
#Starting data collection
while True:
rawData = ser.readline().rstrip()
x = len(rawData)
#print(floatData)
if len(rawData) <= 6:
try:
data = float(rawData)
if data <= 100:
ydata.append(data)
del ydata[0]
line.set_xdata(np.arange(len(ydata)))
line.set_ydata(ydata) # update the data
plt.draw() # update the plot
except ValueError:
print "Not a float"
我想暂停在图中的情节,但我无法弄清楚如何与这个数字在所有的数据是流工作。
I am wanting to pause the plot in the figure but I can't figure out how to work with the figure at all as the data is streaming.
推荐答案
因此,一个良好的解决问题的方法是使用一个线程来运行绘图窗口,必须通过主线程执行的控制。这可以像这样实现:
So a good solution to your problem would be to use a thread to run the plotting window and have control performed through the main thread. This could be implemented like so:
import serial
import numpy as np
from matplotlib import pyplot as plt
from threading import Thread,Event
import time
#A simple ring buffer to keep the plotting data in
class RingBuffer(object):
def __init__(self,size):
self.size = size
self._size = 2*size
self._buffer = np.zeros(self._size)
self._idx = 0
def insert(self,val):
idx = self._idx%self.size
self._buffer[idx] = val
self._buffer[idx+self.size] = val
self._idx+=1
if self._idx > self.size:
self._idx-=self.size
def get(self):
start_idx = (self._idx)%self.size
end_idx = start_idx+self.size
return self._buffer[start_idx:end_idx]
#A thread to handle plotting and reading data from the serial port
class Plotter(Thread):
def __init__(self,stream,stop,pause):
Thread.__init__(self)
self.stream = stream
self.fig = plt.figure()
self.ax = plt.axes()
self.size = 100
self.xdata = np.arange(self.size)
self.ydata = RingBuffer(self.size)
self.line, = self.ax.plot(self.ydata.get())
plt.ylim([24,29])
self.stop = stop
self.pause = pause
#The main loop of the thread, invoked with .start()
def run(self):
while not self.stop.is_set():
if self.pause.is_set():
continue
raw_data = self.stream.readline().rstrip()
if len(raw_data) <= 6:
try:
data = float(raw_data)
except ValueError:
print "Not a float"
else:
if data <= 100:
self.ydata.insert(data)
self.line.set_xdata(self.xdata)
self.line.set_ydata(self.ydata.get())
plt.draw()
#sleep statement to reduce processor load
time.sleep(1)
#this is implemented to facilitate use through something like Ipython easily
class Controller(object):
def __init__(self):
#These events control execution of the thread main loop
self.stop = Event()
self.pause = Event()
self.stream = serial.Serial('/dev/tty.usbmodemfa131', 9600)
self.plotter_thread = Plotter(self.stream,self.stop,self.pause)
self.plotter_thread.start()
def main():
con = Controller()
#Loop over terminal input
#possible commands are stop, pause and unpause
while True:
command = raw_input("cmd >>>")
if command == "stop":
con.stop.set()
con.plotter_thread.join()
break
elif command == "pause":
con.pause.set()
elif command == "unpause":
con.pause.clear()
else:
print "unrecognised command"
if __name__ == "__main__":
main()
这应该给你像一个命令行界面:
This should give you a command line interface like:
cmd >>>
凡下面的语句应控制绘图仪
Where any of the following statements should control the plotter
cmd >>>pause
cmd >>>unpause
cmd >>>stop
这篇关于绘制在Python的串行数据如何暂停matplotlib的数字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文