259 lines
9.2 KiB
Python
259 lines
9.2 KiB
Python
import datetime, time, sys
|
||
import numpy as np
|
||
import pyqtgraph as pg
|
||
from pyqtgraph.Qt import QtWidgets
|
||
|
||
def csv_to_nparray(fileName, ContainDateTime, timeRange):
|
||
if ContainDateTime == 'True':
|
||
ContainDateTime = True
|
||
else:
|
||
ContainDateTime = False
|
||
Filter = 0
|
||
itemMaxNum = 50
|
||
if ContainDateTime:
|
||
timeRange = timeRange.split(',')
|
||
if len(timeRange) == 2:
|
||
Filter = 1
|
||
startTime = datetime.datetime.strptime(timeRange[0].strip(),'%Y/%m/%d %H:%M:%S')
|
||
start_timestamp=time.mktime(startTime.timetuple())
|
||
stopTime = datetime.datetime.strptime(timeRange[1].strip(),'%Y/%m/%d %H:%M:%S')
|
||
stop_timestamp=time.mktime(stopTime.timetuple())
|
||
else:
|
||
Filter = 0
|
||
|
||
#读取文件
|
||
with open(fileName, "r") as f:
|
||
recordTotalNum = len(f.readlines())
|
||
f.seek(0)
|
||
|
||
#读取数据文件中的标题行
|
||
itemNames = []
|
||
itemNames.append('SampleNO')
|
||
if ContainDateTime == False:
|
||
itemNames.append('DateTime')
|
||
|
||
tempStr = f.readline()
|
||
tempStr = tempStr.replace(' ','')
|
||
tempStr = tempStr.replace('"','')
|
||
tempStr = tempStr.replace('\t','')
|
||
tempStr = tempStr.replace('\n','')
|
||
temp = tempStr.split(',')
|
||
for i in range(len(temp)):
|
||
temp[i] = temp[i].strip()
|
||
if ContainDateTime == True:
|
||
temp[0] = 'DateTime'
|
||
itemNames.extend(temp)
|
||
# print(itemNames)
|
||
temp = [item for item in itemNames if len(item)>0]
|
||
itemNames = temp[0:itemMaxNum]
|
||
print(f"itemNames:{itemNames}")
|
||
|
||
#读取数据文件中的数据,以浮点数的形式读取
|
||
rawData = np.array([])
|
||
rawData_list = list(rawData)
|
||
recordNum = 1
|
||
for i in range(1, recordTotalNum-1):
|
||
record = []
|
||
line = f.readline()
|
||
line = line.replace('"','')
|
||
line = line.replace('/', ' ')
|
||
line = line.replace('T', ' ')
|
||
line = line.replace('Z', '')
|
||
line = line.replace('\t', '')
|
||
line = line.replace('\n', '')
|
||
substrings = line.split(',')
|
||
|
||
if ContainDateTime:
|
||
substrings[0] = substrings[0].split('.')[0]
|
||
substrings[0] = substrings[0].replace('-',' ')
|
||
substrings[0] = substrings[0].replace(':',' ')
|
||
temp = substrings[0].split()
|
||
date_str = ""
|
||
for value in temp:
|
||
if value == '':
|
||
temp.remove(value)
|
||
datetime_str = temp[0]+'-'+temp[1]+'-'+temp[2]+' '+temp[3]+':'+temp[4]+':'+temp[5]
|
||
if datetime_str == '1970-1-1 1:1:1' or datetime_str == '1970-1-1 1:01:01':
|
||
datetime_str = temp[0]+'-'+temp[1]+'-'+'2'+' '+temp[3]+':'+temp[4]+':'+temp[5]
|
||
dt = datetime.datetime.strptime(datetime_str,'%Y-%m-%d %H:%M:%S')
|
||
timestamp=time.mktime(dt.timetuple())
|
||
else:
|
||
datetime_str = '1971-1-2 1:1:1'
|
||
dt = datetime.datetime.strptime(datetime_str,'%Y-%m-%d %H:%M:%S')
|
||
timestamp=time.mktime(dt.timetuple())
|
||
|
||
record.append(recordNum)
|
||
record.append(timestamp)
|
||
|
||
if ContainDateTime:
|
||
for j in range(1, min(substrings.__len__(), itemMaxNum)):
|
||
try:
|
||
record.append(float(substrings[j].replace(' ','')))
|
||
except:
|
||
record.append(-1)
|
||
pass
|
||
else:
|
||
for j in range(0, min(substrings.__len__(), itemMaxNum)):
|
||
try:
|
||
record.append(float(substrings[j].replace(' ','')))
|
||
except:
|
||
record.append(-1)
|
||
pass
|
||
if Filter:
|
||
if record[1] >= start_timestamp and record[1] <= stop_timestamp:
|
||
recordNum += 1
|
||
rawData_list.append(record)
|
||
else:
|
||
recordNum += 1
|
||
rawData_list.append(record)
|
||
print(f"record:{record}")
|
||
rawData = np.array(rawData_list)
|
||
return itemNames, rawData
|
||
|
||
if __name__ == '__main__':
|
||
#解析参数
|
||
fileName = sys.argv[1]
|
||
timeRange = sys.argv[2]
|
||
ContainDateTime = sys.argv[3]
|
||
curveNum = int(sys.argv[4])
|
||
|
||
itemNamesRaw, recordsRaw = csv_to_nparray(fileName, ContainDateTime, timeRange)
|
||
itemNames = itemNamesRaw
|
||
records = recordsRaw
|
||
|
||
if ContainDateTime == 'True':
|
||
DisplayTime = True
|
||
else:
|
||
DisplayTime = False
|
||
|
||
if DisplayTime == False:
|
||
itemNames = np.delete(itemNames, 1, 0)
|
||
# print(itemNames)
|
||
|
||
itemsNum = itemNames.__len__()
|
||
# print(itemsNum)
|
||
|
||
if DisplayTime == False:
|
||
records = np.delete(records, 1, 1)
|
||
# print(records[:,:])
|
||
|
||
recordsNum = records.__len__()
|
||
|
||
if(itemsNum%curveNum == 0):
|
||
rowNum = int(itemsNum/curveNum)
|
||
else:
|
||
rowNum = int(itemsNum/curveNum)+1
|
||
|
||
colors = ['#FFFFFF', '#FF0000', '#FFFF00', '#FF00FF', '#00FF00', '#00FFFF', '#C0FF00', '#FF0080', '#FF7F7F', '#7FFF7F','#FFFFFF']
|
||
app = QtWidgets.QApplication([])
|
||
axsY=[]
|
||
axsX=[]
|
||
vbs=[]
|
||
vLine=[]
|
||
# 创建视图
|
||
pw = pg.GraphicsView()
|
||
pw.setWindowTitle(fileName)
|
||
pw.show()
|
||
|
||
# 创建图形布局
|
||
l = pg.GraphicsLayout()
|
||
# 设置视图中心小部件 为该布局
|
||
pw.setCentralWidget(l)
|
||
|
||
label = pg.LabelItem(justify='left')
|
||
l.addItem(label, row=0, col=0, rowspan=1, colspan=11)
|
||
|
||
labelStyle = {'font-size': '9pt'}
|
||
for i in range(0, itemsNum-1):
|
||
axsY.append(pg.AxisItem("left", pen=colors[i%10]))
|
||
axsY[i].setLabel(itemNames[i+1], color=colors[i%10],**labelStyle)
|
||
vbs.append(pg.ViewBox())
|
||
l.addItem(axsY[i],row = int(i/curveNum)+1, col = i%curveNum, rowspan=1, colspan=1)
|
||
l.addItem(vbs[i],row = int(i/curveNum)+1, col = 10, rowspan=1, colspan=1)
|
||
axsY[i].linkToView(vbs[i])
|
||
|
||
if(i>0):
|
||
vbs[i].setXLink(vbs[0])
|
||
if(i%curveNum == 0):
|
||
axsX.append(pg.AxisItem("bottom", pen=colors[10]))
|
||
axsX[int(i/curveNum)].setLabel(itemNames[0], color=colors[10],**labelStyle)
|
||
l.addItem(axsX[int(i/curveNum)],row = int(i/curveNum)+2, col = 10, rowspan=1, colspan=1)
|
||
axsX[int(i/curveNum)].linkToView(vbs[0])
|
||
|
||
tempStr = ""
|
||
if DisplayTime == True:
|
||
tempStr += "<span style='font-size: 9pt; word-wrap: break-word; white-space: normal;'>NO.={SampleNO}, "
|
||
BiasID = 0
|
||
else:
|
||
tempStr += "<span style='font-size: 9pt; word-wrap: break-word; white-space: normal;'>NO.={SampleNO}, <span style='color:white;'>DateTime={DateTime}</span>, "
|
||
BiasID = 1
|
||
for i in range(1, itemsNum):
|
||
tempStr += "<span style='color:"
|
||
tempStr += str(colors[(i-1)%10])
|
||
tempStr += "'>"
|
||
tempStr += itemNames[i]
|
||
tempStr += "={"
|
||
tempStr += itemNames[i]
|
||
tempStr += "}</span>, "
|
||
if(i%10 == 0):
|
||
tempStr +="<br>"
|
||
tempStr += "</span>"
|
||
# print(tempStr)
|
||
for i in range(0, rowNum):
|
||
vLine.append(pg.InfiniteLine(angle=90, movable=True))
|
||
vbs[i*curveNum-1].addItem(vLine[i])
|
||
# pI.addItem(vLine)
|
||
|
||
def mouseMoved(evt):
|
||
global tempStr, itemNamesRaw, recordsRaw, BiasID
|
||
index = 0
|
||
dic = {}
|
||
pos = evt[0]
|
||
# if l.sceneBoundingRect().contains(pos):
|
||
for i in range(0, rowNum):
|
||
if vbs[i*curveNum-1].sceneBoundingRect().contains(pos):
|
||
mousePoint = vbs[i*curveNum-1].mapSceneToView(pos)
|
||
index = int(mousePoint.x())
|
||
|
||
if index > 0 and index < recordsNum:
|
||
dic[itemNamesRaw[0]] = index
|
||
dic[itemNamesRaw[1]] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(recordsRaw[index-1,1]))
|
||
for k in range(2, itemsNum+BiasID):
|
||
dic[itemNamesRaw[k]] =recordsRaw[index-1,k]
|
||
# print(dic)
|
||
label.setText(tempStr.format(**dic))
|
||
for i in range(0, rowNum):
|
||
vLine[i].setPos(index)
|
||
proxy = pg.SignalProxy(l.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved)
|
||
|
||
# slot: 插槽:调整大小时更新视图
|
||
def updateViews():
|
||
# setGeometry设置几何图形
|
||
# sceneBoundingRect场景边界矩形
|
||
for i in range(0, itemsNum-1):
|
||
vbs[i].setGeometry(vbs[i].sceneBoundingRect())
|
||
|
||
# 折线点值 (轴刻度范围自动按最大最小值生成)
|
||
|
||
# 给绘图项的视图框添加折线xy点的值,折线颜色
|
||
for i in range(0, itemsNum-1):
|
||
vbs[i].addItem(pg.PlotCurveItem(records[:,0], records[:,i+1], pen=colors[i%10]))
|
||
#vbs[i].addItem(pg.ScatterPlotItem(records[:,0], records[:,i+1], pen=colors[i%10], symbolBrush=(255,0,0), symbolPen='w', size=2))
|
||
|
||
|
||
# vbs[0].sigResized.connect(updateViews)
|
||
|
||
for i in range(0, itemsNum-1):
|
||
vbs[i].enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
|
||
|
||
|
||
# 调整大小时更新
|
||
|
||
|
||
# 开始时自动调整一次以适应视图
|
||
# enableAutoRange 启用自动范围
|
||
|
||
|
||
updateViews()
|
||
app.exec()
|