class Ui_MainWindow_Company_Scatter_Plot(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 650) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(10, 600, 850, 31)) font = QtGui.QFont() font.setPointSize(10) self.label.setFont(font) self.label.setObjectName("label") read_company_records() read_altered_company_records() alphabet_value = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] unaltered_employee_names = company_name_value_array altered_employee_names = altered_company_name_value_array self.graphWidget = PlotWidget(self.centralwidget) self.graphWidget.setGeometry(QtCore.QRect(0, 0, 785, 580)) self.graphWidget.setObjectName("graphWidget") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.graphWidget.setLabel('left', 'Number of occurrences of company names first letter values', color='red', size=30) self.graphWidget.setLabel('bottom', 'Company Names sorted by first letter in a companies name', color='red', size=30) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.graphWidget.addLegend() self.graphWidget.showGrid(x=True, y=True) self.graphWidget.setXRange(0, 26.5, padding=0) self.graphWidget.setYRange(0, 300, padding=0) try: self.plot(alphabet_value, unaltered_employee_names, "Original Company Names", 'r') self.plot(alphabet_value, altered_employee_names, "Altered Company Names", 'b') except Exception: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Error! Please close existing window.") msg.setInformativeText('You can only have one window open at a time. Please close the existing window to continue!') msg.setWindowTitle("Error") msg.exec_() pass def plot(self, x, y, plotname, color): pen = pg.mkPen(color=color) self.graphWidget.plot(x, y, name=plotname, pen=pen, symbol='+', symbolSize=10, symbolBrush=(color)) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Differential Privacy Engine")) self.label.setText(_translate("MainWindow", "NOTE: This graph displays the difference between company names if the Differential Privacy Engine includes the company name values."))
class RealtimePlotWidget(QWidget): COLORS = [ Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray ] def __init__(self, parent=None): super(RealtimePlotWidget, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.enableAutoRange() self._plot_widget.showGrid(x=True, y=True, alpha=0.2) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._color_index = 0 self._curves = {} def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot} def remove_curve(self, curve_id): curve_id = str(curve_id) if curve_id in self._curves: self._plot_widget.removeItem(self._curves[curve_id]['plot']) del self._curves[curve_id] def set_x_range(self, left, right): self._plot_widget.setRange(xRange=(left, right)) def update_values(self, curve_id, x, y): curve = self._curves[curve_id] curve['x'] = numpy.append(curve['x'], x) curve['y'] = numpy.append(curve['y'], y) def redraw(self): for curve in self._curves.values(): if len(curve['x']): curve['plot'].setData(curve['x'], curve['y']) def lazy_redraw(self, period): timestamp = time.time() if not hasattr(self, '_prev_lazy_redraw'): self._prev_lazy_redraw = 0.0 if timestamp - self._prev_lazy_redraw > period: self._prev_lazy_redraw = timestamp self.redraw()
class RealtimePlotWidget(QWidget): COLORS = [Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray] def __init__(self, parent=None): super(RealtimePlotWidget, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.enableAutoRange() self._plot_widget.showGrid(x=True, y=True, alpha=0.2) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._color_index = 0 self._curves = {} def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot} def remove_curve(self, curve_id): curve_id = str(curve_id) if curve_id in self._curves: self._plot_widget.removeItem(self._curves[curve_id]['plot']) del self._curves[curve_id] def set_x_range(self, left, right): self._plot_widget.setRange(xRange=(left, right)) def update_values(self, curve_id, x, y): curve = self._curves[curve_id] curve['x'] = numpy.append(curve['x'], x) curve['y'] = numpy.append(curve['y'], y) def redraw(self): for curve in self._curves.values(): if len(curve['x']): curve['plot'].setData(curve['x'], curve['y']) def lazy_redraw(self, period): timestamp = time.time() if not hasattr(self, '_prev_lazy_redraw'): self._prev_lazy_redraw = 0.0 if timestamp - self._prev_lazy_redraw > period: self._prev_lazy_redraw = timestamp self.redraw()
class PyQtGraphDataPlot(QWidget): _colors = [ Qt.red, Qt.blue, Qt.magenta, Qt.cyan, Qt.green, Qt.darkYellow, Qt.black, Qt.darkRed, Qt.gray, Qt.darkCyan ] def __init__(self, parent=None): super(PyQtGraphDataPlot, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.setBackground((255, 255, 255)) self._plot_widget.setXRange(0, 10, padding=0) self.legend = self._plot_widget.addLegend() vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._color_index = 0 self._curves = {} def add_curve(self, curve_id, curve_name, data_x, data_y): color = QColor(self._colors[self._color_index % len(self._colors)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot} self._update_legend() def remove_curve(self, curve_id): curve_id = str(curve_id) if curve_id in self._curves: self._plot_widget.removeItem(self._curves[curve_id]['plot']) del self._curves[curve_id] self._update_legend() def _update_legend(self): # TODO Figure this out pass @Slot(str, list, list) def update_values(self, curve_id, x, y): curve = self._curves[curve_id] curve['x'] = numpy.append(curve['x'], x) curve['y'] = numpy.append(curve['y'], y) def redraw(self): # Set axis bounds x_range, _ = self._plot_widget.viewRange() x_delta = x_range[1] - x_range[0] x_max = 0 for curve in self._curves.values(): if len(curve['x']) == 0: continue x_max = max(x_max, curve['x'][-1]) curve['plot'].setData(curve['x'], curve['y']) self._plot_widget.setXRange(x_max - x_delta, x_max, padding=0)
def _plot_prediction(self, historical_dfs: list[pd.DataFrame], model: RandomForest, prediction: ndarray, target_date: datetime.date) -> None: """Opens a window with a plot of the historical target data as well as the prediction the model made.""" hdf = historical_dfs[0] for frame in historical_dfs[1:]: hdf = hdf.combine_first(frame) window_end = target_date - \ pd.DateOffset(days=model.window.target_shift) window_start = window_end - pd.DateOffset(days=30 - 1) hdf = pd.Series( hdf.loc[window_end:window_start][model.window.target_lbl]) hdf_data = hdf.to_list() hdf_dates = hdf.index hdf_dates = [ts.to_pydatetime().timestamp() for ts in hdf_dates] b_axis = pg.DateAxisItem(orientation='bottom') b_axis.setLabel('Date') plot = PlotWidget(axisItems={'bottom': b_axis}) target_time = datetime.combine(target_date, datetime.min.time()) plot.addLegend() plot.plot(x=hdf_dates, y=hdf_data, name=f'Historical {model.window.target_lbl}') plot.plot(x=[target_time.timestamp()], y=prediction, pen=None, symbol='o', name=f'Predicted Value: {prediction[0]}') model_name = self._model.currentText() self._plot_window.setWindowTitle(f'{model_name} Prediction') self._plot_window.setCentralWidget(plot) self._plot_window.show()
class QGraph(QWidget): def __init__(self, config, parent=None, **kwargs): QWidget.__init__(self, parent) self.startTime = None self.numDataPoints = 0 self.datasets = {} for display in config['displays']: self.datasets[display['field']] = self.createDatasetForDisplay( display) self.graph = PlotWidget(title=config['title'], labels=config['labels']) # Only add a legend to the graph if there is more than one dataset displayed on it if len(self.datasets) > 1: self.graph.addLegend() # Show grid lines self.graph.showGrid(x=True, y=True) for _, dataset in self.datasets.items(): self.graph.addItem(dataset['plotData']) vbox = QVBoxLayout() vbox.addWidget(self.graph) self.setLayout(vbox) def createDatasetForDisplay(self, display): plotData = PlotDataItem(name=display['label']) if 'color' in display: plotData.setPen(mkPen({'color': display['color']})) return { 'plotData': plotData, 'points': numpy.zeros((constants.NUMPY_ARRAY_SIZE, 2)), } def updateDataset(self, dataset): time = self.getAxisTime(dataset) # Skip updating if no time is available if not time: return for field, _ in self.datasets.items(): self.updatePoints(time, field, dataset) self.updateGraphs(field, dataset) self.numDataPoints += 1 def updatePoints(self, time, field, dataset): for key, data in dataset.items(): # Only plot float values if field == key and isinstance(data, float): self.datasets[field]['points'][self.numDataPoints] = (time, data) return def getAxisTime(self, dataset): # Use the first dataset as the start time if not self.startTime and dataset['delta']: self.startTime = dataset['delta'] if dataset['delta']: return (dataset['delta'] - self.startTime) else: return None def updateGraphs(self, field, dataset): for data in dataset.items(): if field in dataset: # We don't want to graph the empty values in the points array so only # give the plot data the points up to the current number of data points points = self.datasets[field]['points'] self.datasets[field]['plotData'].setData( points[0:self.numDataPoints])
class central(QWidget): #Cria widget para colocar na janela central onde as duas def __init__(self): super().__init__() self.setWindowIcon(QIcon("icons/icone_TCC.png")) self.UI() def UI(self): main = QVBoxLayout() #Widget principal, onde serão colocadas todas as abas self.unit_y = "Ângulo de deflexão (° graus)" self.unit_x = "Segundos (s)" self.lines = [] #Lista das linhas do listwidget reinicia self.tabela_param = 830 self.passw = "lembrei" # Cria os principais layouts que serão inseridos nas 4 abas do software self.main_tab = QHBoxLayout() #Layout para a aba principal db_tab = QVBoxLayout() #Layout para a aba dos dados rep_tab = QVBoxLayout() #Aba dos relatórios info_tab = QVBoxLayout() #Aba das informações """ Widgets da primeira aba """ fonte = QFont() #Cria a fonte em negrito fonte.setBold(True) #Cria o formulário dos parâmetros, controle e barra de progresso self.formulario = QVBoxLayout() #Cria o form das principais atividades self.lbl_void = QLabel() #Label vazio para espaçar os dados self.lbl_imp = QLabel("Dir. do Sistema",self) #Label da importação do benchmark self.lbl_imp.setFont(fonte) #self.lbl_icon.setAlignment(Qt.AlignCenter) self.btn_bch = QPushButton("Benchmark") self.btn_bch.clicked.connect(self.bench) self.lbl_param = QLabel("Parametrização",self) self.lbl_param.setFont(fonte) self.lbl_font = QLabel("Fonte da OFC: ") self.cmb_font = QComboBox(self) #Cria o combobox do primeiro parâmetro self.cmb_font.addItems(font) #Carrega lista das fontes de perturbação self.cmb_font.currentTextChanged.connect(self.pdate_ampl) self.hbox_font = QHBoxLayout() self.hbox_font.addWidget(self.lbl_font) self.hbox_font.addWidget(self.cmb_font) self.lbl_type = QLabel("Tipo da OFC: ") self.cmb_type = QComboBox(self) #Cria o combobox do primeiro parâmetro self.cmb_type.addItems(type_ofc) #Carrega lista das fontes de perturbação self.hbox_type = QHBoxLayout() self.hbox_type.addWidget(self.lbl_type) self.hbox_type.addWidget(self.cmb_type) self.lbl_turb = QLabel("Turbulência: ") self.cmb_turb = QComboBox(self) #Cria o combobox do segundo parâmetro self.cmb_turb.addItems(turb) self.hbox_turb = QHBoxLayout() self.hbox_turb.addWidget(self.lbl_turb) self.hbox_turb.addWidget(self.cmb_turb) self.lbl_ctrl1 = QLabel("Tipo Controle: ") self.cmb_ctrl1 = QComboBox(self)#Cria o combobox do terceiro parâmetro self.cmb_ctrl1.addItems(ctrl) self.hbox_ctrl1 = QHBoxLayout() self.hbox_ctrl1.addWidget(self.lbl_ctrl1) self.hbox_ctrl1.addWidget(self.cmb_ctrl1) self.lbl_ampl = QLabel("Ampl(mm)/Bias(mm)/Freq(rad/s):") self.cmb_ampl = QComboBox(self) #Cria o combobox das unidades do eixo das abscissas self.cmb_ampl.addItems(ampl) self.cmb_bias = QComboBox(self) #Cria o combobox das unidades do eixo das abscissas self.cmb_bias.addItems(bias) self.cmb_freq = QComboBox(self) #Cria o combobox das unidades do eixo das oordenadas self.cmb_freq.addItems(freq) self.amp_bias_freq = QHBoxLayout() self.amp_bias_freq.addWidget(self.cmb_ampl,30) self.amp_bias_freq.addWidget(self.cmb_bias,30) self.amp_bias_freq.addWidget(self.cmb_freq,40) self.lbl_ctrl = QLabel("Painel de Controle",self) self.lbl_ctrl.setFont(fonte) self.lbl_bench = QLabel("Modelo .lsx Benchmark: ") self.cmb_bench = QComboBox(self) #Cria o combobox das unidades do eixo das oordenadas self.lbl_treino = QLabel("Modo de Treinamento: ") self.cmb_treino = QComboBox(self) #Cria o combobox das unidades do eixo das oordenadas self.cmb_treino.addItems(treino) self.lbl_time = QLabel("Tempo de Simulação: ") self.line_time = QLineEdit() self.line_time.setPlaceholderText("Segundos") self.hbox_time = QHBoxLayout() self.hbox_time.addWidget(self.lbl_time) self.hbox_time.addWidget(self.line_time) self.list_status = QListWidget() self.list_status.doubleClicked.connect(self.exp_rep) self.btn_start = QPushButton("Iniciar") self.btn_start.clicked.connect(self.start) self.btn_start.setDisabled(True) self.pbar = QProgressBar() self.pbar.setFont(fonte) #Insere no formulário os widgets: self.formulario.addStretch() cp = QDesktopWidget().availableGeometry().center() if cp.y()*2 >= 1030: #Se a resolução for alta, coloca o ícone da pontifícia self.tabela_param = 1385 self.lbl_icon = QLabel() #Label que armazena o icone #Icone da pontifícia: icone_tcc = QPixmap("icons/TCC_Icon.png")#.scaled(50, 61, Qt.KeepAspectRatio, Qt.FastTransformation) self.lbl_icon.setPixmap(icone_tcc) self.lbl_icon.setAlignment(Qt.AlignCenter) self.formulario.addWidget(self.lbl_icon) self.passw = "" #self.benchmark_path = r"D:/PUCPR/TRABALHO DE CONCLUSAO DO CURSO - TCC/SOFT SENSORS" self.formulario.addWidget(self.lbl_imp) self.formulario.addWidget(self.btn_bch) self.formulario.addWidget(QHLine())#)#self.lbl_void) #Espaçamento self.formulario.addWidget(self.lbl_param) self.formulario.addLayout(self.hbox_font) self.formulario.addLayout(self.hbox_type) self.formulario.addLayout(self.hbox_turb) self.formulario.addLayout(self.hbox_ctrl1) self.formulario.addWidget(self.lbl_ampl) self.formulario.addLayout(self.amp_bias_freq) self.formulario.addWidget(QHLine())#self.lbl_void) #Espaçamento self.formulario.addWidget(self.lbl_ctrl) self.formulario.addWidget(self.lbl_bench) self.formulario.addWidget(self.cmb_bench) self.formulario.addWidget(self.lbl_treino) self.formulario.addWidget(self.cmb_treino) self.formulario.addLayout(self.hbox_time) self.formulario.addWidget(self.btn_start) self.formulario.addWidget(self.list_status) self.formulario.addWidget(self.pbar) self.formulario.setAlignment(Qt.AlignCenter) self.formulario.addStretch() #cria o gráfico self.grafico = PlotWidget() self.grafico.setBackground('#323232') #Coloca a cor de fundo igual a do restante da interface # Coloca título no gráfico self.grafico.setTitle("Simulação do Benchmark OFC: AirBus", color="#56fceb", size="20pt") self.styles = {"color": "#56fceb", "font-size": "16px"} #Cria os estilos de fonte do gráfico self.grafico.setLabel("left", self.unit_y, **self.styles) #Insere a unidade do eixo Oordenado self.grafico.setLabel("bottom", self.unit_x, **self.styles) #Insere a unidade do eixo das Abscissas self.grafico.addLegend() #Coloca legenda no gráfico self.grafico.showGrid(x=True, y=True) #Coloca as grids no gráfico #Cria as três curvas que serão periodicamente atualizadas #self.dx_falhas = ScatterPlotItem(name="Falhas: OFC", symbolSize=10,symbol='x',symbolBrush=("#fc031c"), # pen=mkPen(color="#fc031c", width=1)) #self.grafico.addItem(self.dx_falhas) self.dx_comm = self.grafico.plot(name="Comando de Controle", symbolSize=5,symbolBrush=("#15bf48"), pen=mkPen(color="#15bf48", width=2)) self.dx_meas = self.grafico.plot(name="Deflexão Mensurada", symbolSize=5,symbolBrush=("#56fceb"), pen=mkPen(color="#56fceb", width=2)) self.dx_falhas = self.grafico.plot(name="Falhas: OFC", symbolSize=20,symbol='x',symbolBrush=("#fc031c"), pen=mkPen(color="#323232", width=0.001)) self.formulario.addStretch() #Insere os widgets na widget da aba self.main_tab.addLayout(self.formulario,13.5) #Adiciona a aba os parâmetros self.main_tab.addWidget(self.grafico,86.5) #Adiciona o gráfico a aba principal """ Cria os widgets da segunda tab """ self.db_table = QTableView() #Cria tabela do banco de dados #Itens abaixo da tabela self.btn_consulta = QPushButton("Consultar o Número de itens mais Atuais") self.btn_consulta.clicked.connect(self.update_tb) self.n_itens = QLineEdit() self.n_itens.setPlaceholderText("N° Itens") self.status_itens = QLineEdit() self.status_itens.setPlaceholderText("Status do software:") self.status_itens.setDisabled(True) self.btn_pdate = QPushButton("Atualiza para os 1000 últimos dados registrados") self.btn_pdate.clicked.connect(self.update_tb_1000) self.btn_exp = QPushButton("Exportar tabela para Excel") self.btn_exp.clicked.connect(self.exp_dados_excel) self.pbar_db = QProgressBar() self.pbar_db.setFont(fonte) self.db_func = QHBoxLayout() #Layout dos botões abaixo da tabela self.db_func.addWidget(self.btn_consulta,28) self.db_func.addWidget(self.n_itens,4.5) self.db_func.addWidget(self.status_itens,8.5) self.db_func.addWidget(self.pbar_db,25) self.db_func.addWidget(self.btn_pdate,21) self.db_func.addWidget(self.btn_exp,12) #Insere abaixo da tabela os itens: db_tab.addWidget(self.db_table,93) db_tab.addLayout(self.db_func,7) db_tab.addStretch() """ Cria os widgets da terceira aba """ self.rep_table = QTableView() #Cria tabela do relatório #Itens abaixo da tabela self.btn_pdate_rep = QPushButton("Atualiza para todos os dados registrados") self.btn_pdate_rep.clicked.connect(self.update_rep) self.btn_rep = QPushButton("Atualiza para todos últimos 'N' dados registrados") self.btn_rep.clicked.connect(self.update_rep_n) self.btn_exp_rep = QPushButton("Exportar relatório para Excel") self.btn_exp_rep.clicked.connect(self.exp_rep_excel) self.n_itens_rep = QLineEdit() self.n_itens_rep.setPlaceholderText("N° Itens") self.status_itens = QLineEdit() self.pbar_rep = QProgressBar() self.pbar_rep.setFont(fonte) self.rep_func = QHBoxLayout() #Layout dos botões abaixo da tabela self.rep_func.addWidget(self.btn_pdate_rep,20) self.rep_func.addWidget(self.btn_rep,22) self.rep_func.addWidget(self.n_itens_rep,4.5) self.rep_func.addWidget(self.pbar_rep,38) self.rep_func.addWidget(self.btn_exp_rep,15.5) #Insere abaixo da tabela os itens: rep_tab.addStretch() rep_tab.addWidget(self.rep_table,90) rep_tab.addLayout(self.rep_func,10) rep_tab.addStretch() """ Cria os widgets da aba informativa """ #Cria a aba informativa do final self.mapa = QLabel() # self.mapa.setPixmap(QPixmap("icons/MAPA_MENTAL.png")) info_tab.addWidget(self.mapa) info_tab.setAlignment(Qt.AlignHCenter) ############################Criando abas############################## self.tabs = QTabWidget() #Widget das tabs que reune as 4 self.tab1 = QWidget() #Tab de emulação do benchmark self.tab2 = QWidget() #Tab do banco de dados self.tab3 = QWidget() #Relatório de Falhas self.tab4 = QWidget() #Informações complementares self.tabs.addTab(self.tab1,"Simulação do Sistema") self.tabs.addTab(self.tab2,"Consulta Geral ao Banco de Dados") self.tabs.addTab(self.tab3,"Consultar Tabela do Relatório de Falhas") self.tabs.addTab(self.tab4,"Informações sobre o TCC: Mapa Mental") self.tab1.setLayout(self.main_tab) # Adicionando a aba de simulação self.tab2.setLayout(db_tab) # Adicionando adicionando aba do db self.tab3.setLayout(rep_tab) # Adicionando adcionando aba self.tab4.setLayout(info_tab) # Adicionando para a tab1 #Adiciona ao box principal a estrutura de tabs main.addWidget(self.tabs) #Coloca a estrutura de tabs no layout principal self.setLayout(main) def plot(self, x, y, plotname, color): pen = mkPen(color=color) self.grafico.plot(x, y, name=plotname, pen=pen, symbolSize=5, symbolBrush=(color)) def maria_conn(self): try: self.conn = mariadb.connect( user="******", password=self.passw, host="127.0.0.1", port=3306, database="db_ofc_tcc") self.cur = self.conn.cursor() except mariadb.Error as e: QMessageBox.warning(self,"Aviso",f"Sem conexão com o Banco de dados, devido ao erro: {e}") self.list_status.addItem("Conectado ao db_tcc") if "Conectado ao db_tcc" not in self.lines: #Se não estiver coloca self.lines.append("Conectado ao db_tcc") def bench(self): ask_dir = "Escolha o diretório onde o Benchmark se encontra" self.benchmark = str(QFileDialog.getExistingDirectory(None,ask_dir)) self.list_status.clear() #Limpa a lista toda vez que o botão de benchmark é pressionado if self.benchmark != '': #Se não for vazio, continua arqs = os.listdir(self.benchmark) bench = [] #Reiniciado quando escolhida outra pasta self.lines = [] #Lista das linhas do listwidget reinicia for arq in arqs: if '.slx' in arq: #Se a extenção do arquivo for a mesma do simulink bench.append(arq) if not(bench): #Se o vetor estiver vazio not_bench = f"Não foi encontrado arquivo do simulink no diretório selecionado {self.benchmark}!" QMessageBox.warning(self,"Aviso!",not_bench) else: self.list_status.addItem(f"Diretório: {self.benchmark}") self.lines.append("\n-------------------------------------------------------------\n") self.lines.append(f"Diretório: {self.benchmark}") self.cmb_bench.addItems(bench) self.maria_conn() #Inicia conexão com o banco de dados self.btn_start.setDisabled(False) #Habilita o botão para iniciar os testes self.pbar.setValue(10)#Coloca 10% na barra de progresso def get_param(self): print(self.line_time.text()) #Valida o que o usuário digitou try: if float(self.line_time.text()) < 0: QMessageBox.warning(None,"Erro!","Insira um valor numérico real não negativo no Tempo de Simulação!") return else: simu_time = float(self.line_time.text()) except: QMessageBox.warning(None,"Erro!","Insira um valor numérico real não negativo no Tempo de Simulação!") return #Define a função de turbulência da classe aircraft turb = self.cmb_turb.currentText() if turb == 'None': func_turb = "setNoTurbulence()" elif turb == 'Light': func_turb = "setLightTurbulence()" elif turb == 'Moderate': func_turb = "setModerateTurbulence()" elif turb == 'Severe': func_turb = "setSevereTurbulence()" param = [self.cmb_font.currentText(),self.cmb_type.currentText(),self.cmb_ampl.currentText(), self.cmb_bias.currentText(),self.cmb_freq.currentText().replace("π","*pi"),func_turb, self.cmb_ctrl1.currentIndex()+1,simu_time] print(param) return param def start(self): global Relatorio_TXT_Etapas, time, time_fail, delta_comm, delta_meas, ofc_falhas #Limpa variáveis globais time = [] time_fail = [] delta_comm = [] delta_meas = [] ofc_falhas = [] #Treina os parâmetros simu = self.cmb_bench.currentText() self.system = self.benchmark+"/"+self.cmb_bench.currentText() #Caminho do sistema #monitora(system) #chama o simulink para emular o sistema quest = f"O sistema para emulação no Simulink é {self.system}?" if QMessageBox.question(self,"Tem certeza?",quest,QMessageBox.Yes|QMessageBox.No, QMessageBox.No) == QMessageBox.Yes: self.metodo = self.cmb_treino.currentText() #Pega do combo o texto do modelo a treinar self.benchmark_simu = self.cmb_bench.currentText() self.parametros = self.get_param() #Recebe os parâmetros informados pelo usuário if not self.parametros: self.line_time.setFocus() return self.list_status.addItem(f"Treinando o modelo {simu} pelo método {self.metodo}") self.lines.append(f"Treinando o modelo {simu} pelo método {self.metodo}") self.pbar.setValue(15) #Chama a classe do treino tic_mdl = datetime.now() #Dá ao usuário a possibilidade de treinar ou carregar modelo quest2 = "Deseja treinar os dados? O não implica em carregar módulo default de treino" if QMessageBox.question(self,"Treinar ou não?",quest2,QMessageBox.Yes|QMessageBox.No, QMessageBox.No) == QMessageBox.Yes and self.metodo != 'Support Vector Machine': self.modelo = treina_modelo(self.metodo,True) method = "Treinado" else: #Se for SVM, carrega o modelo pronto ao invez de treinar self.modelo = treina_modelo(self.metodo,False) method = "Carregado" self.list_status.addItem(f"Modelo {simu} foi {method} pelo método {self.metodo} em {datetime.now()-tic_mdl}") self.lines.append(f"Modelo {simu} foi {method} pelo método {self.metodo} em {datetime.now()-tic_mdl}") self.pbar.setValue(25) self.list_status.addItem(f"Iniciando {self.system} no Simulink") self.lines.append(f"Iniciando {self.system} no Simulink") #monitora(system) #Associa o monitoramento self.list_status.addItem("Iniciando o MatLab (estimado: 13.6s)") self.lines.append("Iniciando o MatLab (estimado: 13.6s)") self.pbar.setValue(30) tic_matlab = datetime.now() self.eng = matlab.engine.start_matlab() #Background true para receber os valores self.list_status.addItem(f"O MatLab foi iniciado em {datetime.now()-tic_matlab}") self.lines.append(f"O MatLab foi iniciado em {datetime.now()-tic_matlab}") print(self.benchmark) self.eng.addpath(self.benchmark,nargout=0) #Função que carrega todas as variáveis necessárias pra se iniciar o simulink self.SimulinkPlant(self.parametros) self.list_status.addItem("Carregando modelo no SimuLink (estimado: 6.35s)") self.lines.append("Carregando modelo no SimuLink (estimado: 6.35s)") self.pbar.setValue(32.5) self.eng.eval(f"model = '{self.system}'",nargout=0) self.eng.eval(f"simulation.setSimulinkModel('{self.benchmark_simu}');",nargout=0) self.pbar.setValue(35) self.list_status.addItem("Carregando prâmetros ao modelo Simulink") self.lines.append("Carregando prâmetros ao modelo Simulink") tic_m = datetime.now() self.eng.eval("SimOut = sim(simulation.simulink_model, 'SrcWorkspace', 'current');",nargout=0) self.processo = self.eng.eval("""[SimOut.dx_comm SimOut.dx_meas SimOut.time];""") self.list_status.addItem(f"O Modelo {simu} foi treinado pelo método {self.metodo} em {datetime.now()-tic_m}") self.lines.append(f"O Modelo {simu} foi treinado pelo método {self.metodo} em {datetime.now()-tic_m}") self.pbar.setValue(40) self.list_status.addItem(f"Emulando {self.system} no Simulink") self.lines.append(f"Emulando {self.system} no Simulink") Relatorio_TXT_Etapas = self.lines #Emulação do sistema self.delta_comm = [] #Zera a lista de declara self.delta_meas = [] self.ofc_fail = [] #Armazena dados das falhas encontradas self.time_fail = [] self.time = [] self.barra = 40 self.janela = 40 #Tamanho da janela de dados a ser colatada self.i = 0 #Número da iteração self.total_itter = self.parametros[-1]*40 + 1 #Numero total de iterações #Loop do timar para plotar o gráfico self.timer = QTimer() self.timer.setInterval(10) self.timer.timeout.connect(self.update_graph) QMessageBox.information(self,"Aviso",f"O {self.system} será emulado") self.timer.start() else: pass def update_graph(self): global time, delta_comm, delta_meas, simulado, ofc_falhas, time_fail self.barra += (self.i/(self.total_itter) - 0.4*(self.i/self.total_itter))/(self.total_itter/200.4) #Recebe apenas os valores desejados, comando, medida e tempo self.delta_comm.append(self.processo[self.i][0]) self.delta_meas.append(self.processo[self.i][1]) self.time.append(self.processo[self.i][2]) dat = [self.processo[self.i][0],self.processo[self.i][1],self.processo[self.i][2]] win = [] for i in range(self.janela): if self.i < self.total_itter-self.janela: win.append(float(self.processo[i+self.i][0])) #Recebe o valor das janelas respectivas else: win.append(float(self.processo[randint(0,self.total_itter-1)][0])) #Revebe valor de indice aleatório w = array(win) result = int(self.modelo.predict(w.reshape(1,-1)).astype(int16)[0]) #Recebe 0 se não há falha e 1 se houver if result == 1: #Se é uma falha, acrescenta ao vetor o dado da falha self.ofc_fail.append(self.processo[self.i][1]) self.time_fail.append(self.processo[self.i][2]) reg = [dat[0],dat[1],dat[2],result,win] #Cria vetor com os dados e a classificação dos sinais self.update_db(reg,self.parametros) #Atualiza o banco de dados com a informação mais recente self.dx_comm.setData(self.time, self.delta_comm) self.dx_meas.setData(self.time, self.delta_meas) if self.ofc_fail: #Se houver dados nesse objeto self.dx_falhas.setData(self.time_fail, self.ofc_fail) else: self.dx_falhas.setData([0],[0]) self.pbar.setValue(self.barra)#Coloca % na barra de progresso self.i += 1 if self.i >= self.total_itter-1: print(self.barra) self.timer.stop() self.conn.commit() self.pbar.setValue(100) time = self.time delta_comm = self.delta_comm delta_meas = self.delta_meas ofc_falhas = self.ofc_fail time_fail = self.time_fail simulado = True #Variável que habilita impressão do gráfico QMessageBox.information(self,"Sucesso!",f"O processo {self.system} foi emulado com sucesso!") return def SimulinkPlant(self,param): """ Essa função objetiva declarar as variáveis necessárias para desenvolvimento da simulação Parameter ---------- param: array Array com todos os parâmetros fornecidos pelo usuário Returns ------- None. Mas realiza inúmeros comandos para simular a planta e declarar as variáveis """ #Iniciando o benchmark e carrega as principais variáveis ao console da API self.eng.eval("ofc_benchmark_init;",nargout=0) self.eng.eval("simulation.setSimulinkModel('ofc_benchmark_acquire');",nargout=0) #Carrega as variáveis: aircraft, ofc, servoModel, servoReal e simulation! self.eng.eval("servoReal.randomiseServoParameters()",nargout=0) #Faz o objeto servo real ficar aleatório self.eng.eval(f"ofc.setLocation('{param[0]}')",nargout=0) self.eng.eval(f"ofc.setType('{param[1]}')",nargout=0) self.eng.eval(f"ofc.setAmplitude({param[2]})",nargout=0) self.eng.eval(f"ofc.setBias({param[3]})",nargout=0) self.eng.eval(f"ofc.setFrequency({param[4]})",nargout=0) self.eng.eval("ofc.setPhase(0)",nargout=0) self.eng.eval("ofc.setStartTime(0)",nargout=0) self.eng.eval(f"aircraft.{param[5]}",nargout=0) #Cria sinal aleatório de controle self.eng.eval("""controls = {@(x)aircraft.setControlInput('FPA_control'), ... @(x)aircraft.setControlInput('NZ_step', x(1), x(2), x(3)), ... @(x)aircraft.setControlInput('NZ_sine', x(1), x(2), x(3), x(4)), ... @(x)aircraft.setControlInput('NZ_chirp', x(1))};""",nargout=0) self.eng.eval("controls{"+str(param[6])+"}([10^randi([-1 1]),randi([10 25]),randi([35, 50]),randi([0, 10])])", nargout=0) self.eng.eval(f"simulation.setStopTime({param[7]})",nargout=0) #Seta o tempo final de simulação def update_tb(self): global df self.pbar_db.setValue(0) #Zera a barra de progresso limite = self.n_itens.text() self.pbar_db.setValue(10) try: int(limite) except: QMessageBox.warning(self,"Atenção!","Insira um número inteiro!") return if int(limite) <= 0: QMessageBox.warning(self,"Atenção!","Insira um número positivo maior que zero!") return try: self.cur.execute(f"SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT {limite};") except: self.maria_conn() self.cur.execute(f"SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT {limite};") self.pbar_db.setValue(20) dados = self.cur.fetchall() #Convertendo os dados provenientes do banco de dados para um dataframe e então envia para tabela self.df = DataFrame(dados, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) df = self.df self.pbar_db.setValue(30) self.db_table.setModel(pandasModel(self.df)) #Coloca os dados consultados na tabela self.db_table.setColumnWidth(0,45) self.db_table.setColumnWidth(1,120) self.db_table.setColumnWidth(2,105) self.db_table.setColumnWidth(3,105) self.db_table.setColumnWidth(4,65) self.db_table.setColumnWidth(5,42) self.db_table.setColumnWidth(6,self.tabela_param) self.pbar_db.setValue(100) def update_tb_1000(self): global Relatorio_TXT_Etapas, df try: self.cur.execute("SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT 1000;") except: self.maria_conn() self.cur.execute("SELECT * FROM tb_ofc_dt ORDER BY id DESC LIMIT 1000;") falhas = self.cur.fetchall() self.list_status.addItem("O relatório de falhas foi gerado!") self.lines.append("O relatório de falhas foi gerado!") Relatorio_TXT_Etapas = self.lines self.df = DataFrame(falhas, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) df = self.df self.db_table.setModel(pandasModel(self.df)) self.db_table.setColumnWidth(0,45) self.db_table.setColumnWidth(1,120) self.db_table.setColumnWidth(2,105) self.db_table.setColumnWidth(3,105) self.db_table.setColumnWidth(4,65) self.db_table.setColumnWidth(5,42) self.db_table.setColumnWidth(6,self.tabela_param) self.pbar_db.setValue(100) def update_db(self,dt,p): """ Essa função cadastra um item no banco de dados Parameters ---------- dt : tuple Linha proveniente do objeto de dados do matlab com três linhas (tempo, comando, medida e falha). p : list Lista dos parâmetros selecionados pelo usuário. Returns ------- None. """ global freq, ctrl, ampl fe = p[4].replace('*pi','π') pa = f"Metodo: {self.metodo}; F_OFC: {p[0]}; T_OFC: {p[1]}; Ampli.: {p[2]}; Bias: {p[3]}; Freq: {fe};" pa += f"Turb: {p[5].replace('()','')}; T_Ctrl: {ctrl[p[6]]}; t_simu: {p[7]}s; window: {dt[4]}" nw = datetime.now().strftime("%Y-%m-%d %H:%M:%S")#datetime.strftime(datetime.now(),"%d/%b/%Y - %H:%M") self.cur.execute("""INSERT INTO tb_ofc_dt (data,dx_comm,dx_meas,dt,falha,parametros) VALUES (?,?,?,?,?,?);""",[nw,dt[0],dt[1],dt[2],dt[3],pa]) def exp_graph(self): """ Essa função exporta o gráfico como está na tela em forma de imagem Returns ------- None. """ global time, delta_comm, delta_meas, simulado if simulado: ask_dir = "Escolha o diretório onde o deseja salvar o gráfico" #string que pergunta o diretório save = str(QFileDialog.getExistingDirectory(None,ask_dir)) #Pede ao usuário o diretório onde ele quer salvar self.grafico.plot(time,delta_comm, symbolSize=5,symbolBrush=("#15bf48"), pen=mkPen(color="#15bf48", width=2)) self.grafico.plot(time,delta_meas, symbolSize=5,symbolBrush=("#56fceb"), pen=mkPen(color="#56fceb", width=2)) self.grafico.plot(time_fail,ofc_falhas, symbolSize=15,symbol='x',symbolBrush=("#fc031c"), pen=mkPen(color="#323232", width=0.001)) exporter = exporters.ImageExporter(self.grafico.plotItem) #Exporta o objeto do gráfico exporter.export(save+f'/graph_{int(datetime.timestamp(datetime.now()))}.png') #Salva como png o gráfico QMessageBox.information(self,"Concluído!",f"Gráfico salvo com sucesso em: {save}") else: QMessageBox.warning(self,"Atenção!","O sistema ainda não foi emulado!") def exp_excel_all(self,aq): """ Essa função exporta os dados adquiridos para uma planilha do excel Returns ------- Não retorna parâmetros, apenas executa a ação de exportar para uma planilha """ global df, dff if not(df.empty) or not(dff.empty): #Se um dos dois não for vazio salve = str(QFileDialog.getExistingDirectory(None, "Escolha o diretório onde quer salvar o relatório")) save = salve+"/Relatório_OFC_MFF.xlsx" if aq==0 and not(df.empty): #Se os dados foram coletados, gera dos dados df.to_excel(save,sheet_name="Relatório_OFC_MFF",index=False) info_save_excel = f"O relatório geral foi salvo em {save}!" elif aq==1 and not(dff.empty): #Se as falhas foram coletadas, gera as falhas dff.to_excel(save.replace("MFF","FALHAS_MFF"),sheet_name="Relatório_Falhas_OFC_MFF",index=False) info_save_excel = f"O relatório final das falhas de caráter oscilatória foi salvo em {save}!" elif aq==2 and (not(df.empty) or not(dff.empty)): #Salva ambos if not(df.empty): df.to_excel(save,sheet_name="Relatório_OFC_MFF",index=False) info_save_excel = f"O relatório geral foi salvo em {save}!" if not(dff.empty): dff.to_excel(save.replace("MFF","FALHAS_MFF"),sheet_name="Relatório_Falhas_OFC_MFF",index=False) info_save_excel = f"O relatório final das falhas de caráter oscilatória foi salvo em {save}!" if not(df.empty) and not(dff.empty): info_save_excel = f"Os dois relatórios foram salvos em {save}!" QMessageBox.information(self,"Sucesso!",info_save_excel) else: info_not_save = "Nenhum dos dois relatórios foram gerados ainda!" QMessageBox.warning(self,"Atenção!",info_not_save) def exp_rep_excel(self): """ Essa função exporta os dados adquiridos para uma planilha do excel Returns ------- Não retorna parâmetros, apenas executa a ação de exportar para uma planilha """ self.exp_excel_all(1) def exp_dados_excel(self): """ Essa função exporta os dados adquiridos para uma planilha do excel Returns ------- Não retorna parâmetros, apenas executa a ação de exportar para uma planilha """ self.exp_excel_all(0) def exp_rep(self): """ Exporta um relatório em txt com os dados de falhas é acionado ao clickar duas vezes na caixa com logs duplo click em Returns ------- None. """ global Relatorio_TXT_Etapas #Insere na função a variável compartilhada entre classes if Relatorio_TXT_Etapas: dire = str(QFileDialog.getExistingDirectory(None, "Escolha o diretório para salvar o relatório em TXT!")) with open(dire+"/Relatorio_TXT_Etapas.txt",'w') as txt: txt.write("Relatório das etapas realizadas pelo software:\n") for line in Relatorio_TXT_Etapas: #Para cada linha, escreve no TXT txt.write("\n"+str(line)) QMessageBox.information(None,"Feito!","O relatório com as etapas realizadas foi salvo com sucesso!") else: QMessageBox.warning(None,"Atenção!","O relatório com as etapas ainda não foi gerado!") def update_rep_n(self): #Essa função irá popular a tabela de dados global dff limit = self.n_itens_rep.text() self.pbar_rep.setValue(10) #Reseta o valor da barra de progresso para 10% try: int(limit) except: QMessageBox.warning(self,"Atenção!","Insira um número inteiro!") return try: self.cur.execute(f"SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC LIMIT {limit}") except: self.maria_conn() self.cur.execute(f"SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC LIMIT {limit}") falhas = self.cur.fetchall() self.dff = DataFrame(falhas, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) dff = self.dff self.rep_table.setModel(pandasModel(self.dff)) self.rep_table.setColumnWidth(0,45) self.rep_table.setColumnWidth(1,120) self.rep_table.setColumnWidth(2,110) self.rep_table.setColumnWidth(3,100) self.rep_table.setColumnWidth(4,65) self.rep_table.setColumnWidth(5,42) self.rep_table.setColumnWidth(6,self.tabela_param) self.pbar_rep.setValue(100) def update_rep(self): #Essa função irá popular a tabela de dados global dff try: self.cur.execute("SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC") except: self.maria_conn() self.cur.execute("SELECT * FROM tb_ofc_dt WHERE falha = 1 ORDER BY id DESC") falhas = self.cur.fetchall() self.dff = DataFrame(falhas, columns = ["id","data","Deflexão comando","Deflexão medida", "Tempo (s)","Falha","Parâmetros"]) dff = self.dff self.rep_table.setModel(pandasModel(self.dff)) self.rep_table.setColumnWidth(0,45) self.rep_table.setColumnWidth(1,120) self.rep_table.setColumnWidth(2,110) self.rep_table.setColumnWidth(3,100) self.rep_table.setColumnWidth(4,65) self.rep_table.setColumnWidth(5,42) self.rep_table.setColumnWidth(6,self.tabela_param) self.pbar_rep.setValue(100) def pdate_ampl(self): if self.cmb_font.currentText() in ['sensor','cs_sensor']: self.lbl_ampl.setText("Ampl(mm)/Bias(mm)/Freq(rad/s):") else: self.lbl_ampl.setText("Ampl(mA)/Bias(mA)/Freq(rad/s):") def filed(self): #Abre o arquivo em forma de dicionário e retorna o caminho completo (posição 0) path = QFileDialog.getOpenFileName(self,"Abre um arquivo do excel","","All Files(*);;*xlsx *xls") if (".xls" in path[0]): #Se for um arquivo do excel modelo = ExcelFile(path[0]).parse(0,skiprows=1)# Carrega o template em um Excel e a planilha self.relatorio.setModel(pandasModel(modelo)) self.tab2.setDisabled(False) self.tab2.update() self.update() else: #Se não for... QMessageBox.warning(self,"Arquivo incorreto","Escolha um arquivo do Excel (.xlsx ou .xls)!") def salva(self): #Salva o dataset do relatório em um arquivo excel global df, dff, Relatorio_TXT_Etapas, simulado if not(df.empty) or not(dff.empty) or Relatorio_TXT_Etapas or simulado: #Se tem algo para salvar, procede r1 = ""; r2 = ""; r3 = "" salve = str(QFileDialog.getExistingDirectory(None, "Escolha o diretório onde quer salvar o relatório")) save_total = salve+"/Relatório_OFC_MFF.xlsx" save_falhas = salve+"/Relatório_OFC_Falhas_MFF.xlsx" save_txt = salve+"/Relatorio_TXT_Etapas.txt" if not(df.empty): #Se o dataframe com os dados contar com mais de 0 codigos df.to_excel(save_total,sheet_name="Relatório_OFC_MFF",index=False) r1 = "Relatório_OFC_MFF," if not(dff.empty): #Se as falhas foram coletadas, gera as falhas dff.to_excel(save_falhas,sheet_name="Relatório_Falhas_OFC_MFF",index=False) r2 = "Relatório_Falhas_OFC_MFF," if len(Relatorio_TXT_Etapas) > 0: #Se o relatório txt não está vazio with open(save_txt,'w') as txt: txt.write("Relatório das etapas realizadas pelo software:\n") for line in Relatorio_TXT_Etapas: #Para cada linha, escreve no TXT txt.write("\n"+str(line)) r3 = "Relatorio_TXT_Etapas" duplas = (r1 or r2) or (r1 or r3) or (r2 or r3) #Uma dupla todos = (r1 and r2 and r3) #Todos solo = (r1 or r2 or r3) and not (duplas) #Apenas um if duplas: #Plural QMessageBox.information(self,"Sucesso!",f"Os relatórios: {r1}{r2}{r3} foram salvos!".replace(","," e ")) elif todos: QMessageBox.information(self,"Sucesso!",f"Os relatórios: {r1}{r2}{r3} foram salvos!") elif solo: #Singular QMessageBox.information(self,"Sucesso!",f"O relatório: {r1}{r2}{r3} foi salvo!") if simulado:#Se foi simulado, exporta o gráfico if (QMessageBox.warning(self,"Aviso","Você gostaria de salvar o gráfico?", QMessageBox.Yes|QMessageBox.No,QMessageBox.No) == QMessageBox.Yes): self.exp_graph() else: QMessageBox.warning(self,"Atenção!","Nenhum relatório foi gerado, portanto não há o que salvar!")
class QGraph(QWidget): def __init__(self, config, parent=None, **kwargs): QWidget.__init__(self, parent) self.startTime = None self.numDataPoints = 0 self.datasets = {} for display in config['displays']: self.datasets[display['field']] = self.createDatasetForDisplay(display) self.graph = PlotWidget(title=config['title'], labels=config['labels']) # Only add a legend to the graph if there is more than one dataset displayed on it if len(self.datasets) > 1: self.graph.addLegend() # Show grid lines self.graph.showGrid(x=True, y=True) for _, dataset in self.datasets.items(): self.graph.addItem(dataset['plotData']) vbox = QVBoxLayout() vbox.addWidget(self.graph) self.setLayout(vbox) def createDatasetForDisplay(self, display): plotData = PlotDataItem(name=display['label']) if 'color' in display: plotData.setPen(mkPen({'color': display['color']})) return { 'plotData': plotData, 'points': numpy.zeros((constants.NUMPY_ARRAY_SIZE, 2)), } def updateDataset(self, dataset): time = self.getAxisTime(dataset) # Skip updating if no time is available if not time: return for field, _ in self.datasets.items(): self.updatePoints(time, field, dataset) self.updateGraphs(field, dataset) self.numDataPoints += 1 def updatePoints(self, time, field, dataset): for key, data in dataset.items(): # Only plot float values if field == key and isinstance(data, float): self.datasets[field]['points'][self.numDataPoints] = (time, data) return def getAxisTime(self, dataset): # Use the first dataset as the start time if not self.startTime and dataset['delta']: self.startTime = dataset['delta'] if dataset['delta']: return (dataset['delta'] - self.startTime) else: return None def updateGraphs(self, field, dataset): for data in dataset.items(): if field in dataset: # We don't want to graph the empty values in the points array so only # give the plot data the points up to the current number of data points points = self.datasets[field]['points'] self.datasets[field]['plotData'].setData(points[0:self.numDataPoints])
class Plotter(QWidget): MAX_DATA_POINTS_PER_CURVE = 200000 COLORS = [ Qt.red, Qt.green, Qt.blue, # RGB - http://ux.stackexchange.com/questions/79561 Qt.yellow, Qt.cyan, Qt.magenta, # Close to RGB Qt.darkRed, Qt.darkGreen, Qt.darkBlue, # Darker RGB Qt.darkYellow, Qt.darkCyan, Qt.darkMagenta, # Close to RGB Qt.gray, Qt.darkGray ] # Leftovers INITIAL_X_RANGE = 60 def __init__(self, parent=None): # Parent super(Plotter, self).__init__(parent) self.setWindowTitle('UAVCAN Plotter') self.setWindowIcon(APP_ICON) # Redraw timer self._update_timer = QTimer() self._update_timer.timeout.connect(self._update) self._update_timer.setSingleShot(False) self._update_timer.start(30) # PyQtGraph self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._legend = self._plot_widget.addLegend() self._plot_widget.setRange(xRange=(0, self.INITIAL_X_RANGE), padding=0) self._plot_widget.showButtons() self._plot_widget.enableAutoRange() self._plot_widget.showGrid(x=True, y=True, alpha=0.4) # Controls # https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html button_add_matcher = QtGui.QPushButton('New matcher', self) button_add_matcher.setIcon(QtGui.QIcon.fromTheme('list-add')) button_add_matcher.setToolTip('Add new curve matcher') button_add_matcher.clicked.connect(lambda: NewCurveMatcherWindow( self, lambda: sorted(self._active_messages), self. _add_curve_matcher).show()) button_clear_plots = QtGui.QPushButton('Clear plots', self) button_clear_plots.setIcon(QtGui.QIcon.fromTheme('edit-clear')) button_clear_plots.setToolTip('Clear the plotting area') button_clear_plots.clicked.connect(lambda: self._remove_all_curves()) def delete_all_matchers(): self._curve_matchers = [] for i in reversed(range(self._curve_matcher_container.count())): self._curve_matcher_container.itemAt(i).widget().deleteLater() self._remove_all_curves() button_delete_all_matchers = QtGui.QPushButton('Delete matchers', self) button_delete_all_matchers.setIcon( QtGui.QIcon.fromTheme('edit-delete')) button_delete_all_matchers.setToolTip('Delete all matchers') button_delete_all_matchers.clicked.connect(delete_all_matchers) self._autoscroll = QtGui.QCheckBox('Autoscroll', self) self._autoscroll.setChecked(True) self._max_x = self.INITIAL_X_RANGE # Layout control_panel = QHBoxLayout() control_panel.addWidget(button_add_matcher) control_panel.addWidget(button_clear_plots) control_panel.addWidget(self._autoscroll) control_panel.addStretch() control_panel.addWidget(button_delete_all_matchers) self._curve_matcher_container = QVBoxLayout() layout = QVBoxLayout() layout.addWidget(self._plot_widget, 1) layout.addLayout(control_panel) layout.addLayout(self._curve_matcher_container) self.setLayout(layout) # Logic self._color_index = 0 self._curves = {} self._message_queue = multiprocessing.Queue() self._active_messages = set() # set(data type name) self._curve_matchers = [] # Defaults self._add_curve_matcher( CurveMatcher('uavcan.protocol.debug.KeyValue', 'value', [('key', None)])) def _add_curve_matcher(self, matcher): self._curve_matchers.append(matcher) view = CurveMatcherView(matcher, self) def remove(): self._curve_matchers.remove(matcher) self._curve_matcher_container.removeWidget(view) view.setParent(None) view.deleteLater() view.on_remove = remove self._curve_matcher_container.addWidget(view) def _update(self): # Processing messages while True: try: m = self._message_queue.get_nowait() self._process_message(m) except queue.Empty: break # Updating curves for curve in self._curves.values(): if len(curve['x']): if len(curve['x']) > self.MAX_DATA_POINTS_PER_CURVE: curve['x'] = curve['x'][-self.MAX_DATA_POINTS_PER_CURVE:] curve['y'] = curve['y'][-self.MAX_DATA_POINTS_PER_CURVE:] assert len(curve['x']) == len(curve['y']) curve['plot'].setData(curve['x'], curve['y']) self._max_x = max(self._max_x, curve['x'][-1]) # Updating view range if self._autoscroll.checkState(): (xmin, xmax), _ = self._plot_widget.viewRange() diff = xmax - xmin xmax = self._max_x xmin = self._max_x - diff self._plot_widget.setRange(xRange=(xmin, xmax), padding=0) def _process_message(self, m): self._active_messages.add(m.data_type_name) for matcher in self._curve_matchers: if matcher.match(m): name, x, y = matcher.extract_curve_name_x_y(m) self._draw_curve(name, x, y) def _remove_all_curves(self): for curve in self._curves.values(): self._plot_widget.removeItem(curve['plot']) self._plot_widget.clear() self._curves = {} self._color_index = 0 self._legend.scene().removeItem(self._legend) self._legend = self._plot_widget.addLegend() def _draw_curve(self, name, x, y): if name not in self._curves: logging.info('Adding curve %r', name) color = self.COLORS[self._color_index % len(self.COLORS)] self._color_index += 1 pen = mkPen(QColor(color), width=1) plot = self._plot_widget.plot(name=name, pen=pen) self._curves[name] = { 'x': numpy.array([]), 'y': numpy.array([]), 'plot': plot } curve = self._curves[name] curve['x'] = numpy.append(curve['x'], [x] if isinstance(x, (float, int)) else x) curve['y'] = numpy.append(curve['y'], [y] if isinstance(y, (float, int)) else y) assert len(curve['x']) == len(curve['y']) def push_received_message(self, msg): self._message_queue.put_nowait(msg)
class DirectDriveWindow(QWidget): virtual_controller = None # will hold an instance of the VirtualController-class motor_controller = None # will hold an instance of the MotorController-class game_interfacer = None # will hold an instance of the GameInterfacer-class # Variables that will be shared between multiple processes raw_force_signal_global = Value( 'f', 0.0) # raw force-feedback value coming from the game game_status_playing_global = Value( 'b', False) # game status (playing/not-playing) motor_pause_mode = Value( 'b', False) # if the motor should be idle when game is paused data_reconstruction = Value( 'b', False) # if the data-reconstruction feature should be used data_smoothing_level = Value( 'i', 0) # if the temproal smoothing feature should be used friction_global = Value('f', 0.0) # strength of the friction effect damping_global = Value('f', 0.0) # strength of the damping effect inertia_global = Value('f', 0.0) # strength of the inertia effect encoder_pos_global = Value( 'f', 0.0) # holds the wheel position in encoder counts wheel_position_deg_global = Value( 'f', 0.0) # holds the wheel position in degrees lock_to_lock_global = Value( 'f', 900.0 ) # holds the digital limit of the wheel (used by the virtual controller) bump_to_bump_global = Value( 'f', 900.0 ) # holds the physical limit of the wheel (used by the motor controller) motor_current_global = Value( 'f', 0.0 ) # holds the current(Ampere) that is applied to the motor at any moment actual_max_force_global = Value( 'f', 0.0 ) # sets the actual maximum torque(Nm) the motor should be limited to invert_force_global = Value( 'b', False) # if the raw force-feedback value should be inverted motor_connected_global = Value( 'b', False) # motor status (connected/not-connected) motor_controller_due_for_restart_global = Value( 'b', False) # is set to true when connection to odrive board is lost motor_control_rate = Value( 'f', 0.0) # target refresh rate for the motor-control process profiles = [] # holds all loaded and newly created profiles selected_profile_index = 0 # holds the index of the currently selected profile graph_sample_rate = 60 # update-rate(Hz) for the motor-current graph graph_history_time_sec = 2 # time-window of the motor-current graph def __init__(self): super().__init__() self.setGeometry(100, 100, 1700, 575) self.setWindowTitle('DIY Direct Drive Wheel') #self.updater = LiveGuiUpdater() #self.updater.ticked.connect(self.LiveGuiTick) #self.updater.start() self.timer = QTimer() self.timer.timeout.connect(self.graph_update) self.timer.setInterval(int(1000 / self.graph_sample_rate)) self.timer.start() self.gui_timer = QTimer() self.gui_timer.timeout.connect(self.LiveGuiTick) self.gui_timer.setInterval(int(1000 / 60)) self.gui_timer.start() self.virtual_controller = VirtualController() self.virtual_controller.set_frequency(180) self.virtual_controller.steering_value_deg = self.wheel_position_deg_global self.virtual_controller.lock_to_lock = self.lock_to_lock_global self.virtual_controller.start() self.game_interfacer = GameInterfacer() self.game_interfacer.set_frequency(180) self.game_interfacer.wheel_force = self.raw_force_signal_global self.game_interfacer.invert_force = self.invert_force_global self.game_interfacer.game_status_playing = self.game_status_playing_global self.motor_controller = MotorController() self.motor_controller.set_frequency(360) self.motor_controller.signal_in = self.raw_force_signal_global self.motor_controller.game_status_playing = self.game_status_playing_global self.motor_controller.motor_pause_mode = self.motor_pause_mode self.motor_controller.data_reconstruction = self.data_reconstruction self.motor_controller.data_smoothing_level = self.data_smoothing_level self.motor_controller.friction = self.friction_global self.motor_controller.damping = self.damping_global self.motor_controller.inertia = self.inertia_global self.motor_controller.encoder_pos = self.encoder_pos_global self.motor_controller.wheel_pos_deg = self.wheel_position_deg_global self.motor_controller.bump_to_bump = self.bump_to_bump_global self.motor_controller.motor_current = self.motor_current_global self.motor_controller.actual_max_force = self.actual_max_force_global self.motor_controller.motor_connected = self.motor_connected_global self.motor_controller.due_for_restart = self.motor_controller_due_for_restart_global self.motor_controller.achieved_freq = self.motor_control_rate self.motor_controller.start() self.lblMotorRate = QLabel('motor control rate:', self) self.lblMotorRate.setFont(QFont("Times", 24, QFont.Normal)) self.lblMotorRate.move(675, 25) self.lblMotorRateHz = QLabel('0.00 Hz', self) self.lblMotorRateHz.setFont(QFont("Times", 24, QFont.Normal)) self.lblMotorRateHz.adjustSize() self.lblMotorRateHz.move(1125 - self.lblMotorRateHz.width(), 25) self.force_graph = PlotWidget(self) self.force_graph.move(675, 75) self.force_graph.resize(1000, 475) self.force_graph.setYRange(-15.0, 15.0) self.force_graph.setBackground((255, 255, 255)) self.force_graph.showGrid(x=False, y=True) self.force_graph.addLegend() pen_ffb = pg.mkPen(color=(0, 0, 255)) self.ffb_curve = self.force_graph.getPlotItem().plot( pen=pen_ffb, name='Game FFB (Nm)') pen_current = pg.mkPen(color=(0, 255, 0)) self.current_curve = self.force_graph.getPlotItem().plot( pen=pen_current, name='Motor Torque (Nm)') self.ffb_history = [ 0 ] * self.graph_sample_rate * self.graph_history_time_sec self.current_history = [ 0 ] * self.graph_sample_rate * self.graph_history_time_sec self.load_profiles_from_file() self.build_gui() self.select_profile(0) # updates the graph showing the raw ffb and the motor torque def graph_update(self): # adding the latest raw game-ffb value(scaled to the actual torque value) to a list storing a history of this value self.ffb_history.append(self.raw_force_signal_global.value / self.actual_max_force_global.value) if len(self.ffb_history ) >= self.graph_history_time_sec * self.graph_sample_rate: self.ffb_history.pop(0) self.ffb_curve.setData(self.ffb_history) # adding the latest final motor torque value to a list storing a history of this value self.current_history.append( self.motor_current_global.value / (self.actual_max_force_global.value * 2.75)) if len(self.current_history ) >= self.graph_history_time_sec * self.graph_sample_rate: self.current_history.pop(0) self.current_curve.setData(self.current_history) # displaying the actually achieved refresh rate of the motor-control process self.lblMotorRateHz.setText( str(int(self.motor_control_rate.value * 100) / 100) + ' Hz') if self.motor_control_rate.value >= 360.0: self.lblMotorRateHz.setStyleSheet( 'QLabel { color: rgb(0,155,0); }') else: self.lblMotorRateHz.setStyleSheet( 'QLabel { color: rgb(155,0,0); }') # initializes and configures all the GUI-elements def build_gui(self): # WHEEL POSITION DATA AND SETTINGS # current bar self.lblCurrent = QLabel(self) self.lblCurrent.move(25 + 128, 25) self.lblCurrent.resize(0, 25) self.lblCurrent.setAutoFillBackground(True) self.lblCurrent.setStyleSheet( 'QLabel { background-color: rgb(0,255,0); }') self.lblCurrentDivider = QLabel(self) self.lblCurrentDivider.move(25 + 128 - 1, 20) self.lblCurrentDivider.resize(2, 35) self.lblCurrentDivider.setAutoFillBackground(True) self.lblCurrentDivider.setStyleSheet( 'QLabel { background-color: rgb(0,0,0); }') # wheel image self.lblWheelImage = QLabel(self) self.wheel_image = QImage('wheel_image.png') self.wheel_image_discon = QImage('wheel_image_disconnect.png') self.wheel_pixmap = QPixmap.fromImage(self.wheel_image) self.lblWheelImage.setPixmap(self.wheel_pixmap) self.lblWheelImage.resize(self.wheel_pixmap.width(), self.wheel_pixmap.height()) self.lblWheelImage.move(25, 75) # motor status label self.lblMotorStatus_1 = QLabel('Motor Status:', self) self.lblMotorStatus_1.move(15, 60) self.lblMotorStatus_2 = QLabel('Not Connected', self) self.lblMotorStatus_2.move(15, 75) self.lblMotorStatus_2.setStyleSheet('QLabel { color: rgb(155,0,0); }') # wheel position self.lblWheelPos = QLabel('0.0°', self) self.lblWheelPos.move(25 + 150 + 25, 75 + 256 + 10) self.lblWheelPos.resize(200, 50) self.lblWheelPos.setFont(QFont("Times", 24, QFont.Normal)) # center button center_pos = [25, 75 + 256 + 22, 150, 30] self.btnCenter = QPushButton('center Wheel', self) self.btnCenter.move(center_pos[0], center_pos[1]) self.btnCenter.resize(center_pos[2], center_pos[3]) self.btnCenter.clicked.connect(self.center_wheel) # lock-to-lock slider self.locklock_pos = [25, 425, 250, 0] self.lblLock = QLabel('Lock to Lock:', self) self.lblLock.move(self.locklock_pos[0], self.locklock_pos[1]) self.sliLock = QSlider(Qt.Horizontal, self) self.sliLock.setTickPosition(QSlider.TicksAbove) self.sliLock.setTickInterval(10) self.sliLock.setMinimum(10) self.sliLock.setMaximum(120) self.sliLock.setValue(90) self.sliLock.setSingleStep(1) self.sliLock.move(self.locklock_pos[0], self.locklock_pos[1] + 20) self.sliLock.resize(self.locklock_pos[2], 25) self.sliLock.valueChanged.connect(self.change_lock) self.lblLockVal = QLabel('900°', self) self.lblLockVal.adjustSize() self.lblLockVal.move( self.locklock_pos[0] + self.locklock_pos[2] - self.lblLockVal.width(), self.locklock_pos[1]) # bump_to_bump slider self.bumpbump_pos = [25, 500, 250, 0] self.lblBump = QLabel('Bump to Bump:', self) self.lblBump.move(self.bumpbump_pos[0], self.bumpbump_pos[1]) self.sliBump = QSlider(Qt.Horizontal, self) self.sliBump.setTickPosition(QSlider.TicksAbove) self.sliBump.setTickInterval(10) self.sliBump.setMinimum(10) self.sliBump.setMaximum(120) self.sliBump.setValue(90) self.sliBump.setSingleStep(1) self.sliBump.move(self.bumpbump_pos[0], self.bumpbump_pos[1] + 20) self.sliBump.resize(self.bumpbump_pos[2], 25) self.sliBump.valueChanged.connect(self.change_bump) self.lblBumpVal = QLabel('900°', self) self.lblBumpVal.adjustSize() self.lblBumpVal.move( self.bumpbump_pos[0] + self.bumpbump_pos[2] - self.lblBumpVal.width(), self.bumpbump_pos[1]) # WHEEL FORCE AND BEHAVIOR SETTINGS # game select combobox gameselect_pos = [325, 25, 250, 25] self.cbxGame = QComboBox(self) self.cbxGame.move(gameselect_pos[0], gameselect_pos[1]) self.cbxGame.resize(gameselect_pos[2], gameselect_pos[3]) for game in self.game_interfacer.games_available: self.cbxGame.addItem(game) self.cbxGame.activated.connect(self.select_game) # invert force checkbox invert_pos = [325, 55] self.cbInvert = QCheckBox('Invert Force Feedback', self) self.cbInvert.move(invert_pos[0], invert_pos[1]) self.cbInvert.stateChanged.connect(self.toggle_invert) # motor pause mode checkbox motorpause_pos = [325, 85] self.cbMotorPause = QCheckBox('pause motor when game is paused', self) self.cbMotorPause.move(motorpause_pos[0], motorpause_pos[1]) self.cbMotorPause.stateChanged.connect(self.toggle_motor_pause_mode) self.cbMotorPause.toggle() # maximum force slider self.max_force_pos = [325, 125, 250, 0] self.lblMaxForce = QLabel('Maximum Force in Nm:', self) self.lblMaxForce.move(self.max_force_pos[0], self.max_force_pos[1]) self.sliMaxForce = QSlider(Qt.Horizontal, self) self.sliMaxForce.setTickPosition(QSlider.TicksAbove) self.sliMaxForce.setTickInterval(10) self.sliMaxForce.setMinimum(1) self.sliMaxForce.setMaximum(150) self.sliMaxForce.setValue(0) self.sliMaxForce.setSingleStep(1) self.sliMaxForce.move(self.max_force_pos[0], self.max_force_pos[1] + 20) self.sliMaxForce.resize(self.max_force_pos[2], 25) self.sliMaxForce.valueChanged.connect(self.change_max_force) self.lblMaxForceVal = QLabel('0.0 Nm - (0.0 Amp)', self) self.lblMaxForceVal.adjustSize() self.lblMaxForceVal.move( self.max_force_pos[0] + self.max_force_pos[2] - self.lblMaxForceVal.width(), self.max_force_pos[1]) # reconstruction checkbox reconst_pos = [325, 175 + 3] self.cbReconst = QCheckBox('Use Data Reconstruction', self) self.cbReconst.move(reconst_pos[0], reconst_pos[1]) self.cbReconst.stateChanged.connect(self.toggle_reconstruction) self.cbReconst.setEnabled(False) # smoothing level combobox smoothing_pos = [475, 175, 100, 25] self.cbxSmoothing = QComboBox(self) self.cbxSmoothing.move(smoothing_pos[0], smoothing_pos[1]) self.cbxSmoothing.resize(smoothing_pos[2], smoothing_pos[3]) self.cbxSmoothing.addItem('no Smoothing') self.cbxSmoothing.addItem('1') self.cbxSmoothing.addItem('2') self.cbxSmoothing.addItem('3') self.cbxSmoothing.addItem('4') self.cbxSmoothing.addItem('5') self.cbxSmoothing.addItem('6') self.cbxSmoothing.addItem('7') self.cbxSmoothing.addItem('8') self.cbxSmoothing.addItem('9') self.cbxSmoothing.activated.connect(self.change_smoothing) self.cbxSmoothing.setEnabled(False) # friction slider self.friction_pos = [325, 215, 250, 0] self.lblFriction = QLabel('Friction:', self) self.lblFriction.move(self.friction_pos[0], self.friction_pos[1]) self.sliFriction = QSlider(Qt.Horizontal, self) self.sliFriction.setTickPosition(QSlider.TicksAbove) self.sliFriction.setTickInterval(10) self.sliFriction.setMinimum(0) self.sliFriction.setMaximum(100) self.sliFriction.setValue(0) self.sliFriction.setSingleStep(1) self.sliFriction.move(self.friction_pos[0], self.friction_pos[1] + 20) self.sliFriction.resize(self.friction_pos[2], 25) self.sliFriction.valueChanged.connect(self.change_friction) self.lblFrictionVal = QLabel('0 %', self) self.lblFrictionVal.adjustSize() self.lblFrictionVal.move( self.friction_pos[0] + self.friction_pos[2] - self.lblFrictionVal.width(), self.friction_pos[1]) # damping slider self.damping_pos = [325, 275, 250, 0] self.lblDamping = QLabel('Damping:', self) self.lblDamping.move(self.damping_pos[0], self.damping_pos[1]) self.sliDamping = QSlider(Qt.Horizontal, self) self.sliDamping.setTickPosition(QSlider.TicksAbove) self.sliDamping.setTickInterval(10) self.sliDamping.setMinimum(0) self.sliDamping.setMaximum(100) self.sliDamping.setValue(0) self.sliDamping.setSingleStep(1) self.sliDamping.move(self.damping_pos[0], self.damping_pos[1] + 20) self.sliDamping.resize(self.damping_pos[2], 25) self.sliDamping.valueChanged.connect(self.change_damping) self.lblDampingVal = QLabel('0 %', self) self.lblDampingVal.adjustSize() self.lblDampingVal.move( self.damping_pos[0] + self.damping_pos[2] - self.lblDampingVal.width(), self.damping_pos[1]) # inertia slider self.inertia_pos = [325, 335, 250, 0] self.lblInertia = QLabel('Inertia:', self) self.lblInertia.move(self.inertia_pos[0], self.inertia_pos[1]) self.sliInertia = QSlider(Qt.Horizontal, self) self.sliInertia.setTickPosition(QSlider.TicksAbove) self.sliInertia.setTickInterval(10) self.sliInertia.setMinimum(0) self.sliInertia.setMaximum(100) self.sliInertia.setValue(0) self.sliInertia.setSingleStep(1) self.sliInertia.move(self.inertia_pos[0], self.inertia_pos[1] + 20) self.sliInertia.resize(self.inertia_pos[2], 25) self.sliInertia.valueChanged.connect(self.change_inertia) self.lblInertiaVal = QLabel('0 %', self) self.lblInertiaVal.adjustSize() self.lblInertiaVal.move( self.inertia_pos[0] + self.inertia_pos[2] - self.lblInertiaVal.width(), self.inertia_pos[1]) # profile select combobox profileselect_pos = [325, 430, 250, 25] self.cbxProfiles = QComboBox(self) self.cbxProfiles.move(profileselect_pos[0], profileselect_pos[1]) self.cbxProfiles.resize(profileselect_pos[2], profileselect_pos[3]) for profile in self.profiles: self.cbxProfiles.addItem(profile.name) self.cbxProfiles.activated.connect(self.select_profile) # create profile button profilecreate_pos = [325, 460, 250, 25] self.btnCreate = QPushButton('create new profile', self) self.btnCreate.move(profilecreate_pos[0], profilecreate_pos[1]) self.btnCreate.resize(profilecreate_pos[2], profilecreate_pos[3]) self.btnCreate.clicked.connect(self.create_profile) # rename profile button profilerename_pos = [325, 490, 250, 25] self.btnRename = QPushButton('rename profile', self) self.btnRename.move(profilerename_pos[0], profilerename_pos[1]) self.btnRename.resize(profilerename_pos[2], profilerename_pos[3]) self.btnRename.clicked.connect(self.rename_profile) # cancel rename button cancelrename_pos = [325 + 200, 490, 50, 25] self.btnCancelRename = QPushButton('cancel', self) self.btnCancelRename.move(cancelrename_pos[0], cancelrename_pos[1]) self.btnCancelRename.resize(cancelrename_pos[2], cancelrename_pos[3]) self.btnCancelRename.clicked.connect(self.cancel_rename) self.btnCancelRename.setVisible(False) # rename textbox self.txtRename = QLineEdit(self) self.txtRename.move(profilerename_pos[0], profilerename_pos[1]) self.txtRename.resize(profilerename_pos[2] - 35 - 55, profilerename_pos[3]) self.txtRename.setVisible(False) self.txtRename.textChanged.connect(self.check_name_validity) # save profile button profilesave_pos = [325, 520, 120, 25] self.btnSave = QPushButton('save profile', self) self.btnSave.move(profilesave_pos[0], profilesave_pos[1]) self.btnSave.resize(profilesave_pos[2], profilesave_pos[3]) self.btnSave.clicked.connect(self.save_current_profile_internally) # delete profile button profiledelete_pos = [325 + 130, 520, 120, 25] self.btnDelete = QPushButton('delete profile', self) self.btnDelete.move(profiledelete_pos[0], profiledelete_pos[1]) self.btnDelete.resize(profiledelete_pos[2], profiledelete_pos[3]) self.btnDelete.clicked.connect(self.delete_current_profile) # updates the GUI-elements that indicate the status of the motor (connected/not-connected) def LiveGuiTick(self): self.lblWheelPos.setText( str(int(self.wheel_position_deg_global.value * 10) / 10) + '°') self.lblCurrent.resize( int( np.abs(self.motor_current_global.value / (self.actual_max_force_global.value * 2.75) * 128)), 25) if self.motor_current_global.value < 0.0: self.lblCurrent.move( 25 + 128 - np.abs(self.motor_current_global.value / (self.actual_max_force_global.value * 2.75) * 128), 25) tf = QTransform() tf.rotate(self.wheel_position_deg_global.value) if self.motor_connected_global.value: self.lblMotorStatus_2.setText('Connected') self.lblMotorStatus_2.setStyleSheet( 'QLabel { color: rgb(0,155,0); }') img_rot = self.wheel_image.transformed(tf) self.btnCenter.setEnabled(True) self.lblWheelPos.setStyleSheet('QLabel { color: rgb(0,0,0); }') else: self.lblMotorStatus_2.setText('Not Connected') self.lblMotorStatus_2.setStyleSheet( 'QLabel { color: rgb(155,0,0); }') img_rot = self.wheel_image_discon.transformed(tf) self.btnCenter.setEnabled(False) self.lblWheelPos.setStyleSheet( 'QLabel { color: rgb(155,155,155); }') diagonal_overlength = (np.sqrt(np.square(256) * 2) - 256) / 2 shift = int( np.abs( np.sin(np.deg2rad(self.wheel_position_deg_global.value * 2)) * diagonal_overlength)) crop_rect = QRect(shift, shift, 256, 256) self.wheel_pixmap = QPixmap.fromImage(img_rot).copy(crop_rect) self.lblWheelImage.setPixmap(self.wheel_pixmap) if self.motor_controller_due_for_restart_global.value: self.motor_controller_due_for_restart_global.value = False print('restarting motor...') try: self.motor_controller.motor_control_process.terminate() except: pass self.motor_controller.start() # helper function to get the index of a profile with a certain name from the profile-list def get_profile_index(self, name): for i in range(len(self.profiles)): if self.profiles[i].name == name: return i # WHEEL POSITION SETTING FUNCTIONS def center_wheel(self): print('centering wheel') self.motor_controller.set_encoder_offset() def change_lock(self): val = int(self.sender().value() * 10) self.lblLockVal.setText(str(val) + '°') self.lock_to_lock_global.value = val self.lblLockVal.adjustSize() self.lblLockVal.move( self.locklock_pos[0] + self.locklock_pos[2] - self.lblLockVal.width(), self.locklock_pos[1]) def change_bump(self): val = int(self.sender().value() * 10) self.lblBumpVal.setText(str(val) + '°') self.bump_to_bump_global.value = val self.lblBumpVal.adjustSize() self.lblBumpVal.move( self.bumpbump_pos[0] + self.bumpbump_pos[2] - self.lblBumpVal.width(), self.bumpbump_pos[1]) # WHEEL FORCE SETTING FUNCTIONS def select_game(self, item_index): print('selecting', item_index) self.game_interfacer.terminate() time.sleep(1) self.game_interfacer.start(item_index) def toggle_invert(self, state): if state == Qt.Checked: self.invert_force_global.value = True else: self.invert_force_global.value = False def toggle_motor_pause_mode(self, state): if state == Qt.Checked: self.motor_pause_mode.value = True else: self.motor_pause_mode.value = False def change_max_force(self): val = self.sender().value() / 10 self.lblMaxForceVal.setText( str(val) + ' Nm - (' + str(int(val * 2.75 * 100) / 100) + ' Amp)') self.actual_max_force_global.value = val self.lblMaxForceVal.adjustSize() self.lblMaxForceVal.move( self.max_force_pos[0] + self.max_force_pos[2] - self.lblMaxForceVal.width(), self.max_force_pos[1]) self.force_graph.setYRange(-val, val) def change_friction(self): val = self.sender().value() / 100 self.lblFrictionVal.setText(str(int(val * 100)) + ' %') self.friction_global.value = val self.lblFrictionVal.adjustSize() self.lblFrictionVal.move( self.friction_pos[0] + self.friction_pos[2] - self.lblFrictionVal.width(), self.friction_pos[1]) def change_damping(self): val = self.sender().value() / 100 self.lblDampingVal.setText(str(int(val * 100)) + ' %') self.damping_global.value = val self.lblDampingVal.adjustSize() self.lblDampingVal.move( self.damping_pos[0] + self.damping_pos[2] - self.lblDampingVal.width(), self.damping_pos[1]) def change_inertia(self): val = self.sender().value() / 100 self.lblInertiaVal.setText(str(int(val * 100)) + ' %') self.inertia_global.value = val self.lblInertiaVal.adjustSize() self.lblInertiaVal.move( self.inertia_pos[0] + self.inertia_pos[2] - self.lblInertiaVal.width(), self.inertia_pos[1]) def toggle_reconstruction(self, state): if state == Qt.Checked: self.data_reconstruction.value = True else: self.data_reconstruction.value = False def change_smoothing(self, item_index): self.data_smoothing_level.value = item_index def select_profile(self, selected_profile): self.sliLock.setValue( int(self.profiles[selected_profile].lock_to_lock / 10)) self.sliBump.setValue( int(self.profiles[selected_profile].bump_to_bump / 10)) self.cbInvert.setChecked( bool(self.profiles[selected_profile].invert_force)) self.sliMaxForce.setValue( int(self.profiles[selected_profile].max_force * 10)) self.cbReconst.setChecked( bool(self.profiles[selected_profile].use_reconstruction)) self.cbxSmoothing.setCurrentIndex( int(self.profiles[selected_profile].smoothing_level)) self.sliFriction.setValue( int(self.profiles[selected_profile].friction * 100)) self.sliDamping.setValue( int(self.profiles[selected_profile].damping * 100)) self.sliInertia.setValue( int(self.profiles[selected_profile].inertia * 100)) def save_current_profile_internally(self): current_index = self.cbxProfiles.currentIndex() self.profiles[ current_index].lock_to_lock = self.lock_to_lock_global.value self.profiles[ current_index].bump_to_bump = self.bump_to_bump_global.value self.profiles[ current_index].invert_force = self.invert_force_global.value self.profiles[ current_index].max_force = self.actual_max_force_global.value self.profiles[ current_index].use_reconstruction = self.data_reconstruction.value self.profiles[ current_index].smoothing_level = self.data_smoothing_level.value self.profiles[current_index].friction = self.friction_global.value self.profiles[current_index].damping = self.damping_global.value self.profiles[current_index].inertia = self.inertia_global.value self.save_profiles_to_file() def save_profiles_to_file(self): root = ET.Element('profiles') for profile in self.profiles: prof_elem = ET.SubElement(root, 'profile', name=profile.name) ET.SubElement(prof_elem, 'lock_to_lock').text = str(profile.lock_to_lock) ET.SubElement(prof_elem, 'bump_to_bump').text = str(profile.bump_to_bump) ET.SubElement(prof_elem, 'invert_force').text = str( bool(profile.invert_force)) ET.SubElement(prof_elem, 'max_force').text = str(profile.max_force) ET.SubElement(prof_elem, 'use_reconstruction').text = str( bool(profile.use_reconstruction)) ET.SubElement(prof_elem, 'smoothing_level').text = str( profile.smoothing_level) ET.SubElement(prof_elem, 'friction').text = str(profile.friction) ET.SubElement(prof_elem, 'damping').text = str(profile.damping) ET.SubElement(prof_elem, 'inertia').text = str(profile.inertia) tree = ET.ElementTree(root) tree.write("profiles.xml") def load_profiles_from_file(self): self.profiles.clear() tree = ET.parse('profiles.xml') root = tree.getroot() for prof in root: profile = Profile(prof.attrib['name']) profile.lock_to_lock = float(prof[0].text) profile.bump_to_bump = float(prof[1].text) profile.invert_force = bool(prof[2].text == 'True') profile.max_force = float(prof[3].text) profile.use_reconstruction = bool(prof[4].text == 'True') profile.smoothing_level = int(prof[5].text) profile.friction = float(prof[6].text) profile.damping = float(prof[7].text) profile.inertia = float(prof[8].text) self.profiles.append(profile) def delete_current_profile(self): current_index = self.cbxProfiles.currentIndex() print('deleting profile at index:', current_index) self.profiles.pop(current_index) self.cbxProfiles.clear() for profile in self.profiles: self.cbxProfiles.addItem(profile.name) self.cbxProfiles.setCurrentIndex(0) self.select_profile(0) self.save_current_profile_internally() if len(self.profiles) == 1: self.btnDelete.setEnabled(False) def create_profile(self): new_profile = Profile('profile #' + str(len(self.profiles) + 1)) current_index = self.cbxProfiles.currentIndex() new_profile.lock_to_lock = self.profiles[current_index].lock_to_lock new_profile.bump_to_bump = self.profiles[current_index].bump_to_bump new_profile.invert_force = self.profiles[current_index].invert_force new_profile.max_force = self.profiles[current_index].max_force new_profile.use_reconstruction = self.profiles[ current_index].use_reconstruction new_profile.smoothing_level = self.profiles[ current_index].smoothing_level new_profile.friction = self.profiles[current_index].friction new_profile.damping = self.profiles[current_index].damping new_profile.inertia = self.profiles[current_index].inertia self.profiles.append(new_profile) self.cbxProfiles.clear() for profile in self.profiles: self.cbxProfiles.addItem(profile.name) self.cbxProfiles.setCurrentIndex(len(self.profiles) - 1) self.select_profile(len(self.profiles) - 1) self.save_current_profile_internally() if len(self.profiles) > 1: self.btnDelete.setEnabled(True) def rename_profile(self): rename_pos = [325, 490, 250, 25] if self.sender().text() == 'rename profile': self.sender().setText('OK') self.sender().move(rename_pos[0] + 220 - 55, rename_pos[1]) self.sender().resize(rename_pos[2] - 220, rename_pos[3]) self.cbxProfiles.setEnabled(False) self.btnCreate.setEnabled(False) self.btnSave.setEnabled(False) self.btnDelete.setEnabled(False) self.btnCancelRename.setVisible(True) self.txtRename.setVisible(True) current_index = self.cbxProfiles.currentIndex() self.txtRename.setText(self.profiles[current_index].name) else: self.sender().setText('rename profile') self.sender().move(rename_pos[0], rename_pos[1]) self.sender().resize(rename_pos[2], rename_pos[3]) self.cbxProfiles.setEnabled(True) self.btnCreate.setEnabled(True) self.btnSave.setEnabled(True) self.btnDelete.setEnabled(True) self.btnCancelRename.setVisible(False) self.txtRename.setVisible(False) current_index = self.cbxProfiles.currentIndex() self.profiles[current_index].name = self.txtRename.text() self.cbxProfiles.clear() for profile in self.profiles: self.cbxProfiles.addItem(profile.name) self.cbxProfiles.setCurrentIndex(current_index) self.select_profile(current_index) self.save_current_profile_internally() def cancel_rename(self): rename_pos = [325, 490, 250, 25] self.btnRename.setText('rename profile') self.btnRename.move(rename_pos[0], rename_pos[1]) self.btnRename.resize(rename_pos[2], rename_pos[3]) self.cbxProfiles.setEnabled(True) self.btnCreate.setEnabled(True) self.btnSave.setEnabled(True) self.btnDelete.setEnabled(True) self.btnCancelRename.setVisible(False) self.txtRename.setVisible(False) def check_name_validity(self, text): if text == '': self.btnRename.setEnabled(False) else: self.btnRename.setEnabled(True)
class FindPeak(QWidget): def __init__(self, parent, x_data, y_data): super(FindPeak, self).__init__() self.parent = parent self.x = x_data self.y = y_data self.lower = np.min(x_data) self.upper = np.max(x_data) self.range = self.upper - self.lower self.renderWindow() self.initPlotView() self.drawCurve() self.setUpProcessUI() self.bindEvents() self.integral(x_data, y_data, self.lower, self.upper) def bindEvents(self): self.bindBoundEvent() self.bindAlgorithmEvent() self.bindFindEvent() def bindBoundEvent(self): def leftBoundEvent(x): self.lower = x upper = self.upper self.plotRegion.setRegion([x, upper]) self.rightBound.setMinimum(x) self.peakCenter.setMinimum(x) self.peakCenter.setValue((x + upper) / 2) self.integral(self.x, self.y, x, upper) def rightBoundEvent(x): self.upper = x lower = self.lower self.plotRegion.setRegion([lower, x]) self.leftBound.setMaximum(x) self.peakCenter.setMaximum(x) self.peakCenter.setValue((x + lower) / 2) self.integral(self.x, self.y, lower, x) def regionChangeEvent(): lower, upper = self.plotRegion.getRegion() self.lower = lower self.upper = upper self.leftBound.setValue(lower) self.leftBound.setMaximum(upper) self.rightBound.setValue(upper) self.rightBound.setMinimum(lower) self.peakCenter.setMinimum(lower) self.peakCenter.setMaximum(upper) self.peakCenter.setValue((lower + upper) / 2) self.integral(self.x, self.y, lower, upper) self.leftBound.valueChanged.connect(leftBoundEvent) self.rightBound.valueChanged.connect(rightBoundEvent) self.plotRegion.sigRegionChanged.connect(regionChangeEvent) def bindAlgorithmEvent(self): def updateInput(a, b, c, d, e, f): self.peakWidth.setEnabled(a) self.detectDis.setEnabled(b) self.noisePrt.setEnabled(c) self.amplitude.setEnabled(d) self.threshold.setEnabled(e) self.findBtn.setEnabled(f) def changeAlgorithm(algorithm): if algorithm == "Extremum": updateInput(False, False, False, False, False, True) pass elif algorithm == "Matlab Like": updateInput(True, True, False, True, True, True) pass elif algorithm == "Gaussian": updateInput(False, False, False, False, False, False) pass elif algorithm == "Lorentzian": updateInput(False, False, False, False, False, False) pass elif algorithm == "Pseudo-Voigt": updateInput(False, False, False, False, False, False) pass elif algorithm == "Wavelet Transform": updateInput(True, True, True, False, False, False) pass self.algorithm.currentTextChanged.connect(changeAlgorithm) updateInput(False, False, False, False, False, True) def integral(self, x_data, y_data, lower, upper): idx = np.where((x_data >= lower) & (x_data <= upper)) x = x_data[idx] y = y_data[idx] self.integralArea.setValue(simps(y, x)) def bindFindEvent(self): x_data = self.x y_data = self.y def findPeak(): region = np.where((x_data >= self.lower) & (x_data <= self.upper)) sub_data = y_data[region] sub_region = x_data[region] algorithm = self.algorithm.currentText() shape = self.shape.currentText() if shape == "Peak": const = 1 else: const = -1 sub_data = sub_data * const if algorithm == "Extremum": peak = np.max(sub_data) idx = np.where(sub_data == peak) x = sub_region[idx][0] y = sub_data[idx][0] * const self.peakCenter.setValue(x) return self.renderPeakPoint([x, y]) elif algorithm == "Matlab Like": indexes = find_peaks( sub_data, height=self.amplitude.value(), #低于指定高度忽略 threshold=self.threshold.value(), #相邻两点高度差 distance=self.detectDis.value(), #两峰间距 width=self.peakWidth.value() #峰宽 )[0] if np.size(indexes) == 0: return idx = np.where(sub_data == np.max(sub_data[indexes])) x = sub_region[idx][0] y = sub_data[idx][0] * const self.peakCenter.setValue(x) return self.renderPeakPoint([x, y]) elif algorithm == "Wavelet Transform": indexes = find_peaks_cwt( sub_data, widths=self.peakWidth.value(), #峰宽 max_distances=self.detectDis.value(), #两峰间距 noise_perc=self.noisePrt.value())[0] if np.size(indexes) == 0: return idx = np.where(sub_data == np.max(sub_data[indexes])) x = sub_region[idx][0] y = sub_data[idx][0] * const self.peakCenter.setValue(x) return self.renderPeakPoint([x, y]) self.noisePrt pass self.findBtn.clicked.connect(findPeak) def renderPeakPoint(self, pos): self.peakPoint.clear() self.peakPoint.addPoints([{'pos': pos, 'data': 1}]) def renderWindow(self): #边框结构 self.setGeometry(80, 80, 800, 420) size = self.geometry() screen = QDesktopWidget().screenGeometry() posX = (screen.width() - size.width()) / 2 posY = (screen.height() - size.height()) / 2 self.move(posX, posY) #标题 self.setWindowTitle('Find Peak') self.setWindowIcon(QIcon('resource/curve.ico')) #布局 layout = QGridLayout() self.graphicsView = QGridLayout() layout.addLayout(self.graphicsView, 0, 0, 1, 1) self.Process_Box = QGroupBox() self.Process_Box.setMinimumSize(200, 420) self.Process_Box.setFlat(True) layout.addWidget(self.Process_Box, 0, 1, 1, 1) self.setLayout(layout) def setUpProcessUI(self): layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) layout.setSpacing(10) self.Process_Box.setLayout(layout) layout.addWidget(QLabel(self.translate('Left Boundary')), 0, 0, 1, 1) layout.addWidget(QLabel(self.translate('Right Boundary')), 1, 0, 1, 1) layout.addWidget(QLabel(self.translate("Integral Area")), 2, 0, 1, 1) layout.addWidget(QLabel(self.translate('Peak Center')), 3, 0, 1, 1) layout.addWidget(QLabel(self.translate('Peak Shape')), 4, 0, 1, 1) layout.addWidget(QLabel(self.translate('Find Peak Algorithm')), 5, 0, 1, 1) layout.addWidget(QLabel(self.translate('Minimum Peak Width')), 6, 0, 1, 1) layout.addWidget(QLabel(self.translate('Minimum Detect Distance')), 7, 0, 1, 1) layout.addWidget(QLabel(self.translate('Noise Percent')), 8, 0, 1, 1) layout.addWidget(QLabel(self.translate("Minimum Amplitude")), 9, 0, 1, 1) layout.addWidget(QLabel(self.translate("Relative Threshold")), 10, 0, 1, 1) self.leftBound = SpinBox(lower=self.lower, dec=4, val=self.lower) self.rightBound = SpinBox(upper=self.upper, dec=4, val=self.upper) self.peakCenter = SpinBox(lower=self.lower, upper=self.upper, dec=4) self.peakWidth = SpinBox(lower=1, upper=10000, val=5) self.noisePrt = SpinBox(lower=0, upper=100, step=1, val=10) self.detectDis = SpinBox(lower=1, val=3) self.amplitude = SpinBox(lower=-1E5, upper=1E5, dec=4, val=-1) self.threshold = SpinBox(lower=0, upper=100, dec=4, val=0.001) self.integralArea = SpinBox(upper=1E8, dec=4) self.integralArea.setReadOnly(True) self.integralArea.setButtonSymbols(QAbstractSpinBox.NoButtons) self.shape = QComboBox() self.shape.addItems(["Peak", "Valley"]) #self.shape.currentTextChanged.connect() self.algorithm = QComboBox() self.algorithm.addItems([ 'Extremum', 'Matlab Like', 'Wavelet Transform', 'Gaussian', 'Lorentzian', 'Pseudo-Voigt' ]) #self.algorithm.currentTextChanged.connect() #https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks_cwt.html layout.addWidget(self.leftBound, 0, 1, 1, 1) layout.addWidget(self.rightBound, 1, 1, 1, 1) layout.addWidget(self.integralArea, 2, 1, 1, 1) layout.addWidget(self.peakCenter, 3, 1, 1, 1) layout.addWidget(self.shape, 4, 1, 1, 1) layout.addWidget(self.algorithm, 5, 1, 1, 1) layout.addWidget(self.peakWidth, 6, 1, 1, 1) layout.addWidget(self.detectDis, 7, 1, 1, 1) layout.addWidget(self.noisePrt, 8, 1, 1, 1) layout.addWidget(self.amplitude, 9, 1, 1, 1) layout.addWidget(self.threshold, 10, 1, 1, 1) self.findBtn = QPushButton(self.translate('Find Peak')) layout.addWidget(self.findBtn, 11, 0, 1, 2) pass def initPlotView(self): self.plot = PlotWidget(enableAutoRange=True) self.plot.setXRange(self.lower - self.range * 0.05, self.upper + self.range * 0.05) self.plotLegand = self.plot.addLegend() self.graphicsView.addWidget(self.plot) self.plotRegion = LinearRegionItem() self.plotRegion.setZValue(10) self.peakPoint = ScatterPlotItem(size=8, pen=mkPen(color='0000FF', width=2), symbol="+", brush=mkBrush(255, 255, 255, 240)) self.plot.addItem(self.plotRegion, ignoreBounds=True) self.plot.addItem(self.peakPoint) self.setGraphViewStyle() def setGraphViewStyle(self): self.plot.setAutoVisible(y=True) self.plot.setBackground('#ffffff') self.plot.showGrid(x=True, y=True, alpha=0.25) self.plot.getAxis('bottom').setPen(color='#000000', width=1.5) self.plot.getAxis('left').setPen(color='#000000', width=1.5) self.plotRegion.setRegion([self.lower, self.upper]) self.plotRegion.setBounds([self.lower, self.upper]) def drawCurve(self): pen = mkPen(color='FF0000', width=2) self.plot.plot(self.x, self.y, pen=pen) self.plot.show() def translate(self, text): if self.parent: self.langText = self.parent.langText else: self.langText = load(open('SCN.translation', encoding='utf-8')) if text in self.langText: return self.langText[text] return text
class Ui_CovidTracker(object): def setupUi(self, CovidTracker): CovidTracker.setObjectName("CovidTracker") CovidTracker.resize(988, 823) self.centralwidget = QtWidgets.QWidget(CovidTracker) self.centralwidget.setObjectName("centralwidget") #plot tab self.plot_tab = QtWidgets.QTabWidget(self.centralwidget) self.plot_tab.setGeometry(QtCore.QRect(10, 310, 971, 451)) self.plot_tab.setObjectName("plot_tab") self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.graphicsView = PlotWidget(self.tab) self.graphicsView.setGeometry(QtCore.QRect(0, 0, 961, 421)) self.graphicsView.setObjectName("graphicsView") self.plot_tab.addTab(self.tab, "") self.tab_2 = QtWidgets.QWidget() self.tab_2.setObjectName("tab_2") self.graphicsView_2 = PlotWidget(self.tab_2) self.graphicsView_2.setGeometry(QtCore.QRect(0, 0, 961, 421)) self.graphicsView_2.setObjectName("graphicsView_2") self.plot_tab.addTab(self.tab_2, "") # self.plot_tab.addTab(self.tab, "") # self.tab_3 = QtWidgets.QWidget() # self.tab_3.setObjectName("tab_3") # self.graphicsView_3 = GraphicsLayoutWidget(self.tab_3) # self.graphicsView_3.setGeometry(QtCore.QRect(0, 0, 961, 421)) # self.graphicsView_3.setObjectName("graphicsView_3") # self.plot_tab.addTab(self.tab_3, "") #country name self.country_name = QtWidgets.QLineEdit(self.centralwidget) self.country_name.setGeometry(QtCore.QRect(850, 150, 113, 22)) self.country_name.setObjectName("country_name") #track button self.track_button = QtWidgets.QPushButton(self.centralwidget) self.track_button.setGeometry(QtCore.QRect(850, 180, 111, 31)) self.track_button.setObjectName("track_button") self.track_button.clicked.connect(self.get_covid) #speak button self.speak_button = QtWidgets.QPushButton(self.centralwidget) self.speak_button.setGeometry(QtCore.QRect(850, 220, 111, 28)) self.speak_button.setObjectName("speak_button") self.speak_button.clicked.connect(self.start_record) #reset button self.reset_button = QtWidgets.QPushButton(self.centralwidget) self.reset_button.setGeometry(QtCore.QRect(850, 260, 111, 28)) self.reset_button.setObjectName("reset_button") self.reset_button.clicked.connect(self.reset_covid) #data_table self.data_table = QtWidgets.QTableWidget(self.centralwidget) self.data_table.setGeometry(QtCore.QRect(10, 150, 441, 141)) self.data_table.setObjectName("data_table") self.data_table.setColumnCount(4) self.data_table.setRowCount(0) item = QtWidgets.QTableWidgetItem() self.data_table.setHorizontalHeaderItem(0, item) item = QtWidgets.QTableWidgetItem() self.data_table.setHorizontalHeaderItem(1, item) item = QtWidgets.QTableWidgetItem() self.data_table.setHorizontalHeaderItem(2, item) item = QtWidgets.QTableWidgetItem() self.data_table.setHorizontalHeaderItem(3, item) #progress bar self.progressBar = QtWidgets.QProgressBar(self.centralwidget) self.progressBar.setGeometry(QtCore.QRect(10, 770, 961, 23)) self.progressBar.setProperty("value", 0) self.progressBar.setObjectName("progressBar") self.progressBar.setMaximum(100) # plot type combo self.plot_type = QtWidgets.QComboBox(self.centralwidget) self.plot_type.setGeometry(QtCore.QRect(850, 120, 111, 22)) self.plot_type.setObjectName("plot_type") self.plot_type.addItem("") self.plot_type.addItem("") self.plot_type.addItem("") self.plot_type.addItem("") #dark_light combo self.dark_light = QtWidgets.QComboBox(self.centralwidget) self.dark_light.setGeometry(QtCore.QRect(850, 90, 111, 22)) self.dark_light.setObjectName("dark_light") self.dark_light.addItem("") self.dark_light.addItem("") self.dark_light.currentIndexChanged.connect(self.mode_change) #animated checkbox self.animated_checkbox = QtWidgets.QCheckBox(self.centralwidget) self.animated_checkbox.setGeometry(QtCore.QRect(870, 300, 101, 20)) self.animated_checkbox.setObjectName("animated_checkbox") #self.animated_checkbox.stateChanged.connect(self.check_box_state_change) # simple horizontal line self.line = QtWidgets.QFrame(self.centralwidget) self.line.setGeometry(QtCore.QRect(10, 290, 951, 16)) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") # history log box self.text_holder = QtWidgets.QTextBrowser(self.centralwidget) self.text_holder.setGeometry(QtCore.QRect(465, 151, 371, 141)) self.text_holder.setObjectName("text_holder") # main label self.main_label = QtWidgets.QLabel(self.centralwidget) self.main_label.setGeometry(QtCore.QRect(400, 30, 261, 41)) font = QtGui.QFont() font.setFamily("Jokerman") font.setPointSize(14) self.main_label.setFont(font) self.main_label.setObjectName("main_label") # history label self.history_label = QtWidgets.QLabel(self.centralwidget) self.history_label.setGeometry(QtCore.QRect(500, 130, 71, 16)) self.history_label.setObjectName("history_label") # data label self.data_label = QtWidgets.QLabel(self.centralwidget) self.data_label.setGeometry(QtCore.QRect(10, 130, 71, 16)) self.data_label.setObjectName("data_label") CovidTracker.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(CovidTracker) self.statusbar.setObjectName("statusbar") CovidTracker.setStatusBar(self.statusbar) self.retranslateUi(CovidTracker) self.plot_tab.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(CovidTracker) self.df = df_covid_2019 self.country_list = self.df['countriesAndTerritories'] self.color_list = ((255, 255, 255), (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (0, 255, 255), (255, 0, 255)) self.num_iter = 0 self.data_table_num = 0 self.start_covid() def retranslateUi(self, CovidTracker): _translate = QtCore.QCoreApplication.translate CovidTracker.setWindowTitle(_translate("CovidTracker", "Covid Tracker")) self.plot_tab.setTabText(self.plot_tab.indexOf(self.tab), _translate("CovidTracker", "Plot 1")) self.plot_tab.setTabText(self.plot_tab.indexOf(self.tab_2), _translate("CovidTracker", "Plot 2")) #self.plot_tab.setTabText(self.plot_tab.indexOf(self.tab_3), _translate("CovidTracker", "Chart")) self.track_button.setText(_translate("CovidTracker", "Track!")) self.speak_button.setText(_translate("CovidTracker", "Speak!")) self.reset_button.setText(_translate("CovidTracker", "Reset!")) self.plot_type.setItemText(0, _translate("CovidTracker", "Infections")) self.plot_type.setItemText(1, _translate("CovidTracker", "deaths_weekly")) self.plot_type.setItemText(2, _translate("CovidTracker", "Cumulative")) self.plot_type.setItemText(3, _translate("CovidTracker", "Comparison")) self.dark_light.setItemText(0, _translate("CovidTracker", "Dark")) self.dark_light.setItemText(1, _translate("CovidTracker", "Light")) # item = self.data_table.horizontalHeaderItem(0) # item.setText(_translate("CovidTracker", "Date")) # item = self.data_table.horizontalHeaderItem(1) # item.setText(_translate("CovidTracker", "Number")) # item = self.data_table.horizontalHeaderItem(2) # item.setText(_translate("CovidTracker", "Date")) # item = self.data_table.horizontalHeaderItem(3) # item.setText(_translate("CovidTracker", "Number")) self.animated_checkbox.setText(_translate("CovidTracker", "Animated")) self.main_label.setText(_translate("CovidTracker", "COVID-19 Tracker")) self.history_label.setText(_translate("CovidTracker", "History Log :")) self.data_label.setText(_translate("CovidTracker", "Data")) def covid_plot(self): ui.progressBar.setValue(0) self.num_iter = self.num_iter + 1 self.data_table_num = self.data_table_num + 2 if self.num_iter > 6: self.num_iter = 0 self.country_input = self.country_name.text() if self.country_input == None or self.country_input == '' or self.country_input == 'None Selected': self.country_input = random.choice(np.array(self.country_list)) self.country_input = self.country_input.replace(' ', '_') if self.country_input in set(self.country_list): pass else: self.text_holder.append( 'Country Not found. Choosing Random Country.') self.country_input = random.choice(np.array(self.country_list)) self.country_name.setText(self.country_input.replace('_', ' ')) self.text_holder.append(datetime.datetime.now().strftime("%I:%M:%S") + ' : Selected country is ' + self.country_input) self.cases_weekly = np.array( self.df[self.df['countriesAndTerritories'] == self.country_input]['cases_weekly'])[::-1] self.dates = np.array(self.df[self.df['countriesAndTerritories'] == self.country_input]['dateRep'])[::-1] self.deaths_weekly = np.array( self.df[self.df['countriesAndTerritories'] == self.country_input]['deaths_weekly'])[::-1] self.cumulative = np.array( self.df[self.df['countriesAndTerritories'] == self.country_input] ['notification_rate_per_100000_population_14-days'])[::-1] if self.plot_type.currentIndex() == 0: #main_plot axis_bottom = self.graphicsView.getAxis('bottom') self.graphicsView.addLegend() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting Infections') self.graphicsView.clear() self.x_cases_weekly = np.arange(0, len(self.cases_weekly)) axis_bottom = self.graphicsView.getAxis('bottom') axis_bottom.setTicks( [[(i, j) for i, j in zip( self.x_cases_weekly[0:len(self.x_cases_weekly):20], self.dates[0:len(self.cases_weekly):20])], [(i, '') for j, i in enumerate( self.x_cases_weekly[0:len(self.cases_weekly):10])]]) self.graphicsView.plot(self.x_cases_weekly, self.cases_weekly, pen=pg.mkPen(color=(255, 0, 0), width=2), name='cases_weekly in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(255, 0, 0)) ui.progressBar.setValue(100) #data_table self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('cases_weekly(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 2) for i in range(len(self.cases_weekly)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.cases_weekly[i]))) #second_plot color = self.color_list[self.num_iter] axis_bottom1 = self.graphicsView_2.getAxis('bottom') axis_bottom1.setTicks( [[(i, j) for i, j in zip( self.x_cases_weekly[0:len(self.x_cases_weekly):20], self.dates[0:len(self.cases_weekly):20])], [(i, '') for j, i in enumerate( self.x_cases_weekly[0:len(self.cases_weekly):10])]]) self.graphicsView_2.addLegend() self.graphicsView_2.plot(self.x_cases_weekly, self.cases_weekly, pen=pg.mkPen(color=color, width=2), name='cases_weekly in ' + self.country_input, symbol='o', symbolBrush=color) if self.plot_type.currentIndex() == 1: #main plot self.graphicsView.addLegend() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting deaths_weekly') self.graphicsView.clear() self.x_deaths_weekly = np.arange(0, len(self.deaths_weekly)) axis_bottom = self.graphicsView.getAxis('bottom') axis_bottom.setTicks( [[(i, j) for i, j in zip( self.x_deaths_weekly[0:len(self.x_deaths_weekly):20], self.dates[0:len(self.deaths_weekly):20])], [(i, '') for j, i in enumerate( self.x_deaths_weekly[0:len(self.deaths_weekly):10])]]) self.graphicsView.plot( self.x_deaths_weekly, self.deaths_weekly, pen=pg.mkPen(color=(200, 200, 200), width=2), name='deaths_weekly in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(200, 200, 200)) ui.progressBar.setValue(100) #data_table self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('deaths_weekly(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 2) for i in range(len(self.deaths_weekly)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.deaths_weekly[i]))) #second plot color = self.color_list[self.num_iter] axis_bottom1 = self.graphicsView_2.getAxis('bottom') axis_bottom1.setTicks( [[(i, j) for i, j in zip( self.x_deaths_weekly[0:len(self.x_deaths_weekly):20], self.dates[0:len(self.deaths_weekly):20])], [(i, '') for j, i in enumerate( self.x_deaths_weekly[0:len(self.deaths_weekly):10])]]) self.graphicsView_2.addLegend() self.graphicsView_2.plot(self.x_deaths_weekly, self.deaths_weekly, pen=pg.mkPen(color=color, width=2), name='deaths_weekly in ' + self.country_input, symbol='o', symbolBrush=color) if self.plot_type.currentIndex() == 2: #main plot self.graphicsView.addLegend() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting Cumulative Average of 14 days per 100000 cases_weekly' ) self.graphicsView.clear() self.x_cumulative = np.arange(0, len(self.cumulative)) axis_bottom = self.graphicsView.getAxis('bottom') axis_bottom.setTicks( [[(i, j) for i, j in zip( self.x_cumulative[0:len(self.x_cumulative):20], self.dates[0:len(self.cumulative):20])], [(i, '') for j, i in enumerate( self.x_cumulative[0:len(self.cumulative):10])]]) self.graphicsView.plot(self.x_cumulative, self.cumulative, pen=pg.mkPen(color=(0, 0, 255), width=2), name='Cumulative in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(0, 255, 255)) ui.progressBar.setValue(100) #data_table self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('Cumulative(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 2) for i in range(len(self.cumulative)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.cumulative[i]))) #second plot color = self.color_list[self.num_iter] axis_bottom1 = self.graphicsView_2.getAxis('bottom') axis_bottom1.setTicks( [[(i, j) for i, j in zip( self.x_cumulative[0:len(self.x_cumulative):20], self.dates[0:len(self.cumulative):20])], [(i, '') for j, i in enumerate( self.x_cumulative[0:len(self.cumulative):10])]]) self.graphicsView_2.addLegend() self.graphicsView_2.plot(self.x_cumulative, self.cumulative, pen=pg.mkPen(color=color, width=2), name='Cumulative in ' + self.country_input, symbol='o', symbolBrush=color) if self.plot_type.currentIndex() == 3: self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting comparison') self.graphicsView.clear() self.graphicsView.addLegend() self.x_cases_weekly = np.arange(0, len(self.cases_weekly)) self.graphicsView.showGrid(x=True, y=True) axis_bottom = self.graphicsView.getAxis('bottom') axis_bottom.setTicks( [[(i, j) for i, j in zip( self.x_cases_weekly[0:len(self.x_cases_weekly):20], self.dates[0:len(self.cases_weekly):20])], [(i, '') for j, i in enumerate( self.x_cases_weekly[0:len(self.cases_weekly):10])]]) self.graphicsView.plot(self.x_cases_weekly, abs(self.cases_weekly), pen=(255, 0, 0), name='cases_weekly in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(255, 0, 0)) self.graphicsView.plot(self.x_cases_weekly, abs(self.deaths_weekly), pen=(200, 200, 200), name='deaths_weekly in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(200, 200, 200)) self.graphicsView.plot(self.x_cases_weekly, abs(self.cumulative), pen=(0, 0, 255), name='Cumulative in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(0, 0, 255)) ui.progressBar.setValue(100) #data_table self.data_table_num = self.data_table_num + 2 self.data_table.insertColumn(self.data_table_num - 4) self.data_table.setHorizontalHeaderItem( self.data_table_num - 4, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 3) self.data_table.setHorizontalHeaderItem( self.data_table_num - 3, QtWidgets.QTableWidgetItem('cases_weekly(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('deaths_weekly(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('Cumulative(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 4) for i in range(len(self.cumulative)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 4, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 3, QtWidgets.QTableWidgetItem(str(self.cases_weekly[i]))) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.deaths_weekly[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.cumulative[i]))) #self.graphicsView.setLogMode(x=False,y=True) # if self.plot_type.currentIndex() == 4: # self.graphicsView_3.clear() # win = self.graphicsView_3 # pg.setConfigOptions(antialias=True) # p1 = win.addPlot(title='cases_weekly') # self.x_cases_weekly = np.arange(0,len(self.cases_weekly)) # p1.plot(self.x_cases_weekly,self.cases_weekly,pen=pg.mkPen(color=(255,0,0),width=2),name='cases_weekly in '+self.country_input,symbol='o', # symbolSize=7,symbolBrush=(255,0,0)) # p2 = win.addPlot(title='deaths_weekly') # self.x_deaths_weekly = np.arange(0,len(self.deaths_weekly)) # p2.plot(self.x_deaths_weekly,self.deaths_weekly,pen=pg.mkPen(color=(200,200,200), width=2),name='deaths_weekly in '+self.country_input,symbol='o', # symbolSize=7,symbolBrush=(200,200,200)) # p3 = win.addPlot(title='Cumulative Average') # self.x_cumulative = np.arange(0,len(self.cumulative)) # p3.plot(self.x_cumulative,self.cumulative,pen=pg.mkPen(color=(0,0,255),width=2),name='Cumulative in '+self.country_input,symbol='o', # symbolSize=7,symbolBrush=(0,255,255)) # win.nextRow() # p4 = win.addPlot(title = 'Covid Histogram') # y1,x1 = np.histogram(np.hstack(self.cases_weekly),bins=int(len(self.cases_weekly)/10)) # p4.plot(x1,y1,stepMode=True, fillLevel=1, fillOutline=True, brush=(255,0,0,150)) def covid_plot_anim(self): ui.progressBar.setValue(0) self.num_iter = self.num_iter + 1 if self.num_iter > 6: self.num_iter = 0 self.data_table_num = self.data_table_num + 2 self.country_input = self.country_name.text() if self.country_input == None or self.country_input == '': self.country_input = random.choice(np.array(self.country_list)) self.country_input = self.country_input.replace(' ', '_') if self.country_input in set(self.country_list): pass else: self.text_holder.append( 'Country Not found. Choosing Random Country.') self.country_input = random.choice(np.array(self.country_list)) self.text_holder.append(datetime.datetime.now().strftime("%I:%M:%S") + ' : Selected country is ' + self.country_input) self.cases_weekly = np.array( self.df[self.df['countriesAndTerritories'] == self.country_input]['cases_weekly'])[::-1] self.dates = np.array(self.df[self.df['countriesAndTerritories'] == self.country_input]['dateRep'])[::-1] self.deaths_weekly = np.array( self.df[self.df['countriesAndTerritories'] == self.country_input]['deaths_weekly'])[::-1] self.cumulative = np.array( self.df[self.df['countriesAndTerritories'] == self.country_input] ['notification_rate_per_100000_population_14-days'])[::-1] self.graphicsView.clear() if self.plot_type.currentIndex() == 0: self.graphicsView.addLegend() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting Infections') self.graphicsView.clear() self.x_cases_weekly = np.arange(0, len(self.cases_weekly)) self.x = [] self.y = [] #data table self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('deaths_weekly(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 2) for i in range(len(self.deaths_weekly)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.deaths_weekly[i]))) for i in range(len(self.cases_weekly)): ui.progressBar.setValue( np.linspace(0, 100, len(self.cases_weekly))[i]) self.graphicsView.clear() self.x.append(self.x_cases_weekly[i]) self.y.append(self.cases_weekly[i]) self.graphicsView.plot( self.x, self.y, pen=pg.mkPen(color=(255, 0, 0), width=2), name='cases_weekly in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(255, 0, 0)) pg.QtGui.QApplication.processEvents() #second_plot color = self.color_list[self.num_iter] axis_bottom1 = self.graphicsView_2.getAxis('bottom') axis_bottom1.setTicks( [[(i, j) for i, j in zip( self.x_cases_weekly[0:len(self.x_cases_weekly):20], self.dates[0:len(self.cases_weekly):20])], [(i, '') for j, i in enumerate( self.x_cases_weekly[0:len(self.cases_weekly):10])]]) self.graphicsView_2.addLegend() self.graphicsView_2.plot(self.x_cases_weekly, self.cases_weekly, pen=pg.mkPen(color=color, width=2), name='cases_weekly in ' + self.country_input, symbol='o', symbolBrush=color) if self.plot_type.currentIndex() == 1: self.graphicsView.addLegend() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting deaths_weekly') self.graphicsView.clear() self.x_deaths_weekly = np.arange(0, len(self.deaths_weekly)) self.x = [] self.y = [] #data_table self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('deaths_weekly(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 2) for i in range(len(self.deaths_weekly)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.deaths_weekly[i]))) #main_anim_plot for i in range(len(self.deaths_weekly)): ui.progressBar.setValue( np.linspace(0, 100, len(self.deaths_weekly))[i]) self.graphicsView.clear() self.x.append(self.x_deaths_weekly[i]) self.y.append(self.deaths_weekly[i]) self.graphicsView.plot(self.x, self.y, pen=pg.mkPen(color=(200, 200, 200), width=2), name='deaths_weekly in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(200, 200, 200)) pg.QtGui.QApplication.processEvents() #second plot color = self.color_list[self.num_iter] axis_bottom1 = self.graphicsView_2.getAxis('bottom') axis_bottom1.setTicks( [[(i, j) for i, j in zip( self.x_deaths_weekly[0:len(self.x_deaths_weekly):20], self.dates[0:len(self.deaths_weekly):20])], [(i, '') for j, i in enumerate( self.x_deaths_weekly[0:len(self.deaths_weekly):10])]]) self.graphicsView_2.addLegend() self.graphicsView_2.plot(self.x_deaths_weekly, self.deaths_weekly, pen=pg.mkPen(color=color, width=2), name='deaths_weekly in ' + self.country_input, symbol='o', symbolBrush=color) if self.plot_type.currentIndex() == 2: self.graphicsView.addLegend() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting Cumulative Average of 14 days per 100000 cases_weekly' ) self.graphicsView.clear() self.x_cumulative = np.arange(0, len(self.cumulative)) self.x = [] self.y = [] #data_table self.data_table.insertColumn(self.data_table_num - 2) self.data_table.setHorizontalHeaderItem( self.data_table_num - 2, QtWidgets.QTableWidgetItem('Date(' + self.country_input + ')')) self.data_table.insertColumn(self.data_table_num - 1) self.data_table.setHorizontalHeaderItem( self.data_table_num - 1, QtWidgets.QTableWidgetItem('Cumulative(' + self.country_input + ')')) self.data_table.setCurrentCell(0, self.data_table_num - 2) for i in range(len(self.cumulative)): rowPosition = self.data_table.rowCount() self.data_table.insertRow(rowPosition) self.data_table.setItem( i, self.data_table_num - 2, QtWidgets.QTableWidgetItem(str(self.dates[i]))) self.data_table.setItem( i, self.data_table_num - 1, QtWidgets.QTableWidgetItem(str(self.cumulative[i]))) for i in range(len(self.cumulative)): ui.progressBar.setValue( np.linspace(0, 100, len(self.cumulative))[i]) self.graphicsView.clear() self.x.append(self.x_cumulative[i]) self.y.append(self.cumulative[i]) self.graphicsView.plot( self.x, self.y, pen=pg.mkPen(color=(0, 0, 255), width=2), name='Cumulative in ' + self.country_input, symbol='o', symbolSize=7, symbolBrush=(0, 255, 255)) pg.QtGui.QApplication.processEvents() if self.plot_type.currentIndex() == 3: self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting comparison. No animation.') self.graphicsView.clear() self.graphicsView.addLegend() self.x_cases_weekly = np.arange(0, len(self.cases_weekly)) self.graphicsView.showGrid(x=True, y=True) self.graphicsView.plot(self.x_cases_weekly, abs(self.cases_weekly), pen=(255, 0, 0), name='cases_weekly', symbol='o', symbolSize=7, symbolBrush=(255, 0, 0)) self.graphicsView.plot(self.x_cases_weekly, abs(self.deaths_weekly), pen=(200, 200, 200), name='deaths_weekly', symbol='o', symbolSize=7, symbolBrush=(200, 200, 200)) self.graphicsView.plot(self.x_cases_weekly, abs(self.cumulative), pen=(0, 0, 255), name='Cumulative', symbol='o', symbolSize=7, symbolBrush=(0, 0, 255)) ui.progressBar.setValue(100) #self.graphicsView.setLogMode(x=False,y=True) if self.plot_type.currentIndex() == 4: self.x_cases_weekly = np.arange(0, len(self.cases_weekly)) self.graphicsView.plot(self.x_cases_weekly, self.cases_weekly) def get_covid(self): if self.animated_checkbox.checkState() == False: self.covid_plot() else: self.covid_plot_anim() def reset_covid(self): self.text_holder.setText('') self.graphicsView.clear() self.graphicsView_2.clear() self.data_table.clear() self.data_table_num = 0 self.num_iter = 0 self.animated_checkbox.setCheckState(False) self.country_name.setText('None Selected') self.text_holder.append(datetime.datetime.now().strftime("%I:%M:%S") + ' : Covid Tracker reset!') def start_record(self): self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ': \n>>>>>><<<<<<\nVoice mode activated\n>>>>>><<<<<<\nListening for 5 seconds....' ) self.text_holder.repaint() self.record_covid() self.text_holder.append('Voice mode deactivated.') def record_covid(self): df = df_covid_2019 fs = 44100 # Sample rate seconds = 5 # Duration of recording myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2) sd.wait() # Wait until recording is finished y = (np.iinfo(np.int32).max * (myrecording / np.abs(myrecording).max())).astype(np.int32) wavfile.write('output.wav', fs, y) r = sr.Recognizer() # Reading Audio file as source # listening the audio file and store in audio_text variable with sr.AudioFile('output.wav') as source: audio_text = r.listen(source) # recoginize_() method will throw a request error if the API is unreachable, hence using exception handling try: # using google speech recognition text = r.recognize_google(audio_text) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ": I guess you said '" + text + "'") except: self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ': Sorry, the speech transcription service did not respond, Try again in a few minutes or type the country name.' ) try: if text == None: self.text_holder.append('Nothin recorded') if text.lower() == 'infections': self.plot_type.setCurrentIndex(0) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Selecting plot type > Infections' ) elif text.lower() == 'deaths_weekly' or text.lower( ) == 'death': self.plot_type.setCurrentIndex(1) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Selecting plot type > deaths_weekly' ) elif text.lower() == 'cumulative': self.plot_type.setCurrentIndex(2) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Selecting plot type > Cumulative' ) elif text.lower() == 'comparison' or text.lower( ) == 'comparisons': self.plot_type.setCurrentIndex(3) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Selecting plot type > Comparison' ) elif text.lower() == 'chart': self.plot_type.setCurrentIndex(4) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Selecting plot type > Chart') elif text.lower() == 'reset': self.reset_button.click() self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Reset Covid Tracker') elif text.lower() == 'dark': self.dark_light.setCurrentIndex(0) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Setting Dark Mode') elif text.lower() == 'light': self.dark_light.setCurrentIndex(1) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Setting Light Mode') elif text.lower() == 'animated': self.animated_checkbox.setCheckState(True) else: self.country_name.setText(text) self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ' : From voice commands : Country selected > ' + text) country_name = text.replace(' ', '_') if country_name in set(self.df['countriesAndTerritories']): self.track_button.click() except UnboundLocalError: self.text_holder.append( datetime.datetime.now().strftime("%I:%M:%S") + ': Nothing was recorded') def mode_change(self): if self.dark_light.currentIndex() == 0: app.setStyle('Fusion') palette = QtGui.QPalette() palette.setColor(QtGui.QPalette.Window, QtGui.QColor(53, 53, 53)) palette.setColor(QtGui.QPalette.WindowText, QtCore.Qt.white) palette.setColor(QtGui.QPalette.Base, QtGui.QColor(15, 15, 15)) palette.setColor(QtGui.QPalette.AlternateBase, QtGui.QColor(53, 53, 53)) palette.setColor(QtGui.QPalette.ToolTipBase, QtCore.Qt.white) palette.setColor(QtGui.QPalette.ToolTipText, QtCore.Qt.white) palette.setColor(QtGui.QPalette.Text, QtCore.Qt.white) palette.setColor(QtGui.QPalette.Button, QtGui.QColor(53, 53, 53)) palette.setColor(QtGui.QPalette.ButtonText, QtCore.Qt.white) palette.setColor(QtGui.QPalette.BrightText, QtCore.Qt.red) palette.setColor(QtGui.QPalette.Highlight, QtGui.QColor(0, 67, 202, 200).lighter()) palette.setColor(QtGui.QPalette.HighlightedText, QtCore.Qt.black) app.setPalette(palette) if self.dark_light.currentIndex() == 1: app.setStyle('Fusion') palette = QtGui.QPalette() palette.setColor(QtGui.QPalette.Window, QtGui.QColor(255, 255, 255)) palette.setColor(QtGui.QPalette.WindowText, QtCore.Qt.black) palette.setColor(QtGui.QPalette.Base, QtGui.QColor(255, 255, 255)) palette.setColor(QtGui.QPalette.AlternateBase, QtGui.QColor(246, 246, 246)) palette.setColor(QtGui.QPalette.ToolTipBase, QtCore.Qt.black) palette.setColor(QtGui.QPalette.ToolTipText, QtCore.Qt.black) palette.setColor(QtGui.QPalette.Text, QtCore.Qt.black) palette.setColor(QtGui.QPalette.Button, QtGui.QColor(240, 240, 240)) palette.setColor(QtGui.QPalette.ButtonText, QtCore.Qt.black) palette.setColor(QtGui.QPalette.BrightText, QtCore.Qt.red) palette.setColor(QtGui.QPalette.Highlight, QtGui.QColor(0, 67, 202, 200).lighter()) palette.setColor(QtGui.QPalette.HighlightedText, QtCore.Qt.black) app.setPalette(palette) # def check_box_state_change(self): # self.text_holder.append('Animation toggled') # if self.animated_checkbox.checkState()== True: # self.remove_item() # if self.animated_checkbox.checkState()==False and self.plot_type.itemText(3)!='Comparison': # self.add_item() # def remove_item(self): # self.plot_type.removeItem(3) # self.plot_type.repaint() # def add_item(self): # self.plot_type.insertItem(3,'Comparison') # self.plot_type.repaint() def start_covid(self): with urllib.request.urlopen("https://geolocation-db.com/json") as url: data = json.loads(url.read().decode()) self.country_name.setText(str(data['country_name'])) self.get_covid() self.text_holder.setText(datetime.datetime.now().strftime("%I:%M:%S") + ' : Country Located : ' + self.country_name.text()) self.text_holder.append(datetime.datetime.now().strftime("%I:%M:%S") + ' : Plotting infections') self.country_name.setText('None Selected')
class RatingView(QtWidgets.QWidget): _ratings_ready = QtCore.pyqtSignal(object, object) _node_ratings_ready = QtCore.pyqtSignal(object) def __init__(self): super().__init__() layout = QtWidgets.QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) self._cubeable_plot = PlotWidget( axisItems={'bottom': TimeAxisItem(orientation='bottom')}) self._nodes_plot = PlotWidget( axisItems={'bottom': TimeAxisItem(orientation='bottom')}) self._splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical) self._splitter.setStretchFactor(0, 1) self._splitter.setStretchFactor(1, 1) layout.addWidget(self._splitter) self._splitter.addWidget(self._cubeable_plot) self._splitter.addWidget(self._nodes_plot) self._display_target: t.Optional[t.Tuple[int, CardboardCubeable]] = None self._ratings_ready.connect(self._set_cubeable_ratings) self._node_ratings_ready.connect(self._set_nodes_ratings) LOGIN_CONTROLLER.login_success.connect(self._on_login) @classmethod def _get_color(cls, n: int = 0) -> QColor: return QColor(100 + (n * 70) % 155, 100 + ((n + 1) * 50) % 155, 100 + ((n + 2) * 40) % 155) @functools.lru_cache(maxsize=128) def _get_rating_points( self, release_id: int, cardboard_cubeable: CardboardCubeable ) -> Promise[t.Sequence[RatingPoint]]: return Context.cube_api_client.rating_history_for_cardboard_cubeable( release_id, cardboard_cubeable, ) @functools.lru_cache(maxsize=256) def _get_node_rating_points( self, release_id: int, node: CardboardNodeChild) -> Promise[t.Sequence[NodeRatingPoint]]: return Context.cube_api_client.rating_history_for_node( release_id, node, ).then(lambda ratings: (node, ratings)) def _on_login(self, *args, **kwargs) -> None: self._get_rating_points.cache_clear() self._get_node_rating_points.cache_clear() def _set_cubeable_ratings(self, cardboard_cubeable: CardboardCubeable, ratings: t.Sequence[RatingPoint]) -> None: self._cubeable_plot.clear() data_item = self._cubeable_plot.plot( [p.rating_map.created_at.timestamp() for p in ratings], [p.rating for p in ratings]) legend = self._cubeable_plot.addLegend(labelTextSize='15pt') legend.addItem( data_item, cardboard_cubeable.name if isinstance( cardboard_cubeable, Cardboard) else cardboard_cubeable.description) self._cubeable_plot.getPlotItem().enableAutoRange() def _set_nodes_ratings( self, ratings: t.Iterable[t.Tuple[CardboardNodeChild, t.Sequence[NodeRatingPoint]]] ) -> None: self._nodes_plot.show() self._nodes_plot.clear() legend = self._nodes_plot.addLegend(labelTextSize='15pt') for idx, (node_child, ratings) in enumerate(ratings): data_item = self._nodes_plot.plot( [p.rating_map.created_at.timestamp() for p in ratings], [p.rating for p in ratings], pen=mkPen(color=self._get_color(idx)), ) legend.addItem( data_item, node_child.name if isinstance(node_child, Cardboard) else node_child.get_minimal_string()) self._nodes_plot.getPlotItem().enableAutoRange() def on_focus_event(self, focus_event: FocusEvent) -> None: if not self.isVisible( ) or not focus_event.release_id or Context.focus_card_frozen: return cardboard_cubeable = focusable_as_cardboards(focus_event.focusable) display_target = (focus_event.release_id, cardboard_cubeable) if display_target == self._display_target: return self._display_target = display_target promise = self._get_rating_points(focus_event.release_id, cardboard_cubeable) if promise.is_pending: promise.then(lambda ratings: self._ratings_ready.emit( cardboard_cubeable, ratings)).catch(logging.warning) elif promise.is_fulfilled: self._set_cubeable_ratings(cardboard_cubeable, promise.get()) if isinstance( cardboard_cubeable, CardboardTrap ) and cardboard_cubeable.intention_type == IntentionType.GARBAGE: promise = Promise.all([ self._get_node_rating_points(focus_event.release_id, node) for node in cardboard_cubeable.node.children.distinct_elements() ]) if promise.is_pending: promise.then(self._node_ratings_ready.emit).catch( logging.warning) elif promise.is_fulfilled: self._set_nodes_ratings(promise.get()) else: self._nodes_plot.hide()
class CombinedPlot(QWidget): PLOT_PENS = [mkPen((219, 148, 92), width=1.25), mkPen((103, 219, 104), width=1.25), mkPen((59, 198, 219), width=1.25), mkPen((219, 70, 143), width=1.25)] def __init__(self): super().__init__() capacity = 256 self.buffer1 = RingBuffer(capacity=capacity, dtype=np.float32) self.buffer2 = RingBuffer(capacity=capacity, dtype=np.float32) self.buffer3 = RingBuffer(capacity=capacity, dtype=np.float32) self.buffer4 = RingBuffer(capacity=capacity, dtype=np.float32) self.plot = PlotWidget() self.plot.getPlotItem().showGrid(x=True, y=True, alpha=1) self.plot.addLegend() if "qdarkstyle" in sys.modules: self.plot.setBackground((25, 35, 45)) self.bufferSizeEdit = QLineEdit() self.bufferSizeEdit.setText(str(capacity)) self.bufferSizeEdit.setValidator(QRegExpValidator(QRegExp("[0-9]*"))) self.bufferSizeEdit.editingFinished.connect(self.change_capacity) self.layout = QVBoxLayout() group = QGroupBox("Combined controller plot") layout = QVBoxLayout() layout.addWidget(self.plot) innerLayout = QHBoxLayout() innerLayout.addWidget(QLabel("Buffer size")) innerLayout.addWidget(self.bufferSizeEdit) layout.addLayout(innerLayout) group.setLayout(layout) self.layout.addWidget(group) self.setLayout(self.layout) def update_plot(self, controllerN: int, sample: np.float16): self.plot.clear() if controllerN == 1: self.buffer1.append(sample) elif controllerN == 2: self.buffer2.append(sample) elif controllerN == 3: self.buffer3.append(sample) elif controllerN == 4: self.buffer4.append(sample) self.plot.plot(self.buffer1, pen=self.PLOT_PENS[0], symbolPen=self.PLOT_PENS[0], symbol='o', symbolSize=5, name="Controller 1") self.plot.plot(self.buffer2, pen=self.PLOT_PENS[1], symbolPen=self.PLOT_PENS[1], symbol='o', symbolSize=5, name="Controller 2") self.plot.plot(self.buffer3, pen=self.PLOT_PENS[2], symbolPen=self.PLOT_PENS[2], symbol='o', symbolSize=5, name="Controller 3") self.plot.plot(self.buffer4, pen=self.PLOT_PENS[3], symbolPen=self.PLOT_PENS[3], symbol='o', symbolSize=5, name="Controller 4") def change_capacity(self): value = int(self.bufferSizeEdit.text()) if value > len(self.buffer1): newBuf1 = RingBuffer(capacity=value, dtype=np.float16) newBuf1.extend(self.buffer1) newBuf2 = RingBuffer(capacity=value, dtype=np.float16) newBuf2.extend(self.buffer2) newBuf3 = RingBuffer(capacity=value, dtype=np.float16) newBuf3.extend(self.buffer3) newBuf4 = RingBuffer(capacity=value, dtype=np.float16) newBuf4.extend(self.buffer4) self.buffer1 = newBuf1 self.buffer2 = newBuf2 self.buffer3 = newBuf3 self.buffer4 = newBuf4 elif value < len(self.buffer1): newBuf1 = RingBuffer(capacity=value, dtype=np.float16) newBuf1.extend(self.buffer1[:-value]) newBuf2 = RingBuffer(capacity=value, dtype=np.float16) newBuf2.extend(self.buffer2[:-value]) newBuf3 = RingBuffer(capacity=value, dtype=np.float16) newBuf3.extend(self.buffer3[:-value]) newBuf4 = RingBuffer(capacity=value, dtype=np.float16) newBuf4.extend(self.buffer4[:-value]) self.buffer1 = newBuf1 self.buffer2 = newBuf2 self.buffer3 = newBuf3 self.buffer4 = newBuf4
class ComplicatedTestResultsDialog(QMainWindow): def __init__(self, parent=None, methods=None, vertices_amounts=None, samples_amount=None, name_1=None, name_2=None): super(ComplicatedTestResultsDialog, self).__init__(parent) self.parent_window = parent self.setWindowTitle("Grismo - Wyniki dla testu wpływu liczby " + name_1) self.setMinimumWidth(630) self.setMinimumHeight(800) self.setMaximumHeight(900) self.methods = methods self.results_count = 0 self.start_vertices = vertices_amounts[0] self.all_vertices_amount = len(vertices_amounts) self.samples_amount = samples_amount # store all results to calculate means self.all_results = [] central = QWidget() self.setCentralWidget(central) central_layout = QVBoxLayout() central.setLayout(central_layout) # plot box plot_label = QLabel("Wykres dla wszystkich testów:") central_layout.addWidget(plot_label) self.plot_log_mode = False self.results_plot = PlotWidget() self.results_plot.setLogMode(False, self.plot_log_mode) self.results_plot.setBackground('w') self.results_plot.setTitle("Badanie wpływu liczby " + name_1 + " na czas testu") self.results_plot.setLabel('left', 'Czas obliczeń [s]', color='k', size=10) self.results_plot.setLabel('bottom', 'Liczba ' + name_1, color='k', size=10) self.results_plot.setXRange(self.start_vertices, vertices_amounts[-1]) self.results_plot.setMaximumWidth(600) self.results_plot.showGrid(y=True) central_layout.addWidget(self.results_plot) switch_plot_log_button = QPushButton("Zmień skalę osi Y (logarytmiczna/liniowa)") switch_plot_log_button.setCheckable(False) switch_plot_log_button.clicked.connect(self.switch_plot_log) central_layout.addWidget(switch_plot_log_button) # prepare plot lines self.plot_data = [] method_colors = ['k', 'b', 'g', 'r', 'y'] self.results_plot.plot([], [], name="") self.results_plot.addLegend() for method_index in range(len(self.methods)): method_name = self.methods[method_index] method_color = method_colors[method_index] pen = mkPen(color=method_color, width=2) self.plot_data.append(self.results_plot.plot([], [], name=method_name, pen=pen, symbol='+', symbolSize=10, symbolBrush=method_color)) self.results_plot.addLegend() # tables box tables_box = QScrollArea(self) tables_box.setWidgetResizable(True) tables_box_content = QWidget(tables_box) tables_box_layout = QVBoxLayout(tables_box_content) tables_box_content.setLayout(tables_box_layout) tables_box.setWidget(tables_box_content) central_layout.addWidget(tables_box) # for each vertices_amount prepare table: label -> table -> label -> progress_bar self.results_tables = [] self.results_progress_bars = [] bold_font = QFont() bold_font.setBold(True) for i in vertices_amounts: vertices_label = QLabel("Wyniki dla grafów o " + str(i) + " " + name_2 + ":") vertices_label.setFont(bold_font) results_table = QTableWidget() results_table.setRowCount(len(methods)) results_table.setColumnCount(4) results_table.setColumnWidth(1, 150) results_table.setColumnWidth(2, 150) results_table.setMinimumHeight((len(methods) + 1) * 30) results_table.setHorizontalHeaderLabels(["Metoda", "Wyniki pozytywne", "Wyniki negatywne", "Średni czas [s]"]) progress_label = QLabel("Postęp:") results_progress_bar = QProgressBar() results_progress_bar.setValue(0) self.results_tables.append(results_table) self.results_progress_bars.append(results_progress_bar) tables_box_layout.addWidget(vertices_label) tables_box_layout.addWidget(results_table) tables_box_layout.addWidget(progress_label) tables_box_layout.addWidget(results_progress_bar) self.all_results.append([]) for method_index in range(len(methods)): method_title = methods[method_index] results_table.setItem(method_index, 0, QTableWidgetItem(method_title)) self.all_results[-1].append([]) def add_result(self, result, vertices_amount, sample_number): # result: [method, decision, time] # vertices table index table_index = vertices_amount - self.start_vertices # method index method_index = self.methods.index(result[0]) # add result to all stored results self.all_results[table_index][method_index].append(result) # positive and negatives # firstly extract 2nd column from results matrix new_positives = sum([row[1] for row in self.all_results[table_index][method_index]]) new_negatives = len(self.all_results[table_index][method_index]) - new_positives self.results_tables[table_index].setItem(method_index, 1, QTableWidgetItem(str(new_positives))) self.results_tables[table_index].setItem(method_index, 2, QTableWidgetItem(str(new_negatives))) # mean new_mean = mean([row[2] for row in self.all_results[table_index][method_index]]) self.results_tables[table_index].setItem(method_index, 3, QTableWidgetItem(str(new_mean))) # progress_bar self.results_progress_bars[table_index].setValue(sample_number / self.samples_amount * 100) self.results_count = self.results_count + 1 # update plot self.update_plot() def update_plot(self): for method_index in range(len(self.methods)): # for this method find all mean values x = [] y = [] for vertices_index in range(self.all_vertices_amount): vertices_amount = vertices_index + self.start_vertices if len(self.all_results[vertices_index][method_index]): x.append(vertices_amount) y.append(mean([row[2] for row in self.all_results[vertices_index][method_index]])) self.plot_data[method_index].setData(x, y) def switch_plot_log(self): self.plot_log_mode = not self.plot_log_mode self.results_plot.setLogMode(False, self.plot_log_mode) def closeEvent(self, event): self.parent_window.stop_test = True
def __init__(self, instance): super(GUIBuilder, self).__init__() self.setCentralWidget(QWidget()) layout = QVBoxLayout(self.centralWidget()) self.plots_layout = DockArea() layout.addWidget(self.plots_layout) self.form_layout = QFormLayout() self.form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) layout.addLayout(self.form_layout) self.buttons_layout = QHBoxLayout() layout.addLayout(self.buttons_layout) self.instance = instance self.plot_widgets = {} self.plot_data_items = {} self.plot_color_generators = {} seen_form_items = [] seen_plot_items = [] for node in ast.walk(ast.parse(getsource(type(instance)))): if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): if node.func.id.startswith('gb_get_') or node.func.id.startswith('gb_set_'): segs = node.func.id.split('_') caster = __builtins__[segs[2]] name = "_".join(segs[3:]) if name in seen_form_items: continue seen_form_items.append(name) if caster is bool: editor = QCheckBox() if node.func.id.startswith('gb_get_') and node.args: editor.setChecked(node.args[0].id == 'True') get_fn = lambda e=editor: e.isChecked() set_fn = lambda v, e=editor: e.setChecked(v) else: editor = QLineEdit() if node.func.id.startswith('gb_get_') and node.args: if isinstance(node.args[0], ast.Num): init = node.args[0].n else: init = node.args[0].s editor.setText(str(caster(init))) get_fn = lambda e=editor, c=caster: c(e.text()) set_fn = lambda val, e=editor: e.setText(str(val)) base_name = "_".join(segs[2:]) get_name = "gb_get_" + base_name set_name = "gb_set_" + base_name __builtins__[get_name] = lambda init=0, get_fn=get_fn: get_fn() __builtins__[set_name] = lambda val, set_fn=set_fn: set_fn(val) self.form_layout.addRow(prettify(name), editor) if node.func.id.startswith('gb_plot_'): segs = node.func.id.split("_") plot_type = segs[2] plot_name = segs[3] if len(segs) >= 5: data_item_name = "_".join(segs[4:]) else: data_item_name = "" if (plot_name, data_item_name) in seen_plot_items: continue seen_plot_items.append((plot_name, data_item_name)) if plot_name not in self.plot_widgets: if plot_type in ['y', 'xy']: pw = PlotWidget() self.plot_widgets[plot_name] = pw self.plot_color_generators[plot_name] = itertools.cycle('rgb') pw.addLegend() else: raise ValueError("Unknown plot type in {}: {}".format(node.func.id, plot_type)) dock = Dock(name=prettify(plot_name), widget=pw) self.plots_layout.addDock(dock, 'above') self.add_plot_item(node.func.id, plot_name, data_item_name) if isinstance(node, ast.FunctionDef): if node.name.endswith("_gb_button"): name = "_".join(node.name.split("_")[:-2]) button = QPushButton(prettify(name)) button.clicked.connect(getattr(instance, node.name)) self.buttons_layout.addWidget(button)
class Plotter(QWidget): MAX_DATA_POINTS_PER_CURVE = 200000 COLORS = [Qt.red, Qt.green, Qt.blue, # RGB - http://ux.stackexchange.com/questions/79561 Qt.yellow, Qt.cyan, Qt.magenta, # Close to RGB Qt.darkRed, Qt.darkGreen, Qt.darkBlue, # Darker RGB Qt.darkYellow, Qt.darkCyan, Qt.darkMagenta, # Close to RGB Qt.gray, Qt.darkGray] # Leftovers INITIAL_X_RANGE = 60 def __init__(self, parent=None): # Parent super(Plotter, self).__init__(parent) self.setWindowTitle('UAVCAN Plotter') self.setWindowIcon(APP_ICON) # Redraw timer self._update_timer = QTimer() self._update_timer.timeout.connect(self._update) self._update_timer.setSingleShot(False) self._update_timer.start(30) # PyQtGraph self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._legend = self._plot_widget.addLegend() self._plot_widget.setRange(xRange=(0, self.INITIAL_X_RANGE), padding=0) self._plot_widget.showButtons() self._plot_widget.enableAutoRange() self._plot_widget.showGrid(x=True, y=True, alpha=0.4) # Controls # https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html button_add_matcher = QtGui.QPushButton('New matcher', self) button_add_matcher.setIcon(QtGui.QIcon.fromTheme('list-add')) button_add_matcher.setToolTip('Add new curve matcher') button_add_matcher.clicked.connect( lambda: NewCurveMatcherWindow(self, lambda: sorted(self._active_messages), self._add_curve_matcher).show()) button_clear_plots = QtGui.QPushButton('Clear plots', self) button_clear_plots.setIcon(QtGui.QIcon.fromTheme('edit-clear')) button_clear_plots.setToolTip('Clear the plotting area') button_clear_plots.clicked.connect(lambda: self._remove_all_curves()) def delete_all_matchers(): self._curve_matchers = [] for i in reversed(range(self._curve_matcher_container.count())): self._curve_matcher_container.itemAt(i).widget().deleteLater() self._remove_all_curves() button_delete_all_matchers = QtGui.QPushButton('Delete matchers', self) button_delete_all_matchers.setIcon(QtGui.QIcon.fromTheme('edit-delete')) button_delete_all_matchers.setToolTip('Delete all matchers') button_delete_all_matchers.clicked.connect(delete_all_matchers) self._autoscroll = QtGui.QCheckBox('Autoscroll', self) self._autoscroll.setChecked(True) self._max_x = self.INITIAL_X_RANGE # Layout control_panel = QHBoxLayout() control_panel.addWidget(button_add_matcher) control_panel.addWidget(button_clear_plots) control_panel.addWidget(self._autoscroll) control_panel.addStretch() control_panel.addWidget(button_delete_all_matchers) self._curve_matcher_container = QVBoxLayout() layout = QVBoxLayout() layout.addWidget(self._plot_widget, 1) layout.addLayout(control_panel) layout.addLayout(self._curve_matcher_container) self.setLayout(layout) # Logic self._color_index = 0 self._curves = {} self._message_queue = multiprocessing.Queue() self._active_messages = set() # set(data type name) self._curve_matchers = [] # Defaults self._add_curve_matcher(CurveMatcher('uavcan.protocol.debug.KeyValue', 'value', [('key', None)])) def _add_curve_matcher(self, matcher): self._curve_matchers.append(matcher) view = CurveMatcherView(matcher, self) def remove(): self._curve_matchers.remove(matcher) self._curve_matcher_container.removeWidget(view) view.setParent(None) view.deleteLater() view.on_remove = remove self._curve_matcher_container.addWidget(view) def _update(self): # Processing messages while True: try: m = self._message_queue.get_nowait() self._process_message(m) except queue.Empty: break # Updating curves for curve in self._curves.values(): if len(curve['x']): if len(curve['x']) > self.MAX_DATA_POINTS_PER_CURVE: curve['x'] = curve['x'][-self.MAX_DATA_POINTS_PER_CURVE:] curve['y'] = curve['y'][-self.MAX_DATA_POINTS_PER_CURVE:] assert len(curve['x']) == len(curve['y']) curve['plot'].setData(curve['x'], curve['y']) self._max_x = max(self._max_x, curve['x'][-1]) # Updating view range if self._autoscroll.checkState(): (xmin, xmax), _ = self._plot_widget.viewRange() diff = xmax - xmin xmax = self._max_x xmin = self._max_x - diff self._plot_widget.setRange(xRange=(xmin, xmax), padding=0) def _process_message(self, m): self._active_messages.add(m.data_type_name) for matcher in self._curve_matchers: if matcher.match(m): name, x, y = matcher.extract_curve_name_x_y(m) self._draw_curve(name, x, y) def _remove_all_curves(self): for curve in self._curves.values(): self._plot_widget.removeItem(curve['plot']) self._plot_widget.clear() self._curves = {} self._color_index = 0 self._legend.scene().removeItem(self._legend) self._legend = self._plot_widget.addLegend() def _draw_curve(self, name, x, y): if name not in self._curves: logging.info('Adding curve %r', name) color = self.COLORS[self._color_index % len(self.COLORS)] self._color_index += 1 pen = mkPen(QColor(color), width=1) plot = self._plot_widget.plot(name=name, pen=pen) self._curves[name] = {'x': numpy.array([]), 'y': numpy.array([]), 'plot': plot} curve = self._curves[name] curve['x'] = numpy.append(curve['x'], [x] if isinstance(x, (float, int)) else x) curve['y'] = numpy.append(curve['y'], [y] if isinstance(y, (float, int)) else y) assert len(curve['x']) == len(curve['y']) def push_received_message(self, msg): self._message_queue.put_nowait(msg)
class RealtimePlotWidget(QWidget): AUTO_RANGE_FRACTION = 0.99 COLORS = [ Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray ] def __init__(self, display_measurements, parent): super(RealtimePlotWidget, self).__init__(parent) self.setAttribute( Qt.WA_DeleteOnClose) # This is required to stop background timers! self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._legend = self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.showGrid(x=True, y=True, alpha=0.3) vbox = QVBoxLayout(self) vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._last_update_ts = 0 self._reset_required = False self._update_timer = QTimer(self) self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._update) self._update_timer.start(200) self._color_index = 0 self._curves = {} # Crosshair def _render_measurements(cur, ref): text = 'time %.6f sec, y %.6f' % cur if ref is None: return text dt = cur[0] - ref[0] dy = cur[1] - ref[1] if abs(dt) > 1e-12: freq = '%.6f' % abs(1 / dt) else: freq = 'inf' display_measurements(text + ';' + ' ' * 4 + 'dt %.6f sec, freq %s Hz, dy %.6f' % (dt, freq, dy)) display_measurements( 'Hover to sample Time/Y, click to set new reference') add_crosshair(self._plot_widget, _render_measurements) # Final reset self.reset() def _trigger_auto_reset_if_needed(self): ts = time.monotonic() dt = ts - self._last_update_ts self._last_update_ts = ts if dt > 2: self._reset_required = True def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'data': (data_x, data_y), 'plot': plot} self._trigger_auto_reset_if_needed() def update_values(self, curve_id, x, y): curve = self._curves[curve_id] old_x, old_y = curve['data'] curve['data'] = numpy.append(old_x, x), numpy.append(old_y, y) self._trigger_auto_reset_if_needed() def reset(self): for curve in self._curves.keys(): self._plot_widget.removeItem(self._curves[curve]['plot']) self._curves = {} self._color_index = 0 self._plot_widget.enableAutoRange(enable=self.AUTO_RANGE_FRACTION, x=self.AUTO_RANGE_FRACTION, y=self.AUTO_RANGE_FRACTION) self._legend.scene().removeItem(self._legend) self._legend = self._plot_widget.addLegend() def _update(self): if self._reset_required: self.reset() self._reset_required = False for curve in self._curves.values(): if len(curve['data'][0]): curve['plot'].setData(*curve['data'])
class Design(QWidget): colors = {"cathode": "#FF0000", "anode": "#0000FF", "full": "#000000"} symbols = {"cathode": "o", "anode": "s", "full": "t"} def __init__(self, parent): super(Design, self).__init__() self.parent = parent self.core = parent.core self.parameters = None self.datas = None self.renderWindow() self.initPlotView() self.setUpProcessUI() self.bindEvents() def bindEvents(self): self.generate.clicked.connect(self.genCurve) self.save.clicked.connect(self.saveCurve) self.Sheme.currentIndexChanged.connect(self.selectScheme) pass def renderWindow(self): #边框结构 self.setGeometry(80, 80, 800, 420) size = self.geometry() screen = QDesktopWidget().screenGeometry() posX = (screen.width() - size.width()) / 2 posY = (screen.height() - size.height()) / 2 self.move(posX, posY) #标题 self.setWindowTitle('Designer') self.setWindowIcon(QIcon('resource/curve.ico')) #布局 layout = QGridLayout() self.graphicsView = QGridLayout() layout.addLayout(self.graphicsView, 0, 0, 1, 1) self.Process_Box = QGroupBox() self.Process_Box.setMinimumSize(240, 440) self.Process_Box.setFlat(True) layout.addWidget(self.Process_Box, 0, 1, 1, 1) self.setLayout(layout) def setUpProcessUI(self): layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) layout.setSpacing(10) self.Process_Box.setLayout(layout) layout.addWidget(QLabel(self.translate('Standard Cathode')), 0, 0, 1, 3) layout.addWidget(QLabel(self.translate('Standard Anode')), 1, 0, 1, 3) layout.addWidget(QLabel( self.translate('Capacity Ratio of 0.01C/0.2C')), 2, 0, 1, 3) #() layout.addWidget(QLabel(self.translate('Capacity of 0.2C')), 3, 0, 1, 3) layout.addWidget(QLabel(self.translate('1st Cycle Efficiency')), 4, 0, 1, 3) layout.addWidget(QLabel(self.translate('Cathode Area')), 5, 0, 1, 3) layout.addWidget(QLabel(self.translate('Cathode Coating Weight')), 6, 0, 1, 3) layout.addWidget(QLabel(self.translate('Cathode Loading')), 7, 0, 1, 3) layout.addWidget(QLabel(self.translate('Anode Coating Weight')), 8, 0, 1, 3) layout.addWidget(QLabel(self.translate("Anode Loading")), 9, 0, 1, 3) layout.addWidget(QLabel(self.translate("Sheme")), 10, 0, 1, 3) layout.addWidget(QLabel(self.translate("Discharge Start Voltage")), 11, 0, 1, 3) layout.addWidget(QLabel(self.translate("Discharge End Voltage")), 12, 0, 1, 3) self.Cathodes = QComboBox() self.Anodes = QComboBox() keys = list(self.core.datas.keys()) keys.sort(key=lambda x: self.core.order.index(x)) for k in keys: for tag in self.core.pos_tag: if isStartWith(k, tag): self.Cathodes.addItem(k) break for tag in self.core.neg_tag: if isStartWith(k, tag): self.Anodes.addItem(k) break self.Sheme = QComboBox() self.Sheme.addItems([ self.translate("Discharge Start Voltage"), self.translate("Discharge End Voltage") ]) self.Ratio = SpinBox(lower=0, upper=10, dec=4) self.Capacity = SpinBox(lower=0, upper=10000, val=0, dec=4) self.Efficiency = SpinBox(lower=0, upper=1, val=0.98, dec=4) self.CathodeArea = SpinBox(lower=0, upper=1E9, dec=4) self.CathodeCW = SpinBox(lower=0, upper=1E9, dec=4) self.CathodeLoading = SpinBox(lower=0, upper=1, dec=4) self.AnodeCW = SpinBox(lower=0, upper=1E9, dec=4) self.AnodeLoading = SpinBox(lower=0, upper=1, dec=4) self.StartVoltage = SpinBox(lower=0, upper=5, val=4.3, dec=4) self.EndVoltage = SpinBox(lower=0, upper=5, val=2.7, dec=4) layout.addWidget(self.Cathodes, 0, 3, 1, 3) layout.addWidget(self.Anodes, 1, 3, 1, 3) layout.addWidget(self.Ratio, 2, 3, 1, 3) layout.addWidget(self.Capacity, 3, 3, 1, 3) layout.addWidget(self.Efficiency, 4, 3, 1, 3) layout.addWidget(self.CathodeArea, 5, 3, 1, 3) layout.addWidget(self.CathodeCW, 6, 3, 1, 3) layout.addWidget(self.CathodeLoading, 7, 3, 1, 3) layout.addWidget(self.AnodeCW, 8, 3, 1, 3) layout.addWidget(self.AnodeLoading, 9, 3, 1, 3) layout.addWidget(self.Sheme, 10, 3, 1, 3) layout.addWidget(self.StartVoltage, 11, 3, 1, 3) layout.addWidget(self.EndVoltage, 12, 3, 1, 3) self.load = QPushButton(self.translate("Load")) self.generate = QPushButton(self.translate("Generate")) self.save = QPushButton(self.translate("Save")) self.load.setDisabled(True) scheme = int(self.defaultSetting("Design/Sheme", 0)) self.Sheme.setCurrentIndex(scheme) self.selectScheme() layout.addWidget(self.load, 13, 0, 1, 2) layout.addWidget(self.generate, 13, 2, 1, 2) layout.addWidget(self.save, 13, 4, 1, 2) pass def initPlotView(self): self.plot = PlotWidget(enableAutoRange=True) self.plotLegand = self.plot.addLegend() self.graphicsView.addWidget(self.plot) self.setGraphViewStyle() def setGraphViewStyle(self): bgColor = self.defaultSetting('Graph/BackgroundColor', '#ffffff') gridAlpha = float(self.defaultSetting('Graph/GridAlpha', 0.25)) axisColor = self.defaultSetting('Graph/AxisColor', '#000000') axisWidth = float(self.defaultSetting('Graph/AxisWidth', 1.5)) self.plot.setAutoVisible(y=True) self.plot.setBackground(bgColor) self.plot.showGrid(x=True, y=True, alpha=gridAlpha) self.plot.getAxis('bottom').setPen(color=axisColor, width=axisWidth) self.plot.getAxis('left').setPen(color=axisColor, width=axisWidth) def drawCurve(self, x, y, text): self.plot.removeItem(text) curveType = self.defaultSetting('Curve/type', 'line') width = int(self.defaultSetting('Curve/width', 3)) size = int(self.defaultSetting('Curve/size', 5)) color = self.colors[text] symbol = self.symbols[text] pen = mkPen(color=color, width=width) text = self.translate(text) self.plotLegand.removeItem(text) if curveType == 'scatter': self.plot.plot(x, y, pen=pen, symbolBrush=color, symbolPen=color, symbol=symbol, symbolSize=size, name=text) else: self.plot.plot(x, y, pen=pen, name=text) self.plot.show() def genCurve(self): posName = self.Cathodes.currentText() negName = self.Anodes.currentText() capacity = self.Ratio.value() * self.Capacity.value() posMass = self.CathodeArea.value() * self.CathodeCW.value( ) * self.CathodeLoading.value() / 1540.25 negMass = self.CathodeArea.value() * self.AnodeCW.value( ) * self.AnodeLoading.value() / 1540.25 efficiency = self.Efficiency.value() if capacity * posMass * negMass * efficiency == 0 or posName == "" or negName == "": self.critical("Invalid Parameters!") return posLoss = capacity * (1 / efficiency - 1) #print(posMass,posLoss) posData = self.core.get_data(posName).modify_x(posMass, 0) posLoss = posData.x_max - capacity - posLoss if posLoss < 0: return self.cathodeLess() posData = self.core.get_data(posName).modify_x(posMass, posLoss) #print(posMass,posLoss) if self.Sheme.currentIndex() == 1: terminal = posData.posValue(capacity) #print(terminal) if terminal == None: return self.cathodeLess() delta = terminal - self.EndVoltage.value() negData = self.core.get_data(negName).modify_x(negMass, 0) terminal = negData.invert().posValue(delta) if terminal == None or terminal < capacity: return self.anodeLess() negLoss = terminal - capacity negData = self.core.get_data(negName).modify_x(negMass, negLoss) else: terminal = posData.posValue(0) if terminal == None: return self.cathodeLess() delta = terminal - self.StartVoltage.value() negData = self.core.get_data(negName).modify_x(negMass, 0) #print(delta) terminal = negData.invert().posValue(delta) if terminal == None: return self.anodeLess() negLoss = terminal negData = self.core.get_data(negName).modify_x(negMass, negLoss) if negData.x_max < capacity: return self.anodeLess() fulDataX = np.linspace(0, capacity, 2000) fulDataY = posData.interpolate(fulDataX).y_data - negData.interpolate( fulDataX).y_data self.parameters = [posMass, posLoss, negMass, negLoss] self.datas = [posData, negData, posData.copy(fulDataX, fulDataY)] for x in self.plot.items(): if isinstance(x, (ScatterPlotItem, PlotCurveItem, PlotDataItem)): self.plot.removeItem(x) self.drawCurve(*posData(), "cathode") self.drawCurve(*negData(), "anode") self.drawCurve(fulDataX, fulDataY, "full") def saveCurve(self): # (value, ok) = QInputDialog.getText(self, self.translate("Save Data"), self.translate("Please input data name"), QLineEdit.Normal, "") # if not ok: # return # if self.parameters == None or self.datas == None: # return # if value == "": # self.critical("Data name can not be empty string!") # return # elif re.match(r'(\:|\\|\/|\*|\?|\"|<|>|\|)',value): # self.critical("There are invalid characters in the data name!") # return # if (value + "_full") in self.core.datas or (value + "_anode") in self.core.datas or (value + "_cathode") in self.core.datas: # ok = self.warnning("Data with the same name already exists!\nDo you want to override old datas?") # if not ok: # return # self.core.add_data((value + "_cathode"),self.datas[0],override=True) # self.core.add_data((value + "_anode"),self.datas[1],override=True) # self.core.add_data((value + "_full"),self.datas[2],override=True) self.core.max_capacity = self.Ratio.value() * self.Capacity.value() self.parent.setSetting('Core/MaxCapacity', self.core.max_capacity) self.core.auto_cal_param(self.parameters[0], 0) self.core.auto_cal_param(self.parameters[1], 1) self.core.auto_cal_param(self.parameters[2], 2) self.core.auto_cal_param(self.parameters[3], 3) self.core.for_fitting = [ self.Cathodes.currentText(), self.Anodes.currentText(), "" ] self.core.triggle('change') self.core.triggle('fitting') def anodeLess(self): self.critical( "The theoretical maximum anode capacity is less than the design capacity!" ) def cathodeLess(self): self.critical( "The theoretical maximum cathode capacity is less than the design capacity!" ) def selectScheme(self, idx=0): if self.Sheme.currentIndex() == 0: self.EndVoltage.setDisabled(True) self.StartVoltage.setEnabled(True) else: self.StartVoltage.setDisabled(True) self.EndVoltage.setEnabled(True) self.setSetting("Design/Sheme", self.Sheme.currentIndex()) def translate(self, text): if self.parent: self.langText = self.parent.langText else: self.langText = load(open('SCN.translation', encoding='utf-8')) if text in self.langText: return self.langText[text] return text def defaultSetting(self, key, value): if self.parent: return self.parent.defaultSetting(key, value) return value def setSetting(self, key, value): if self.parent: return self.parent.setSetting(key, value) def critical(self, text): QMessageBox.critical(self, self.translate("Critical"), self.translate(text), QMessageBox.Yes) def warnning(self, text): return QMessageBox.warning(self, self.translate("Warning"), self.translate(text), QMessageBox.No | QMessageBox.Yes)
class Ui_Dialog(object): def setupUi(self, Dialog, gen): pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') Dialog.setObjectName("Dialog") Dialog.resize(600, 900) self.a = 13 self.i = 0 self.flag = 0 self.gen = copy.copy(gen) self.next = QtWidgets.QPushButton(Dialog) self.next.setGeometry(QtCore.QRect(496, 863, 93, 28)) self.next.setObjectName("next") self.showtable = QtWidgets.QPushButton(Dialog) self.showtable.setGeometry(QtCore.QRect(10, 863, 93, 28)) self.showtable.setObjectName("showtable") self.label = QtWidgets.QLabel(Dialog) self.label.setGeometry(QtCore.QRect(220, 863, 171, 21)) self.label.setObjectName("label") self.plotw = PlotWidget(Dialog) self.plotw.setGeometry(QtCore.QRect(0, 0, 607, 854)) self.plotw.setObjectName("plotw") self.plotw.getViewBox().invertX(True) self.plotw.showGrid(x=True, y=True, alpha=0.3) (xrange, yrange) = self.makeVector() self.plotw.setXRange(0, -xrange) self.plotw.getViewBox().setAspectLocked(True) self.plotw.setYRange(0, yrange) self.plotw.getPlotItem().getAxis("bottom").setLabel(text='d (cm)') self.plotw.getPlotItem().getAxis("left").setLabel(text='q (cm)') self.plotw.addLegend() self.initUI() self.retranslateUi(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog) def initUI(self): self.next.clicked.connect(self.plotDiag) self.showtable.clicked.connect(self.showTable) def makeVector(self): Iqpu = np.absolute(self.gen.Igpu) * np.sin(np.radians(self.gen.alfa)) Idpu = -np.absolute(self.gen.Igpu) * np.cos(np.radians(self.gen.alfa)) Uqpu = np.absolute(self.gen.Ugpu) * np.sin( np.radians(self.gen.alfa) + np.radians(self.gen.phi)) Udpu = -np.absolute(self.gen.Ugpu) * np.cos( np.radians(self.gen.alfa) + np.radians(self.gen.phi)) C = (0, np.absolute(self.gen.Ugpu + (self.gen.Xq * self.gen.Igpu) * 1j)) B = (Udpu, Uqpu) OA = self.gen.OA CA = np.absolute(self.gen.Ugpu) * np.sin(np.radians( self.gen.phi)) + np.absolute(self.gen.Igpu) * self.gen.Xq if 2 * C[1] != 0: y_a = (OA**2 + C[1]**2 - CA**2) / (2 * C[1]) else: y_a = 0 x_a = -np.sqrt(OA**2 - y_a**2) A = (x_a, y_a) IX2 = (B[1] - Idpu * self.gen.Xd2, B[0] + Iqpu * self.gen.Xq2) IX1 = (B[1] - Idpu * self.gen.Xd1, B[0] + Iqpu * self.gen.Xq1) IX = (B[1] - Idpu * self.gen.Xd, B[0] + Iqpu * self.gen.Xq) xrange = -Idpu self.x = [0, Idpu, 0, 0, 0, Idpu, 0, Udpu, 0, 0, 0, Udpu] self.y = [0, Iqpu, 0, Iqpu, 0, 0, 0, Uqpu, 0, Uqpu, 0, 0] if np.absolute(self.gen.Ugpu) > np.absolute(self.gen.Igpu): pass self.limit = 41 self.x = self.x + [0, A[0]] self.y = self.y + [0, A[1]] xrange = -A[0] else: self.limit = 39 self.flag = self.limit self.x = self.x + [ A[0], C[0], B[0], B[0], B[0], B[0], B[0], B[0], B[0], IX[1], B[0], IX1[1], B[0], IX2[1], B[0], IX[1], B[0], IX1[1], B[0], IX2[1], 0, IX[1], 0, IX1[1], 0, IX2[1] ] self.y = self.y + [ A[1], C[1], B[1], IX[0], B[1], IX1[0], B[1], IX2[0], IX[0], IX[0], IX1[0], IX1[0], IX2[0], IX2[0], B[1], IX[0], B[1], IX1[0], B[1], IX2[0], 0, IX[0], 0, IX1[0], 0, IX2[0] ] self.next.setDisabled(True) for xx, yy in zip(self.x, self.y): if xx != 0 or yy != 0: self.next.setDisabled(False) return xrange, IX[0] def plotDiag(self): if self.i < 5: color = 4 elif self.i < 11: color = 7 elif self.i < self.a: color = 6 if self.flag == 41: self.flag = 0 self.a = 15 color = 4 elif self.i in [self.a + 1, self.a + 7, self.a + 13, self.a + 19]: color = 0 elif self.i in [self.a + 3, self.a + 9, self.a + 15, self.a + 21]: color = 11 elif self.i in [self.a + 5, self.a + 11, self.a + 17, self.a + 23]: color = 13.9 pen = pg.mkPen(color, width=3) if self.i < self.limit: if self.i == 0: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen, name='I') elif self.i == 6: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen, name='U') elif self.i == self.a - 1: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen, name='AC') elif self.i == self.a + 1: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen, name='E') elif self.i == self.a + 3: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen, name="E'") elif self.i == self.a + 5: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen, name='E"') else: self.plotw.plot(self.x[self.i:self.i + 2], self.y[self.i:self.i + 2], pen=pen) self.i = self.i + 2 if self.i == self.limit - 1: self.next.setDisabled(True) def showTable(self): self.window = QtWidgets.QMainWindow() self.ui2 = Ui_Form() self.ui2.setupUi(self.window) self.ui2.passValues(self.x, self.y) self.window.show() self.window.setFixedSize(self.window.size()) def retranslateUi(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_translate("Vector Diagram", "Vector Diagram")) self.next.setText(_translate("Dialog", "Next")) self.showtable.setText(_translate("Dialog", "Show table")) self.label.setText( _translate("Dialog", "assumed scale is 1 cm for p.u "))
class App(QWidget): def __init__(self): super().__init__() #todo: Agregar estilos a nuestro proyecto self.setStyleSheet(style.style) self.layoutUI() self.tabletas_zipra = 28; self.tabletas_rispe = 40 self.tabletas_halo = 20 self.tabletas_olan = 14 self.tabletas_cloza = 30 self.zipra_dia = 2 self.rispe_dia = 2 self.halo_dia = 2 self.olan_dia = 1 self.cloza_dia = 2 def layoutUI(self): # layout principal self.principalLayout = QHBoxLayout(self) # primer Frame self.firstFrame = QFrame(self) self.firstFrame.setFrameShape(QFrame.StyledPanel) self.firstFrame.setFrameShadow(QFrame.Raised) self.firstFrame.setObjectName("contenedor1") # Frame II self.second_Frame = QFrame() self.second_Frame.setObjectName("contenedor2") # Layouts self.verticalLayout = QVBoxLayout(self.firstFrame) self.gridLayout = QGridLayout() self.grafic_principal = QVBoxLayout(self.second_Frame) self.grafic_plot = QVBoxLayout() self.layout_button = QGridLayout() self.text_title = QLabel( "Análisis de Simulación de coste - efectividad en el\ntratamiento de la esquizofrenia") self.text_title.setAlignment(QtCore.Qt.AlignCenter) self.text_title.setObjectName("tittle") self.grafic_principal.addWidget(self.text_title) self.text_salida = QLabel( "Salidas") self.text_salida.setAlignment(QtCore.Qt.AlignCenter) self.text_salida.setObjectName("salida") labels = {(1,0):"Ziprasidona", (2,0):"Risperidona", (3,0):"Haloperidol",(4,0):"Olanzapina",(5,0):"Clozapina",(6,1):""} self.lbl_costo = QLabel("COSTO $") self.lbl_costo.setAlignment(QtCore.Qt.AlignCenter) self.gridLayout.addWidget(self.lbl_costo, 0, 1) a = database.CargarDatos() self.text_ziprasidona = QLineEdit(str(a[0][2])) self.text_ziprasidona.setAlignment(QtCore.Qt.AlignCenter) self.text_ziprasidona.setEnabled(False) self.gridLayout.addWidget(self.text_ziprasidona, 1, 1) self.text_Risperidona = QLineEdit(str(a[1][2])) self.text_Risperidona.setAlignment(QtCore.Qt.AlignCenter) self.text_Risperidona.setEnabled(False) self.gridLayout.addWidget(self.text_Risperidona, 2, 1) self.text_haloperidol = QLineEdit(str(a[2][2])) self.text_haloperidol.setAlignment(QtCore.Qt.AlignCenter) self.text_haloperidol.setEnabled(False) self.gridLayout.addWidget(self.text_haloperidol, 3, 1) self.text_olanzapina = QLineEdit(str(a[3][2])) self.text_olanzapina.setAlignment(QtCore.Qt.AlignCenter) self.text_olanzapina.setEnabled(False) self.gridLayout.addWidget(self.text_olanzapina, 4, 1) self.text_clozapina = QLineEdit(str(a[4][2])) self.text_clozapina.setEnabled(False) self.text_clozapina.setAlignment(QtCore.Qt.AlignCenter) self.gridLayout.addWidget(self.text_clozapina, 5, 1) for pos, name in labels.items(): x, y = pos lbl = QLabel(self.firstFrame) lbl.setText(name) self.gridLayout.addWidget(lbl, x, y) self.verticalLayout.addLayout(self.gridLayout) self.principalLayout.addWidget(self.firstFrame) #? Parte de la Grafica self.graphWidget = PlotWidget() self.graphWidget.showGrid(x = True, y = True) self.graphWidget.addLegend() self.graphWidget.setTitle("Entrada",color="w", size="22px") styles = {"color": "#fff", "font-size": "23px"} self.graphWidget.setLabel("left", " Pr (la intervención es óptima) ", **styles) self.graphWidget.setLabel("bottom", "Financiamiento disponible para IMSS", **styles) self.grafic_plot.addWidget(self.graphWidget) self.grafic_principal.addLayout(self.grafic_plot) self.principalLayout.addWidget(self.second_Frame) self.verticalLayout.addWidget(self.text_salida) #! Tabla self.table = QTableWidget(5, 4,self.firstFrame) self.table.setHorizontalHeaderLabels(['TRATAMIENTO ', 'PRESENTACIÓN ', 'PRECIO IMSS ','COSTO DIARIO ']) self.table.setAlternatingRowColors(True) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setSelectionMode(QTableWidget.SingleSelection) self.verticalLayout.addWidget(self.table) #! Boton self.start_simulation = QPushButton(" Iniciar simulación") self.start_simulation.clicked.connect(self.event_simulation) self.start_simulation.setObjectName("buttonsim") self.button_save = QPushButton("Guardar plot") self.button_save.setObjectName("save") self.button_save.hide() self.button_save.clicked.connect(self.saveFig) self.grafic_plot.addWidget(self.button_save) self.layout_button.addWidget(self.start_simulation,0,1) self.verticalLayout.addLayout(self.layout_button) #Todo cargar datos desde la bdd def simulation_data(self): database.connnection() a = database.CargarDatos() for i in range(len(a)): for j in range(len(a[i])): self.table.setItem(i,j,QTableWidgetItem(str(a[i][j]))) #Todo Event simulator def event_simulation(self): self.simulation_data() prob_zipra=0.4 prob_aloper=0.06 prob_clozapina=0.9 prob_risper=0.007 prob_olanzap=0.01 y_zipra = [] y_aloper = [] y_clozapina = [] y_olanzap = [] y_risper = [] x = arange(0,1000,1) for y in x: y_zipra.append(1+exp(-prob_zipra*int(y))) y_aloper.append(1+exp(-prob_aloper*int(y))) y_clozapina.append(1-exp(-prob_clozapina*int(y))) y_olanzap.append(1-exp(-prob_olanzap*int(y))) y_risper.append(1-exp(-prob_risper*int(y))) self.graphWidget.setXRange(-0.2,22,padding=0) self.graphWidget.setYRange(-0.1,2.3,padding=0) self.plot(x,y_zipra,'Ziprasidona','r',"o") self.plot(x,y_aloper,'Haloperidol','y',"t1") self.plot(x,y_clozapina,'Clozapina','b',"x") self.plot_2(x,y_olanzap,'Olanzapina','g',"p") self.plot_2(x,y_risper,'Risperidona','s',"+") self.costo_diario_zipra = round(float(self.text_ziprasidona.text())/(self.tabletas_zipra/self.zipra_dia),4) self.costo_diario_rispe = round(float(self.text_Risperidona.text())/(self.tabletas_rispe/self.rispe_dia),4) self.costo_diario_halo = round(float(self.text_haloperidol.text())/(self.tabletas_halo/self.halo_dia),4) self.costo_diario_olan = round(float(self.text_olanzapina.text())/(self.tabletas_olan/self.olan_dia),4) self.costo_diario_cloza = round(float(self.text_clozapina.text())/(self.tabletas_cloza/self.cloza_dia),4) self.table.setItem(0,3,QTableWidgetItem(str(self.costo_diario_zipra))) self.table.setItem(1,3,QTableWidgetItem(str(self.costo_diario_rispe))) self.table.setItem(2,3,QTableWidgetItem(str(self.costo_diario_halo))) self.table.setItem(3,3,QTableWidgetItem(str(self.costo_diario_olan))) self.table.setItem(4,3,QTableWidgetItem(str(self.costo_diario_cloza))) self.button_save.show() self.start_simulation.setEnabled(False) def plot(self, x, y, plotname, color,symbol): pen = mkPen(color=color,style=QtCore.Qt.DashLine) self.graphWidget.plot(x, y, name=plotname, pen=pen, symbol=symbol, symbolSize=10, symbolBrush=(color)) def plot_2(self, x, y, plotname, color,symbol): pen = mkPen(color=color,style=QtCore.Qt.DashLine) self.graphWidget.plot(x, y, name=plotname, symbol=symbol,pen=pen, symbolSize=10, symbolBrush=(color)) # Guardar la imagen en un directorio de nuestro ordenador def saveFig(self): exp = exporters.ImageExporter(self.graphWidget.plotItem) exp.parameters()['width'] = 1000 options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName,_ = QFileDialog.getSaveFileName(self, "QFileDialog.getSaveFileName()","Plot.png","All Files (*);;Text Files (*.png)", options=options) if fileName !="": exp.export(fileName) imagen = Image.open(fileName) imagen.show()
def init_widget(self): layout = QtGui.QHBoxLayout() self.setLayout(layout) plot_layout = QtGui.QHBoxLayout() layout.addLayout(plot_layout) plots = {} traces = {} for plot in PLOTS: plot_dict = PLOTS_DICT[plot] plot_widget = PlotWidget( title=plot_dict[TITLE], labels={ 'bottom':'time (samples)', 'left':plot_dict[LABEL] } ) plot_traces = plot_dict[TRACES] if len(plot_traces) > 1: plot_widget.addLegend() trace_index = 0 colors = ('F33','3F3','33F') for trace_key, trace_d in plot_traces.items(): trace = [0] * HISTORY kwargs = { LINE:{ 'pen':{'color':colors[trace_index]} }, SCATTER:{ 'pen':None, 'symbol':'o', 'symbolSize':3, 'symbolBrush':colors[trace_index] } }[trace_d[TRACE_TYPE]] kwargs['name'] = trace_d[TRACE_NAME] plot = plot_widget.plot( trace, **kwargs ) plots[trace_key] = plot traces[trace_key] = trace trace_index += 1 plot_layout.addWidget(plot_widget) client = yield connectAsync() sh_server = client.sample_heater controls_layout = QtGui.QVBoxLayout() layout.addLayout(controls_layout) temperature_setpoint_layout = QtGui.QHBoxLayout() controls_layout.addWidget( LabelWidget( 'temperature setpoint', temperature_setpoint_layout ) ) temperature_setpoint_label = QtGui.QLabel() temperature_setpoint_layout.addWidget(temperature_setpoint_label) temperature_setpoint_layout.addStretch() temperature_setpoint_spin = QtGui.QSpinBox() temperature_setpoint_spin.setRange(MIN_TEMPERATURE,MAX_TEMPERATURE) temperature_setpoint_spin.setPrefix('temp') temperature_setpoint_spin.setSuffix('C') temperature_setpoint_layout.addWidget(temperature_setpoint_spin) temperature_setpoint_button = QtGui.QPushButton('set') temperature_setpoint_layout.addWidget(temperature_setpoint_button) def set_temperature_setpoint(): catch_labrad_error( self, sh_server.set_temperature_setpoint(temperature_setpoint_spin.value()) ) temperature_setpoint_button.clicked.connect(set_temperature_setpoint) def update_temperature_setpoint(temperature_setpoint): self.temperature_setpoint = temperature_setpoint temperature_setpoint_label.setText('temp setpoint: %d' % self.temperature_setpoint) sh_server.on_temperature_setpoint_changed.connect( lambda c, temperature_setpoint: update_temperature_setpoint(temperature_setpoint) ) temperature_setpoint = yield sh_server.get_temperature_setpoint() update_temperature_setpoint(temperature_setpoint) def update_label(label,state): label.setText('status: ' + str(state)) for name, signal, getter, setter, option_1, option_2 in ( ( 'heating state', sh_server.on_heating_state_changed, sh_server.get_heating_state, sh_server.set_heating_state, 'heating', 'cooling' ), ( 'feedback state', sh_server.on_feedback_state_changed, sh_server.get_feedback_state, sh_server.set_feedback_state, True, False ), ( 'temperature limit state', sh_server.on_temperature_limit_state_changed, sh_server.get_temperature_limit_state, None, None, None ), ( 'emission current limit state', sh_server.on_emission_current_limit_state_changed, sh_server.get_emission_current_limit_state, None, None, None ), ( 'thermocouple state', sh_server.on_thermocouple_state_changed, sh_server.get_thermocouple_state, None, None, None ), ): layout = QtGui.QHBoxLayout() controls_layout.addWidget( LabelWidget( name, layout ) ) label = QtGui.QLabel() layout.addWidget(label) layout.addStretch() state = yield getter() update_label(label,state) def get_slot(label): def slot(c,state): update_label(label,state) return slot signal.connect(get_slot(label)) if setter is None: continue def cb(setter,option): catch_labrad_error( self, setter(option) ) for option in (option_1,option_2): button = QtGui.QPushButton(str(option)) layout.addWidget(button) button.clicked.connect(partial(cb,setter,option)) for lockable_setting in ( sh_server.set_feedback_state, sh_server.set_heating_state, sh_server.set_temperature_setpoint ): controls_layout.addWidget(LockWidget(sh_server,lockable_setting.ID,lockable_setting.name)) def update_plot(plot,sample): t = traces[plot] t.insert(0,sample) t.pop() plots[plot].setData(t) @inlineCallbacks def loop(): packet = sh_server.packet() packet.get_filament_control() packet.get_emission_current() packet.get_temperature() packet.get_rate() packet.get_rate_setpoint() result = yield packet.send() filament_control = result.get_filament_control update_plot(FILAMENT_TRACE,filament_control) temperature = result.get_temperature update_plot(TEMPERATURE_TRACE,temperature) emission_current = result.get_emission_current update_plot(EMISSION_TRACE,emission_current) rate = result.get_rate update_plot(RATE_TRACE,rate) rate_setpoint = result.get_rate_setpoint update_plot(RATE_SETPOINT_TRACE,rate_setpoint) temperature_setpoint = self.temperature_setpoint update_plot(TEMPERATURE_SETPOINT_TRACE,temperature_setpoint) rate_average = np.average(traces[RATE_TRACE][:RUNNING_AVERAGE]) update_plot(RATE_AVERAGE,rate_average) loop() loop()
class VNAVibrationWidget(VNAWidget): def __init__(self): super(VNAVibrationWidget, self).__init__() self.setWindowTitle("VNA Vibration Analyzer") self.fft_plot = PlotWidget() self.mean_fft_plot = PlotWidget() self.mean_fft_plot.addLegend() self.plot_layout.addWidget(self.fft_plot) self.plot_layout.addWidget(self.mean_fft_plot) continuous_button = QPushButton("Continuous Acquire") break_button = QPushButton("Break") reset_button = QPushButton("Reset Average") self.button_layout.addWidget(continuous_button) self.button_layout.addWidget(break_button) self.button_layout.addWidget(reset_button) continuous_button.clicked.connect(self.continuous_acquire) break_button.clicked.connect(self.set_break_acquire) reset_button.clicked.connect(self.reset_averaging) self.reset_averaging() def reset_averaging(self): self.acquisition_number = 0 self.fft_points = {} self.mean_fft_points = {} self.mean_fft_plot.clear() def grab_trace(self): super(VNAVibrationWidget, self).grab_trace() self.acquisition_number += 1 # Frequency Axis sweep_time = self.get_vna().get_sweep_time() n_points = self.get_vna().get_points() self.fft_plot.clear() self.mean_fft_plot.clear() self.mean_fft_plot.plotItem.legend.setParent(None) self.mean_fft_plot.addLegend() for name, dataset, pen in [('mag', self.mags, 'r'), ('phase', self.phases, 'g')]: self.fft_points[name] = numpy.abs(rfft(dataset - dataset.mean())) if name not in self.mean_fft_points: self.mean_fft_points[name] = self.fft_points[name] else: self.mean_fft_points[name] += self.fft_points[name] self.mean_fft_points[name] /= float(self.acquisition_number-1) / self.acquisition_number self.fft_freqs = fftfreq(n_points, sweep_time / n_points)[:len(self.fft_points[name])] self.fft_plot.plot(self.fft_freqs, self.fft_points[name], pen=pen) self.mean_fft_plot.plot(self.fft_freqs, self.mean_fft_points[name], pen=pen, name=name) self.mean_fft_plot.autoRange() def save_trace(self): super(VNAVibrationWidget, self).save_trace() group = self.get_h5group() group['fft_freqs'] = self.fft_freqs for name in ('mag', 'phase'): group[name+'_fft'] = self.fft_points[name] group[name+'_mean_fft'] = self.mean_fft_points[name] dataserver_helpers.set_scale(group, 'fft_freqs', name+'_fft') dataserver_helpers.set_scale(group, 'fft_freqs', name+'_mean_fft') group.attrs['n_averages'] = self.acquisition_number group.file.close() def set_break_acquire(self): self.break_acquire = True def continuous_acquire(self): self.break_acquire = False while not self.break_acquire: self.grab_trace() self.message('Acquisition Number %d' % self.acquisition_number) QApplication.instance().processEvents()
class VNAWidget(QWidget): settings = None def __init__(self): super(VNAWidget, self).__init__() self.setWindowTitle("VNA Window") layout = QVBoxLayout(self) self.plot_layout = QHBoxLayout() layout.addLayout(self.plot_layout) self.mag_plot = PlotWidget() self.mag_plot.addLegend() self.plot_layout.addWidget(self.mag_plot) self.message_box = QPlainTextEdit() layout.addWidget(self.message_box) self.form_layout = QFormLayout() layout.addLayout(self.form_layout) self.dataset_edit = QLineEdit("TestSample") save_file_button = QPushButton("HDF5 File") self.save_file_edit = QLineEdit("C:\\_Data\\test.h5") # self.form_layout.addRow("VNA Address", self.address_combo_box) self.form_layout.addRow(save_file_button, self.save_file_edit) dataset_button = QPushButton("Dataset") self.form_layout.addRow(dataset_button, self.dataset_edit) self.button_layout = QHBoxLayout() layout.addLayout(self.button_layout) grab_trace_button = QPushButton("Grab Trace") save_button = QPushButton("Save") self.button_layout.addWidget(grab_trace_button) self.button_layout.addWidget(save_button) self.freqs = None self.mags = None self.phases = None self.vna = None self.current_vna_addr = None self.vna_params = None save_file_button.clicked.connect(self.change_save_file) dataset_button.clicked.connect(self.change_dataset) grab_trace_button.clicked.connect(self.grab_trace) save_button.clicked.connect(self.save_trace) def get_vna(self): return instruments['VNA'] def grab_trace(self): vna = self.get_vna() self.freqs = vna.do_get_xaxis() self.mags, self.phases = vna.do_get_data() self.replot() self.vna_params = vna.get_parameter_values(query=True) self.message("VNA Params") self.message("----------") for k, v in self.vna_params.items(): self.message(k, ":", v) self.message("") def replot(self): self.mag_plot.clear() self.mag_plot.plotItem.legend.setParent(None) self.mag_plot.addLegend() if self.freqs is None: return self.mag_plot.plot(self.freqs, self.mags, pen='g', name='Data') def message(self, *objs): self.message_box.appendPlainText(" ".join([str(o) for o in objs])) def change_save_file(self): filename = QFileDialog.getSaveFileName( self, "Save File", self.save_file_edit.text(), "HDF5 files (*.h5 *.hdf5)", options=QFileDialog.DontConfirmOverwrite ) self.save_file_edit.setText(filename) def change_dataset(self): dialog = QDialog() layout = QVBoxLayout(dialog) model = H5File(h5py.File(str(self.save_file_edit.text()))) tree_view = H5View() tree_view.setModel(model) tree_view.setSelectionMode(QAbstractItemView.SingleSelection) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(dialog.accept) button_box.rejected.connect(dialog.reject) layout.addWidget(tree_view) layout.addWidget(button_box) if dialog.exec_(): #self.dataset_edit.setText(tree_view.selected_path()[1:]) dsname = model.itemFromIndex(tree_view.selectedIndexes()[0]).fullname[1:] self.dataset_edit.setText(dsname) def get_h5group(self): filename = str(self.save_file_edit.text()) h5file = datasrv.get_file(filename) path = str(self.dataset_edit.text()) return h5helpers.resolve_path(h5file, path) def save_trace_csv(self): default_name = time.strftime("trace_%Y%m%d_%H%M%S.dat") save_path = str(self.save_path_edit.text()) default_filename = os.path.join(save_path, default_name) filename = str(QFileDialog.getSaveFileName(self, "Save Trace", default_filename)) data = numpy.array([self.freqs, self.mags, self.phases]).transpose() numpy.savetxt(filename, data) def save_trace(self): group = self.get_h5group() if 'freqs' in group: reply = QMessageBox.question(self, "", "Dataset exists in file, Overwrite?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.No: return group['freqs'] = self.freqs group['mags'] = self.mags group['phases'] = self.phases h5helpers.set_scale(group, 'freqs', 'mags') h5helpers.set_scale(group, 'freqs', 'phases') h5helpers.update_attrs(group, self.vna_params) self.message("Saved in file %s" % group.get_fullname())
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) self.resize(1920, 1080) self.status = False self.setAutoFillBackground(False) self.setDocumentMode(False) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) self.exitAct = QAction(QIcon('exit.png'), '&Exit', self) self.exitAct.setShortcut('Ctrl+Q') self.exitAct.setStatusTip('Exit application') self.exitAct.triggered.connect(qApp.quit) self.loadAct = QAction(QIcon('exit.png'), '&Import Unfolding', self) self.loadAct.setShortcut('Ctrl+L') self.loadAct.setStatusTip('Import Unfolding') self.loadAct.triggered.connect(self.openFileNameDialog) self.exportAct = QAction(QIcon('exit.png'), '&Export Unfolding', self) self.exportAct.setShortcut('Ctrl+E') self.exportAct.setStatusTip('Export Unfolding') self.exportAct.triggered.connect(self.exportUnfolding) self.writeNPAct = QAction(QIcon('exit.png'), '&Write coordinates as np file', self) self.writeNPAct.setShortcut('Ctrl+W') self.writeNPAct.setStatusTip('Write coordinates') self.writeNPAct.triggered.connect(self.writeNP_file) self.loadGeometryAct = QAction(QIcon('exit.png'), '&Load geometry from .log file', self) #self.loadGeometry.setShortcut('Ctrl+W') self.loadGeometryAct.setStatusTip('Load geometry') self.loadGeometryAct.triggered.connect(self.loadGeometry) self.select_directoryAct = QAction( QIcon('exit.png'), '&Select a directory to generate hdf5 files from', self) self.select_directoryAct.setStatusTip('Select directory') self.select_directoryAct.triggered.connect(self.select_directory) self.load_HDF5Act = QAction(QIcon('exit.png'), '&Select a hdf5 files for the DFT data', self) self.load_HDF5Act.setStatusTip('Select HDF5') self.load_HDF5Act.triggered.connect(self.load_hdf5_scan) self.statusBar() self.menubar = self.menuBar() self.fileMenu = self.menubar.addMenu('&File') self.fileMenu.addAction(self.exitAct) self.fileMenu.addAction(self.loadAct) self.fileMenu.addAction(self.exportAct) self.fileMenu.addAction(self.writeNPAct) self.fileMenu.addAction(self.loadGeometryAct) self.fileMenu.addAction(self.select_directoryAct) self.fileMenu.addAction(self.load_HDF5Act) self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setSpacing(10) self.verticalLayout = QVBoxLayout() ### Containing the integration buttons self.horizontalLayout_2 = QHBoxLayout() ### Containing the inital/final position show self.finalPositionLayout = QHBoxLayout() self.gl_widget = gl.GLViewWidget() self.gl_widget.setCameraPosition(distance=20, elevation=40) self.gl_widget.setGeometry(0, 110, 1920, 1080) self.energy_Plot = PlotWidget() self.energy_Plot.setObjectName(_fromUtf8("energyPlot")) self.energy_Plot.setBackground('k') # set properties of the label for y axis self.energy_Plot.setLabel('left', 'E(B3LYP)', units='H') # set properties of the label for x axis self.energy_Plot.setLabel('bottom', 'CC-distance', units='A') # adding legend self.energy_Plot.addLegend() self.horizontalLayout.addWidget(self.gl_widget, 4) ### Push button for sinle integration self.btnUp = QPushButton() self.btnUp.setObjectName(_fromUtf8("btnUp")) ### Check box for continous integration self.chkIntegrate = QCheckBox() self.chkIntegrate.setObjectName(_fromUtf8("chkIntegrate")) ### SpinBox to set the size of the integration step self.spinStep = QSpinBox() self.spinStep.setMinimum(0) self.spinStep.setMaximum(10000) self.spinStep.setObjectName(_fromUtf8("spinStep")) ### final position button self.btnFin = QPushButton() self.btnFin.setObjectName(_fromUtf8("btnFin")) ### initial position button self.btnInit = QPushButton() self.btnInit.setObjectName(_fromUtf8("btnPos")) ### select hinges button self.btnSelHinge = QPushButton() self.btnSelHinge.setObjectName(_fromUtf8("btnSelHinge")) ### close unfolding button self.btnClose = QPushButton() self.btnClose.setObjectName(_fromUtf8("btnClose")) ### add the buttons to the integration layout self.horizontalLayout_2.addWidget(self.spinStep) self.horizontalLayout_2.addWidget(self.btnUp) self.horizontalLayout_2.addWidget(self.chkIntegrate) ## add final position button to layout self.finalPositionLayout.addWidget(self.btnInit) self.finalPositionLayout.addWidget(self.btnFin) self.finalPositionLayout.addWidget(self.btnSelHinge) self.finalPositionLayout.addWidget(self.btnClose) ### add integration and final position layout and plot widget to right side layout self.verticalLayout.addLayout(self.horizontalLayout_2, 1) self.verticalLayout.addLayout(self.finalPositionLayout, 1) self.verticalLayout.addWidget(self.energy_Plot, 6) self.horizontalLayout.addLayout(self.verticalLayout, 1) self.widget = QWidget() self.widget.setLayout(self.horizontalLayout) self.setCentralWidget(self.widget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.setWindowTitle('Fullerene Unfolding') def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.btnUp.setText("Integrate") self.chkIntegrate.setText("Keep integrating") self.btnFin.setText("Final position") self.btnInit.setText("Initial position") self.btnClose.setText("Close unfolding") self.btnSelHinge.setText("Select Hinges")
class Window(QWidget): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.title = "Motor Control" self.setWindowTitle(self.title) #Application Size self.left = 100 self.top = 100 self.width = 1000 self.height = 700 self.setGeometry(self.left, self.top, self.width, self.height) self.initUI() def initUI(self): self.setStyleSheet(qdarkstyle.load_stylesheet()) self.horizontalLayout = QHBoxLayout() self.verticalLayout = QVBoxLayout() self.verticalLayout.setSizeConstraint(QLayout.SetDefaultConstraint) self.verticalLayout.setSpacing(6) self.gridLayout = QGridLayout() self.imageLabel = QLabel() sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.imageLabel.sizePolicy().hasHeightForWidth()) self.imageLabel.setSizePolicy(sizePolicy) self.imageLabel.setMinimumSize(QSize(200, 130)) self.imageLabel.setMaximumSize(QSize(200, 130)) self.imageLabel.setPixmap( QPixmap("./Arduino/logo/CUAtHomeLogo-Horz.png").scaled( 200, 130, Qt.KeepAspectRatio, Qt.FastTransformation)) self.verticalLayout.addWidget(self.imageLabel) self.startbutton = QPushButton("Start", self) self.startbutton.setCheckable(False) self.startbutton.clicked.connect(self.startbutton_pushed) self.startbutton.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.startbutton, 0, 0, 1, 1) self.stopbutton = QPushButton("Stop", self) self.stopbutton.setCheckable(False) self.stopbutton.clicked.connect(self.stopbutton_pushed) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.stopbutton.sizePolicy().hasHeightForWidth()) self.stopbutton.setSizePolicy(sizePolicy) self.stopbutton.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.stopbutton, 0, 1, 1, 1) self.clearbutton = QPushButton("Clear", self) self.clearbutton.setCheckable(False) self.clearbutton.clicked.connect(self.clearbutton_pushed) self.clearbutton.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.clearbutton, 1, 0, 1, 1) self.savebutton = QPushButton("Save", self) self.savebutton.setCheckable(False) self.savebutton.clicked.connect(self.savebutton_pushed) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.savebutton.sizePolicy().hasHeightForWidth()) self.savebutton.setSizePolicy(sizePolicy) self.savebutton.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.savebutton, 1, 1, 1, 1) self.settings = QPushButton("Settings", self) self.settings.clicked.connect(self.settingsMenu) self.settings.setMaximumSize(QSize(300, 20)) self.gridLayout.addWidget(self.settings, 2, 0, 1, 2) self.checkBoxShowAll = QCheckBox("Show All Plots", self) self.checkBoxShowAll.setMaximumSize(QSize(100, 20)) self.checkBoxShowAll.setChecked(True) self.checkBoxShowAll.toggled.connect(self.visibilityAll) self.gridLayout.addWidget(self.checkBoxShowAll, 3, 0, 1, 1) self.checkBoxHideAll = QCheckBox("Hide All Plots", self) self.checkBoxHideAll.setChecked(False) self.checkBoxHideAll.toggled.connect(self.hideAll) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.checkBoxHideAll.sizePolicy().hasHeightForWidth()) self.checkBoxHideAll.setSizePolicy(sizePolicy) self.checkBoxHideAll.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.checkBoxHideAll, 3, 1, 1, 1) self.checkBoxPlot1 = QCheckBox("Plot 1", self) self.checkBoxPlot1.toggled.connect(self.visibility1) self.checkBoxPlot1.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.checkBoxPlot1, 4, 0, 1, 1) self.checkBoxPlot2 = QCheckBox("Plot 2", self) self.checkBoxPlot2.toggled.connect(self.visibility2) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.checkBoxPlot2.sizePolicy().hasHeightForWidth()) self.checkBoxPlot2.setSizePolicy(sizePolicy) self.checkBoxPlot2.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.checkBoxPlot2, 4, 1, 1, 1) self.checkBoxShowAll.stateChanged.connect(self.checkbox_logic) self.checkBoxHideAll.stateChanged.connect(self.checkbox_logic) self.checkBoxPlot1.stateChanged.connect(self.checkbox_logic) self.checkBoxPlot2.stateChanged.connect(self.checkbox_logic) self.PowerScalingLabel = QLabel("Power Scaling (%)", self) self.PowerScalingLabel.setMinimumSize(QSize(100, 20)) self.PowerScalingLabel.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.PowerScalingLabel, 7, 0, 1, 1) self.PowerScalingInput = QLineEdit("", self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.PowerScalingInput.sizePolicy().hasHeightForWidth()) self.PowerScalingInput.setSizePolicy(sizePolicy) self.PowerScalingInput.setMaximumSize(QSize(100, 20)) #self.PowerScalingInput.setValidator(QRegExpValidator(QRegExp("^[0-9][0-9]?$|^100$"))) #0-1 as a float FIX THIS self.gridLayout.addWidget(self.PowerScalingInput, 7, 1, 1, 1) self.FrequencyLabel = QLabel("Frequency (Hz)", self) self.FrequencyLabel.setMinimumSize(QSize(100, 20)) self.FrequencyLabel.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.FrequencyLabel, 8, 0, 1, 1) self.FrequencyInput = QLineEdit("", self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.FrequencyInput.sizePolicy().hasHeightForWidth()) self.FrequencyInput.setSizePolicy(sizePolicy) self.FrequencyInput.setMaximumSize(QSize(100, 20)) self.FrequencyInput.setValidator(QDoubleValidator()) self.gridLayout.addWidget(self.FrequencyInput, 8, 1, 1, 1) PID_validator = QDoubleValidator( 0.0000, 50.000, 4, notation=QDoubleValidator.StandardNotation) self.PCheckBox = QCheckBox("P", self) self.PCheckBox.setMaximumSize(QSize(100, 20)) self.PCheckBox.setChecked(True) self.PCheckBox.toggled.connect(self.PCheckBoxLogic) self.gridLayout.addWidget(self.PCheckBox, 9, 0, 1, 1) self.PInput = QLineEdit("", self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.PInput.sizePolicy().hasHeightForWidth()) self.PInput.setSizePolicy(sizePolicy) self.PInput.setMaximumSize(QSize(100, 20)) self.PInput.setValidator(PID_validator) self.gridLayout.addWidget(self.PInput, 9, 1, 1, 1) self.ICheckBox = QCheckBox("I", self) self.ICheckBox.setMaximumSize(QSize(100, 20)) self.ICheckBox.setChecked(True) self.ICheckBox.toggled.connect(self.ICheckBoxLogic) self.gridLayout.addWidget(self.ICheckBox, 10, 0, 1, 1) self.IInput = QLineEdit("", self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.IInput.sizePolicy().hasHeightForWidth()) self.IInput.setSizePolicy(sizePolicy) self.IInput.setMaximumSize(QSize(100, 20)) self.IInput.setValidator(PID_validator) self.gridLayout.addWidget(self.IInput, 10, 1, 1, 1) self.DCheckBox = QCheckBox("D", self) self.DCheckBox.setMaximumSize(QSize(100, 20)) self.DCheckBox.setChecked(True) self.DCheckBox.toggled.connect(self.DCheckBoxLogic) self.gridLayout.addWidget(self.DCheckBox, 11, 0, 1, 1) self.DInput = QLineEdit("", self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.DInput.sizePolicy().hasHeightForWidth()) self.DInput.setSizePolicy(sizePolicy) self.DInput.setMaximumSize(QSize(100, 20)) self.DInput.setValidator(PID_validator) self.gridLayout.addWidget(self.DInput, 11, 1, 1, 1) self.LabType = QComboBox() self.LabType.addItems(["Position", "Speed"]) #self.LabType.activated.connect(self.getLabType) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.LabType.sizePolicy().hasHeightForWidth()) self.LabType.setSizePolicy(sizePolicy) self.LabType.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.LabType, 5, 1, 1, 1) self.LabLabel = QLabel("Lab Type") self.LabLabel.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.LabLabel, 5, 0, 1, 1) self.inputForms = QComboBox() self.inputForms.addItems(["Sine", "Step"]) self.inputForms.activated.connect(self.getInput) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.inputForms.sizePolicy().hasHeightForWidth()) self.inputForms.setSizePolicy(sizePolicy) self.inputForms.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.inputForms, 6, 1, 1, 1) self.inputType = QLabel("Input Type") self.inputType.setMaximumSize(QSize(100, 20)) self.gridLayout.addWidget(self.inputType, 6, 0, 1, 1) self.verticalLayout.addLayout(self.gridLayout) spacerItem = QSpacerItem(20, 80, QSizePolicy.Minimum, QSizePolicy.Fixed) self.verticalLayout.addItem(spacerItem) #What is this? self.label = QLabel() self.label.setMaximumSize(QSize(200, 130)) self.label.setText("") self.verticalLayout.addWidget(self.label) self.horizontalLayout.addLayout(self.verticalLayout) self.rightVerticalLayout = QVBoxLayout() self.graphWidgetOutput = PlotWidget() self.graphWidgetInput = PlotWidget() #Adds grid lines self.graphWidgetOutput.showGrid(x=True, y=True, alpha=None) self.graphWidgetInput.showGrid(x=True, y=True, alpha=None) #self.graphWidget.setXRange(0, 100, padding=0) #Doesn't move with the plot. Can drag around #self.graphWidget.setLimits(xMin=0, xMax=100)#, yMin=c, yMax=d) #Doesn't move with the plot. Cannot drag around #self.graphWidget.setYRange(0, 4, padding=0) self.graphWidgetOutput.setYRange(-11, 11, padding=0) self.graphWidgetOutput.enableAutoRange() self.graphWidgetInput.setYRange(-11, 11, padding=0) self.graphWidgetInput.enableAutoRange() #Changes background color of graph self.graphWidgetOutput.setBackground((0, 0, 0)) self.graphWidgetInput.setBackground((0, 0, 0)) #Adds a legend after data starts to plot NOT before self.graphWidgetOutput.addLegend() #Adds title to graphs self.graphWidgetOutput.setTitle("Response", color="w", size="12pt") self.graphWidgetInput.setTitle("PWM Actuation Signal", color="w", size="12pt") self.rightVerticalLayout.addWidget(self.graphWidgetOutput) self.rightVerticalLayout.addWidget(self.graphWidgetInput) self.horizontalLayout.addLayout(self.rightVerticalLayout) self.setLayout(self.horizontalLayout) #Plot time update settings self.timer = QTimer() self.timer.setInterval( 50 ) #Changes the plot speed. Defaulted to 50. Can be placed in startbutton_pushed() method self.initialState() time.sleep(2) try: self.timer.timeout.connect(self.update) except: raise Exception("Not Connected") #self.show() #Checkbox logic def checkbox_logic(self, state): # checking if state is checked if state == Qt.Checked: if self.sender() == self.checkBoxShowAll: self.checkBoxHideAll.setChecked(False) self.checkBoxPlot1.setChecked(False) self.checkBoxPlot2.setChecked(False) #self.checkBoxShow.stateChanged.disconnect(self.uncheck) elif self.sender() == self.checkBoxHideAll: #self.checkBoxShow.stateChanged.connect(self.uncheck) self.checkBoxShowAll.setChecked(False) self.checkBoxPlot1.setChecked(False) self.checkBoxPlot2.setChecked(False) elif self.sender() == self.checkBoxPlot1: self.checkBoxShowAll.setChecked(False) self.checkBoxHideAll.setChecked(False) self.checkBoxPlot2.setChecked(False) elif self.sender() == self.checkBoxPlot2: self.checkBoxShowAll.setChecked(False) self.checkBoxHideAll.setChecked(False) self.checkBoxPlot1.setChecked(False) #Resets data arrays and establishes serial communcation. Disables itself after clicking def startbutton_pushed(self): self.initialState( ) #Reinitializes arrays in case you have to retake data self.size = self.serial_values[3] #Value from settings. Windows data #self.buffersize = self.serial_values[4] #Value from settings. Restricts buffer data ''' self.ser = serial.Serial(port = self.serial_values[0], baudrate = self.serial_values[1], timeout = self.serial_values[2]) self.ser.flushInput() self.ser.write(b'A') time.sleep(2) print("Recording Data") self.timer.start() #self.timer.setInterval(50) self.curve() self.startbutton.clicked.disconnect(self.startbutton_pushed) ''' self.serialInstance = SerialComm(self.serial_values[0], self.serial_values[1], self.serial_values[2]) self.serialInstance.serialOpen() time.sleep(2) print("Recording Data") self.timer.start() self.curve() self.startbutton.clicked.disconnect(self.startbutton_pushed) #Stops timer and ends serial communication def stopbutton_pushed(self): self.timer.stop() #self.ser.close() self.serialInstance.serialClose() ''' print("y1 zeros:", self.y1_zeros) print("y2 zeros:", self.y2_zeros) print("y1 full:", self.y1) print("y2 full:", self.y2) ''' #Resets both plotting windows and reenables Start Button def clearbutton_pushed(self): self.graphWidgetOutput.clear() self.graphWidgetInput.clear() self.graphWidgetOutput.enableAutoRange(axis=None, enable=True, x=None, y=None) self.startbutton.clicked.connect(self.startbutton_pushed) #Dumps data into a csv file to a selected path def savebutton_pushed(self): self.createCSV() path = QFileDialog.getSaveFileName(self, 'Save CSV', os.getenv('HOME'), 'CSV(*.csv)') if path[0] != '': with open(path[0], 'w', newline='') as csvfile: csvwriter = csv.writer(csvfile) csvwriter.writerow(self.header) csvwriter.writerows(self.data_set) #Creates csv data def createCSV(self): self.header = ['time', 'y1', 'y2'] self.data_set = zip(self.time, self.y1, self.y2) #Initilizes lists/arrays def initialState(self): self.buffersize = 500 #np array size that is used to plot data self.step = 0 #Used for repositioning data in plot window to the left #Data buffers. What is being plotted in the 2 windows self.time_zeros = np.zeros(self.buffersize + 1, float) self.y1_zeros = np.zeros(self.buffersize + 1, float) self.y2_zeros = np.zeros(self.buffersize + 1, float) self.y3_zeros = np.zeros(self.buffersize + 1, float) #Complete data. What will be written to the csv file self.time = list() self.y1 = list() self.y2 = list() self.y3 = list() self.getLabType() ''' def readValues(self): arduinoData = self.ser.readline().decode().replace('\r\n','').split(",") return arduinoData ''' #Initializes data# to have specific attributes def curve(self): pen1 = pg.mkPen(color=(255, 0, 0), width=1) pen2 = pg.mkPen(color=(0, 255, 0), width=1) pen3 = pg.mkPen(color=(0, 0, 255), width=1) self.data1 = self.graphWidgetOutput.plot(pen=pen1, name="Data 1") #Response self.data2 = self.graphWidgetOutput.plot(pen=pen2, name="Data 2") #Setpoint self.data3 = self.graphWidgetInput.plot( pen=pen3, name="Data 3") #PWM Actuation Signal #Connected to timer to update plot. Incoming data is in the form of timestamp,data1,data2... def update(self): #fulldata = self.readValues() #print(fulldata) fulldata = self.serialInstance.readValues() self.step = self.step + 1 time_index = int(self.time_zeros[self.buffersize]) self.time_zeros[time_index] = self.time_zeros[time_index + self.size] = float( fulldata[0]) self.time_zeros[self.buffersize] = time_index = (time_index + 1) % self.size self.time.append(fulldata[0]) i = int(self.y1_zeros[self.buffersize]) self.y1_zeros[i] = self.y1_zeros[i + self.size] = float(fulldata[1]) self.y1_zeros[self.buffersize] = i = (i + 1) % self.size self.y1.append(fulldata[1]) j = int(self.y2_zeros[self.buffersize]) self.y2_zeros[j] = self.y2_zeros[j + self.size] = float(fulldata[2]) self.y2_zeros[self.buffersize] = j = (j + 1) % self.size self.y2.append(fulldata[2]) k = int(self.y3_zeros[self.buffersize]) self.y3_zeros[k] = self.y3_zeros[k + self.size] = float(fulldata[3]) self.y3_zeros[self.buffersize] = k = (k + 1) % self.size self.y3.append(fulldata[3]) self.data1.setData(self.time_zeros[time_index:time_index + self.size], self.y1_zeros[i:i + self.size]) self.data1.setPos(self.step, 0) self.data2.setData(self.time_zeros[time_index:time_index + self.size], self.y2_zeros[j:j + self.size]) self.data2.setPos(self.step, 0) self.data3.setData(self.time_zeros[time_index:time_index + self.size], self.y3_zeros[k:k + self.size]) self.data3.setPos(self.step, 0) #Below 4 change visibility of data# in the curves() method def visibilityAll(self): showall = self.sender() if showall.isChecked() == True: self.data1.setVisible(True) self.data2.setVisible(True) def hideAll(self): disappearall = self.sender() if disappearall.isChecked() == True: self.data1.setVisible(False) self.data2.setVisible(False) def visibility1(self): test1 = self.sender() if test1.isChecked() == True: self.data1.setVisible(True) self.data2.setVisible(False) def visibility2(self): test2 = self.sender() if test2.isChecked() == True: self.data2.setVisible(True) self.data1.setVisible(False) #Class instance of settings menu. Creates a dialog (popup) def settingsMenu(self): self.settingsPopUp = Dialog1() self.settingsPopUp.show() #self.settingsPopUp.exec() self.serial_values = self.settingsPopUp.getDialogValues() def PCheckBoxLogic(self): test1 = self.sender() if test1.isChecked() == True: self.PInput.setEnabled(True) elif test1.isChecked() == False: self.PInput.setEnabled(False) def ICheckBoxLogic(self): test1 = self.sender() if test1.isChecked() == True: self.IInput.setEnabled(True) elif test1.isChecked() == False: self.IInput.setEnabled(False) def DCheckBoxLogic(self): test1 = self.sender() if test1.isChecked() == True: self.DInput.setEnabled(True) elif test1.isChecked() == False: self.DInput.setEnabled(False) def PIDInput(self): if self.PInput.text() == "" or self.PCheckBox.checkState() == False: self.Pvalue = 0 else: self.Pvalue = self.PInput.text() if self.IInput.text() == "" or self.ICheckBox.checkState() == False: self.Ivalue = 0 else: self.Ivalue = self.IInput.text() if self.DInput.text() == "" or self.DCheckBox.checkState() == False: self.Dvalue = 0 else: self.Dvalue = self.DInput.text() return ([self.Pvalue, self.Ivalue, self.Dvalue]) #Function that connects output pyqtgraph widget, and the combobox def getInput(self): self.inputType = str(self.inputForms.currentText()) pen_input = pg.mkPen(color=(255, 0, 0), width=1) if self.inputType == "Sine": print("Sine") self.graphWidgetInput.clear() self.x_input = np.arange(0, 10, 0.1) self.y_input = np.sin(self.x_input) self.data_input = self.graphWidgetInput.plot(self.x_input, self.y_input, pen=pen_input) self.data_input.setData(self.x_input, self.y_input) self.graphWidgetInput.setYRange(-2, 2, padding=0) elif self.inputType == "Step": print("Step") self.graphWidgetInput.clear() self.x_input = np.arange(0, 10, 0.1) self.y_input = np.heaviside(self.x_input, 1) self.data_input = self.graphWidgetInput.plot(self.x_input, self.y_input, pen=pen_input) self.data_input.setData(self.x_input, self.y_input) self.graphWidgetInput.setYRange(-2, 2, padding=0) def getLabType(self): self.inputType = str(self.LabType.currentText()) if self.inputType == "Position": print("Lab: Position") return ( self.graphWidgetOutput.setLabel( 'left', "<span style=\"color:white;font-size:16px\">θ (°)</span>" ), self.graphWidgetInput.setLabel( 'left', "<span style=\"color:white;font-size:16px\">Voltage</span>" ), self.graphWidgetOutput.setLabel( 'bottom', "<span style=\"color:white;font-size:16px\">Time (s)</span>" ), self.graphWidgetInput.setLabel( 'bottom', "<span style=\"color:white;font-size:16px\">Time (s)</span>" )) elif self.inputType == "Speed": print("Lab: Speed") return ( self.graphWidgetOutput.setLabel( 'left', "<span style=\"color:white;font-size:16px\">ω (°/s)</span>" ), self.graphWidgetInput.setLabel( 'left', "<span style=\"color:white;font-size:16px\">Voltage</span>" ), self.graphWidgetOutput.setLabel( 'bottom', "<span style=\"color:white;font-size:16px\">Time (s)</span>" ), self.graphWidgetInput.setLabel( 'bottom', "<span style=\"color:white;font-size:16px\">Time (s)</span>" ), )
class RealtimePlotWidget(QWidget): AUTO_RANGE_FRACTION = 0.99 COLORS = [Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray] def __init__(self, display_measurements, parent): super(RealtimePlotWidget, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._legend = self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.showGrid(x=True, y=True, alpha=0.3) vbox = QVBoxLayout(self) vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._last_update_ts = 0 self._reset_required = False self._update_timer = QTimer(self) self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._update) self._update_timer.start(200) self._color_index = 0 self._curves = {} # Crosshair def _render_measurements(cur, ref): text = 'time %.6f sec, y %.6f' % cur if ref is None: return text dt = cur[0] - ref[0] dy = cur[1] - ref[1] if abs(dt) > 1e-12: freq = '%.6f' % abs(1 / dt) else: freq = 'inf' display_measurements(text + ';' + ' ' * 4 + 'dt %.6f sec, freq %s Hz, dy %.6f' % (dt, freq, dy)) display_measurements('Hover to sample Time/Y, click to set new reference') add_crosshair(self._plot_widget, _render_measurements) # Final reset self.reset() def _trigger_auto_reset_if_needed(self): ts = time.monotonic() dt = ts - self._last_update_ts self._last_update_ts = ts if dt > 2: self._reset_required = True def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'data': (data_x, data_y), 'plot': plot} self._trigger_auto_reset_if_needed() def update_values(self, curve_id, x, y): curve = self._curves[curve_id] old_x, old_y = curve['data'] curve['data'] = numpy.append(old_x, x), numpy.append(old_y, y) self._trigger_auto_reset_if_needed() def reset(self): for curve in self._curves.keys(): self._plot_widget.removeItem(self._curves[curve]['plot']) self._curves = {} self._color_index = 0 self._plot_widget.enableAutoRange(enable=self.AUTO_RANGE_FRACTION, x=self.AUTO_RANGE_FRACTION, y=self.AUTO_RANGE_FRACTION) self._legend.scene().removeItem(self._legend) self._legend = self._plot_widget.addLegend() def _update(self): if self._reset_required: self.reset() self._reset_required = False for curve in self._curves.values(): if len(curve['data'][0]): curve['plot'].setData(*curve['data'])