我只是将我的脚趾浸入Python并在此处获得帮助以获得实时更新Matplotlib图形以便为我工作。该程序使用动画从动态增长的CSV文件中提取数据,其数据如下所示:
TimeStamp, ReadCount, Antenna, Protocol, RSSI, EPC, Sensor
09/28/2016 17:34:28.967, 5686, 2, GEN2, -25, E036115348A908CB, 23.16,0.00,0.00, (Infinity%),
09/28/2016 17:34:29.716, 5687, 2, GEN2, -32, E036115348A908CB, (Infinity%),
09/28/2016 17:34:31.155, 5689, 2, GEN2, -27, E036115348A908CB, 22.74,3.38, (Infinity%),
09/28/2016 17:34:32.351, 5692, 2, GEN2, -25, E036115348A908CB, 22.95,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:32.895, 5695, 2, GEN2, -23, E036115348A908CB, 22.95,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:33.397, 5698, 2, GEN2, -21, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:33.946, 5699, 2, GEN2, -23, E036115348A908CB, 23.57,0.00,3.38, (Infinity%),
09/28/2016 17:34:34.912, 5702, 2, GEN2, -27, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:35.394, 5705, 2, GEN2, -25, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:35.988, 5707, 2, GEN2, -23, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:36.489, 5710, 2, GEN2, -21, E036115348A908CB, 23.99,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:37.269, 5712, 2, GEN2, -23, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:37.796, 5715, 2, GEN2, -18, E036115348A908CB, 23.78,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:38.296, 5718, 2, GEN2, -7, E036115348A908CB, 22.32,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:38.826, 5721, 2, GEN2, -7, E036115348A908CB, 23.57,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:39.320, 5724, 2, GEN2, -30, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%),
09/28/2016 17:34:39.870, 5727, 2, GEN2, -9, E036115348A908CB, 23.36,0.00,0.00,3.38, (Infinity%),
此数据来自传感器,我希望能够在显示器上随此图拉出/显示此数据包含的其他一些值。该图的代码如下所示:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from datetime import datetime, timedelta
import collections
import csv
offset = 16
slope = -.2081
def plot(ax, data, colour, width):
if data:
last_dt = data[0][0]
gap = timedelta(seconds=10)
x = []
y = []
# Plot groups of data not more than 60 seconds apart
for dt, ten in data:
if dt <= last_dt + gap:
x.append(dt)
y.append(ten)
else:
ax.plot(matplotlib.dates.date2num(x), y, colour, linewidth=width)
x = [dt]
y = [ten]
last_dt = dt
ax.plot(matplotlib.dates.date2num(x), y, colour, linewidth=width)
def animate(i, fig, ax):
# Read in the CSV file
data = collections.defaultdict(list)
fields = ["TimeStamp", "ReadCount", "Antenna", "Protocol", "RSSI", "EPC", "Temp", "Ten", "Powr", "Unpowr", "Inf"]
with open('SensorLogFile.csv') as f_input:
csv_input = csv.DictReader(f_input, skipinitialspace=True, fieldnames=fields)
header = next(csv_input)
# Separate the rows based on the Antenna field
for row in csv_input:
try:
data[row['Antenna']].append(
[datetime.strptime(row['TimeStamp'], '%m/%d/%Y %H:%M:%S.%f'),
int(float(row['Ten']) * float(slope) + float(offset))])
except:
pass
# Drop any data points more than 1.5 mins older than the last entry
latest_dt = data[row['Antenna']][-1][0] # Last entry
not_before = latest_dt - timedelta(minutes=.25)
for antenna, entries in data.items():
data[antenna] = [[dt, count] for dt, count in entries if dt >= not_before]
# Redraw existing axis
ax.clear()
ax.spines['bottom'].set_color("#5998ff")
ax.spines['top'].set_color("#5998ff")
ax.spines['left'].set_color("#5998ff")
ax.spines['right'].set_color("#5998ff")
hfmt = matplotlib.dates.DateFormatter('%m/%d/%Y\n%I:%M:%S %p')
ax.xaxis.set_major_formatter(hfmt)
fig.autofmt_xdate()
plot(ax, data['1'], 'c', 6) # Antenna 1
plot(ax, data['2'], 'r', 6) # Antenna 2
plot(ax, data['3'], 'y', 6) # Antenna 3
ax.grid(True, color='w')
plt.ylabel('Tension (lb)', color='w', fontsize=20)
plt.title('Spiral 1 Tension', color='w', fontsize=26)
ax.tick_params(axis='y', colors='w')
ax.tick_params(axis='x', colors='w')
# ax.set_ylim([21,28])
fig = plt.figure(facecolor='#07000d')
ax = fig.add_subplot(111, axisbg='#07000d')
ani = animation.FuncAnimation(fig, animate, fargs=(fig, ax), interval=250)
plt.show()
我希望能够将图形放在图形的下方和图形下方的开放区域(图形的整个宽度),我可以在其中放置以下内容(可能有一个框用于每个部分的数据):
我已经研究过使用Tkinter并尝试关注sentdex&#39; s video here
但未能让它发挥作用。
我正处于紧张状态,不能再独自奋斗 - 需要专业人士的帮助。任何人都可以给我一些关于如何制作像我正在寻找的显示器的方向/指导吗?
答案 0 :(得分:1)
为了帮助您入门,可能首先要回答一些问题。
FuncAnimation
可能是一个坏主意。 答案:是的,实时 说到你的数据,我发现了一个问题。看着那些线
E036115348A908CB, 22.74,3.38, (Infinity%),
E036115348A908CB, 22.95,0.00,0.00,3.38, (Infinity%),
似乎有数据不完整的情况?!这是可以避免的吗?
情节的时间轴怎么样?首先,您#Drop any data points more than 1.5 mins older than the last entry
然后是#Plot groups of data not more than 60 seconds apart
,然后丢弃任何早于gap = timedelta(seconds=10)
的数据。你能告诉我们什么&#34;数据组&#34;意味着时间轴应该是多长时间?
您如何计算number of cycles
?
<小时/> 结果(目前为止): 我们走了,这是matplotlib可以轻松搞定的。
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from datetime import datetime, timedelta
import collections
import csv
class Anim():
"""
This class provides a "live" plot of the contents of a log file in csv format.
The class structure makes it easy to separate the plot generation from the
frequent updating of the plot.
The code is based on a question at stackoverflow
http://stackoverflow.com/questions/39858501/python-data-display-with-graph
"""
def __init__(self):
self.offset = 16.
self.slope = -.2081
self.i = 0
self.axisbg = '#07000d'
self.fig = plt.figure(figsize=(15,8), facecolor=self.axisbg)
self.ax = self.fig.add_subplot(111, axisbg=self.axisbg)
[self.ax.spines[wh].set_color("#5998ff") for wh in ['bottom', 'top', 'left', 'right']]
self.hfmt = matplotlib.dates.DateFormatter('%m/%d/%Y\n%I:%M:%S %p')
self.ax.xaxis.set_major_formatter(self.hfmt)
self.fig.autofmt_xdate()
#self.framenumber = plt.figtext(0.9, .9, "0", color='w')
self.ax.grid(True, color='w')
plt.ylabel('Tension (lb)', color='w', fontsize=20)
plt.title('Spiral 1 Tension', color='w', fontsize=26)
self.ax.tick_params(axis='y', colors='w')
self.ax.tick_params(axis='x', colors='w')
initialx = [self.stime("09/28/2016 17:34:28.967"),self.stime("09/28/2016 17:34:29.716") ]
initialy = [0,0 ]
self.line1, = self.ax.plot(matplotlib.dates.date2num(initialx), initialy, color="c", linewidth=6)
self.line2, = self.ax.plot(matplotlib.dates.date2num(initialx), initialy, color="r", linewidth=6)
self.line3, = self.ax.plot(matplotlib.dates.date2num(initialx), initialy, color="y", linewidth=6)
plt.subplots_adjust(left=0.1, bottom=0.28, right=0.9, top=0.9, wspace=0, hspace=0)
self.ax_temp = plt.axes([0.1, 0.08, 0.2, 0.06], axisbg=self.axisbg)
self.ax_time = plt.axes([0.2, 0.08, 0.2, 0.06], axisbg=self.axisbg)
self.ax_overdrive = plt.axes([0.4, 0.08, 0.2, 0.06], axisbg=self.axisbg)
self.ax_cycles = plt.axes([0.5, 0.08, 0.2, 0.06], axisbg=self.axisbg)
self.ax_image = plt.axes([0.75, 0.03, 0.3, 0.2], axisbg=self.axisbg)
self.tx_temp = self.ax_temp.text(0,0, "Temp", color="w", transform=self.ax_temp.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg})
self.tx_time = self.ax_time.text(0,0, "Time", color="w", transform=self.ax_time.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg})
self.tx_overdrive = self.ax_overdrive.text(0,0, "Overdrive", color="w", transform=self.ax_overdrive.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg})
self.tx_cycles = self.ax_cycles.text(0,0, "Cyles", color="w", transform=self.ax_cycles.transAxes, bbox={"pad" : 10, "ec" : "w", "fc" : self.axisbg})
self.ax_image.imshow(mpimg.imread('mmbRy.jpg'))
self.ax_image.tick_params(axis='x',which='both',bottom='off', top='off',labelbottom='off')
self.ax_image.tick_params(axis='y',which='both',left='off', right='off',labelleft='off')
[self.ax_image.spines[wh].set_color("#5998ff") for wh in ['bottom', 'top', 'left', 'right']]
self.timer = self.fig.canvas.new_timer(interval=250, callbacks=[(self.animate, [], {})])
self.timer.start()
plt.show()
def plot(self, data, line):
if data:
last_dt = data[0][0]
gap = timedelta(seconds=10)
x = []
y = []
# Plot groups of data not more than 60 seconds apart
for dt, ten in data:
if dt <= last_dt + gap:
x.append(dt)
y.append(ten)
else:
line.set_data(matplotlib.dates.date2num(x), y)
#ax.plot(, colour, linewidth=width)
x = [dt]
y = [ten]
last_dt = dt
line.set_data(matplotlib.dates.date2num(x), y)
def animate(self):
self.i +=1 #counting the number of frames
# Read in the CSV file
data = collections.defaultdict(list)
fields = ["TimeStamp", "ReadCount", "Antenna", "Protocol", "RSSI", "EPC", "Temp", "Ten", "Powr", "Unpowr", "Inf"]
temp = ""
# the complete file is read in, which might be a problem once the file gets very large
with open('SensorLogFile.csv') as f_input:
csv_input = csv.DictReader(f_input, skipinitialspace=True, fieldnames=fields)
header = next(csv_input)
# Separate the rows based on the Antenna field
for row in csv_input:
try:
data[row['Antenna']].append([self.stime(row['TimeStamp']), self.rten(row['Ten']) ])
temp= row['Temp']
except:
pass
# Drop any data points more than 1.5 mins older than the last entry
latest_dt = data[row['Antenna']][-1][0] # Last entry
not_before = latest_dt - timedelta(minutes=.25)
for antenna, entries in data.items():
data[antenna] = [[dt, count] for dt, count in entries if dt >= not_before]
self.plot(data['1'], self.line1) # Antenna 1
self.plot(data['2'], self.line2) # Antenna 2
self.plot(data['3'], self.line3) # Antenna 3
#Filling the text boxes
self.tx_temp.set_text(u"Temperature\n{temp:.2f} °F".format(temp=self.deg2F(temp)))
self.tx_time.set_text("Time\n{time}".format(time=datetime.now().time()) )
self.tx_overdrive.set_text("Overdrive\nfill later")
#Todo: how do you calculate this?
self.tx_cycles.set_text("Cyles\n{cyles}".format(cyles=self.i))
#Todo: setting the limits correctly, depending on the user's need
self.ax.set_ylim([0,16])
self.ax.set_xlim([matplotlib.dates.date2num(not_before), matplotlib.dates.date2num(latest_dt)])
#Update the canvas
self.fig.canvas.draw()
def deg2F(self,deg):
return float(deg) * 9./5. + 32.
def stime(self, timestamp):
return datetime.strptime(timestamp, '%m/%d/%Y %H:%M:%S.%f')
def rten(self, ten):
return int(float(ten) * self.slope + self.offset)
if __name__ == "__main__":
Anim()