227 lines
8.4 KiB
Python
227 lines
8.4 KiB
Python
#coding:utf-8
|
|
|
|
# 导入matplotlib模块并使用Qt5Agg
|
|
import typing
|
|
from PyQt5.QtCore import QObject
|
|
import matplotlib
|
|
matplotlib.use('Qt5Agg')
|
|
# 使用 matplotlib中的FigureCanvas (在使用 Qt5 Backends中 FigureCanvas继承自QtWidgets.QWidget)
|
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
from PyQt5.QtCore import *
|
|
from PyQt5.QtGui import *
|
|
from PyQt5.QtWidgets import *
|
|
import matplotlib.pyplot as plt
|
|
import sys
|
|
import scheme_data
|
|
import numpy as np
|
|
import threading
|
|
import os
|
|
|
|
|
|
plt.rcParams['font.sans-serif']=['SimHei']
|
|
plt.rcParams['axes.unicode_minus']=False
|
|
|
|
|
|
# 定义一个可以嵌入到qt的figure
|
|
class QFigure(QObject):
|
|
def __init__(self,title:str) -> None:
|
|
QObject.__init__(self)
|
|
self.__figure = plt.figure(figsize=(14,7))
|
|
self.__canvas = FigureCanvas(self.__figure)
|
|
self.__ax = self.__figure.add_axes([0.1,0.1,0.8,0.8])
|
|
self.__ax.set_title(title)
|
|
self._title=title
|
|
|
|
def draw(self,x,y,lable:str=None,limit_max:int=None,limit_min:int=None):
|
|
line,=self.__ax.plot(x,y,)
|
|
if(lable!=None):
|
|
line.set_label(lable)
|
|
self.__ax.legend()
|
|
if(limit_max!=None):
|
|
self.__ax.axhline(y=limit_max,color='g',linestyle='--')
|
|
if(limit_min!=None):
|
|
self.__ax.axhline(y=limit_min,color='r',linestyle='--')
|
|
# start, end = self.__ax.get_ylim()
|
|
# self.__ax.yaxis.set_ticks(np.arange(start, end,(end-start)/20),minor=True)
|
|
# ticks=self.__ax.yaxis.get_ticklocs()
|
|
# self.__ax.yaxis.set_ticks(minor=True)
|
|
# self.__ax.yaxis.set_ticks(ticks)
|
|
self.__ax.grid(visible=True,which="major",axis="y")
|
|
self.__canvas.draw()
|
|
def save(self,path:str,perfix:str):
|
|
if not os.path.exists(path):
|
|
os.makedirs(path)
|
|
name=os.path.join(path,perfix+self._title)
|
|
self.__figure.savefig(name+'.png')
|
|
def lable(self,lablex,labley):
|
|
self.__ax.set_ylabel(labley)
|
|
self.__ax.set_xlabel(lablex)
|
|
def canvas(self):
|
|
return self.__canvas
|
|
|
|
|
|
# 定义一个任务需要的参数布局
|
|
class TParamLayout(QObject):
|
|
def __init__(self) -> None:
|
|
QObject.__init__(self)
|
|
self.__layout=QFormLayout()
|
|
self.__items=[]
|
|
def add_item(self,name:str,value:str="",tooltip:str=None):
|
|
line_edit = QLineEdit()
|
|
line_edit.setObjectName(value)
|
|
line_edit.setText(value)
|
|
line_edit_label = QLabel()
|
|
line_edit_label.setObjectName(name)
|
|
line_edit_label.setText(name)
|
|
line_edit_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
if(tooltip!=None):
|
|
line_edit_label.setToolTip(tooltip)
|
|
line_edit.setToolTip(tooltip)
|
|
self.__layout.addRow(line_edit_label,line_edit)
|
|
self.__items.append((line_edit_label,line_edit))
|
|
def item_value(self,name:str):
|
|
for i in self.__items:
|
|
if(i[0].text()==name):
|
|
return i[1].text()
|
|
return None
|
|
def values(self):
|
|
vals=[]
|
|
for i in self.__items:
|
|
vals.append((i[0].text(),i[1].text()))
|
|
return vals
|
|
def layout(self):
|
|
return self.__layout
|
|
|
|
class Analysis(QWidget):
|
|
data_recv_end_signal =pyqtSignal([list,list])
|
|
calc_item_end_signal =pyqtSignal([list])
|
|
def __init__(self,parent=None):
|
|
super(Analysis,self).__init__(parent)
|
|
self.setWindowTitle("检测数据分析")
|
|
self.calc_item_end_signal.connect(self.calc_item_end_slot)
|
|
self.data_recv_end_signal.connect(self.data_recv_end_slot)
|
|
self.__import_but = QPushButton("导入方案",self)
|
|
self.__import_but.clicked.connect(self.import_but_clicked)
|
|
self.__import_but.setGeometry(QRect(0,0,100,27))
|
|
self.__export_but = QPushButton("导出方案")
|
|
self.__export_but.clicked.connect(self.export_but_clicked)
|
|
|
|
self.__scroll=QScrollArea(self)
|
|
self.__scroll.setGeometry(0,30,1230,700)
|
|
# 设置布局
|
|
self.__layout = QFormLayout()
|
|
self.__layout.addRow(' ',self.__export_but)
|
|
self.__items=[]
|
|
def add_item(self,data_dict:dict):
|
|
data=data_dict["data"]
|
|
x=data_dict["x"]
|
|
name=data_dict["name"]
|
|
max=data_dict["max"]
|
|
min=data_dict["min"]
|
|
avg=data_dict["avg"]
|
|
mid=data_dict["mid"]
|
|
std=data_dict["std"]
|
|
limit_max=data_dict["limit_max"]
|
|
limit_min=data_dict["limit_min"]
|
|
dat_count=data_dict["dat_count"]
|
|
y=data_dict["y"]
|
|
figure = QFigure(name)
|
|
figure.lable("序号","数值")
|
|
tplayout=TParamLayout()
|
|
tplayout.add_item(name+":Max",str(max))
|
|
tplayout.add_item(name+":Min",str(min))
|
|
tplayout.add_item(name+":Avg",str(avg))
|
|
tplayout.add_item(name+":Mid",str(mid))
|
|
tplayout.add_item(name+":Std",str(std))
|
|
tplayout.add_item(name+":LimitMax",str(limit_max))
|
|
tplayout.add_item(name+":LimitMin",str(limit_min))
|
|
self.__layout.addRow(figure.canvas(),tplayout.layout())
|
|
figure.draw(range(len(data)),data,lable="原始值",limit_max=limit_max,limit_min=limit_min)
|
|
figure.draw(dat_count,y,lable="权重")
|
|
figure.save(self._save_path,str(self._item_index)+".")
|
|
self.__items.append((figure,tplayout))
|
|
self._item_index+=1
|
|
def calc_item_end_slot(self,data:list):
|
|
print("calc_item end.")
|
|
widget=QWidget()
|
|
widget.setGeometry(QRect(0,0,1200,20000))
|
|
for i in data:
|
|
self.add_item(i)
|
|
widget.setLayout(self.__layout)
|
|
self.__scroll.setWidget(widget)
|
|
|
|
def calc_item(self,data,name:str):
|
|
length=len(data)
|
|
# 排序,从小到大
|
|
sort_list=np.sort(data)
|
|
dat_count=np.bincount(data)
|
|
avg=round(np.average(data))
|
|
max=sort_list[-1]
|
|
min=sort_list[0]
|
|
mid=sort_list[len(sort_list)//2]
|
|
std=round(np.std(data))
|
|
# 把众数和原始值对齐
|
|
dat_count=dat_count[min:]
|
|
dat_count_max=np.max(dat_count)
|
|
dat_zoom=length//dat_count_max
|
|
dat_count=np.multiply(dat_count,dat_zoom)
|
|
# 去掉极大值,去掉极小值,使用99.8%的数据来统计区间
|
|
limit_max_t=sort_list[-(length//1000)]
|
|
limit_min_t=sort_list[(length//1000)]
|
|
limit_max=limit_max_t+(limit_max_t-limit_min_t)//5
|
|
limit_min=limit_min_t-(limit_max_t-limit_min_t)//5
|
|
|
|
# 使用3倍标准差来统计区间
|
|
# limit_max=avg+3*std
|
|
# limit_min=avg-3*std
|
|
if(limit_min<0):
|
|
limit_min=0
|
|
x=range(length)
|
|
y=np.add(range(len(dat_count)),min)
|
|
dat_struct={"name":name,"max":max,"min":min,"avg":avg,"mid":mid,"std":std,"limit_max":limit_max,
|
|
"limit_min":limit_min,"dat_count":dat_count,"y":y,"x":x,"data":data}
|
|
# self.add_item_signal.emit(dat_struct)
|
|
return dat_struct
|
|
|
|
# 连接的绘制的方法
|
|
def import_but_clicked(self):
|
|
self.sch_data=scheme_data.sch_data()
|
|
self.__import_but.setEnabled(False)
|
|
self.sch_data.select_scheme()
|
|
self._save_path="file/"+self.sch_data.scheme_name.split('/')[-1].split('.')[0]
|
|
print(self._save_path)
|
|
self.recv_data()
|
|
def recv_data(self):
|
|
self._item_index=0
|
|
def recv_data_thread(sch_data:scheme_data.sch_data):
|
|
titles,data,num=sch_data.datas_sql()
|
|
print("recv data,len=",num)
|
|
self.data_recv_end_signal.emit(titles,data)
|
|
if(num<1000):
|
|
print("data len too less.")
|
|
return
|
|
items_data=[]
|
|
for i in range(len(titles)):
|
|
a=self.calc_item(data[i],titles[i])
|
|
items_data.append(a)
|
|
self.calc_item_end_signal.emit(items_data)
|
|
|
|
t = threading.Thread(target=recv_data_thread, args=(self.sch_data,))
|
|
t.start()
|
|
def data_recv_end_slot(self,titles:list,data:list):
|
|
self.titles=titles
|
|
self.sql_data=data
|
|
print("data recv end.")
|
|
def export_but_clicked(self):
|
|
ret_limit=[]
|
|
for i,t in zip(self.__items,self.titles):
|
|
max=i[1].item_value(t+":LimitMax")
|
|
min=i[1].item_value(t+":LimitMin")
|
|
ret_limit.append((max,min))
|
|
self.sch_data.export_scheme(ret_limit)
|
|
# 运行程序
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
main_window = Analysis()
|
|
main_window.show()
|
|
app.exec() |