class Plotter(QtGui.QWidget): update_plot_xy_signal = pyqtSignal(object, object) def __init__(self, title='PLOTTER', x_label='X', y_label='Y'): QtGui.QWidget.__init__(self) self.gridLayout = QtGui.QGridLayout(self) self.setWindowTitle(title) #graph graphSetOptions(antialias=True) self.graph = PlotWidget() self.graph.setTitle(title) self.graph.setLabel('left', y_label) self.graph.setLabel('bottom', x_label) self.graph.showGrid(x=True, y=True) self.graph.setBackground((235, 236, 237)) self.pen = mkPen(color=(46, 142, 226), width=3, style=QtCore.Qt.DashLine) self.gridLayout.addWidget(self.graph, 0, 1, 10, 10) self.update_plot_xy_signal.connect(self.update_graph_with_value) self.x_vect = [] self.y_vect = [] self.__x_range_was_set = False def set_max_x(self, value): self.graph.setXRange(0, value) self.__x_range_was_set = True def get_max(self): max_y = max(self.y_vect) x = self.x_vect[self.y_vect.index(max_y)] return x, max_y def get_min(self): min_y = min(self.y_vect) x = self.x_vect[self.y_vect.index(min_y)] return x, min_y def update_graph_with_value(self, x, y): self.x_vect.append(x) self.y_vect.append(y) y_max = 0 y_min = 0 x_max = 0 for x_val in self.x_vect: y_val = self.y_vect[self.x_vect.index(x_val)] if y_val > y_max: y_max = y_val if y_val < y_min: y_min = y_val if x_val > x_max: x_max = x_val self.graph.clear() self.graph.setYRange(y_min - float(y_min) / 10, y_max + float(y_max) / 10) if self.__x_range_was_set is False: self.graph.setXRange(0, x_max + float(x_max) / 10) self.graph.plot(self.x_vect, self.y_vect, symbol='o', pen=self.pen)
class SensirionSBPlot(QWidget): def __init__(self, plot_title, color, bufferSize): super().__init__() masterLayout = QVBoxLayout() self.pen = mkPen(color, width=1.25) layout = QVBoxLayout() self.group = QGroupBox(plot_title) self.plot = PlotWidget() self.plot.getPlotItem().showGrid(x=True, y=True, alpha=1) if "qdarkstyle" in sys.modules: self.plot.setBackground((25, 35, 45)) self.buffer = RingBuffer(capacity=bufferSize, dtype=float) self.group.setLayout(layout) layout.addWidget(self.plot) masterLayout.addWidget(self.group) self.setLayout(masterLayout) def change_capacity(self, value): if value > len(self.buffer): newBuf = RingBuffer(capacity=value, dtype=float) newBuf.extend(self.buffer) self.buffer = newBuf elif value < len(self.buffer): newBuf = RingBuffer(capacity=value, dtype=float) newBuf.extend(self.buffer[:-value]) self.buffer = newBuf def update_plot(self, sample): self.plot.clear() self.buffer.append(sample) self.plot.plot(self.buffer, pen=self.pen, symbolPen=self.pen, symbol='o', symbolSize=5, name="symbol ='o'")
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(497, 463) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.graphicsView = PlotWidget(self.centralwidget) self.graphicsView.setGeometry(QtCore.QRect(10, 10, 471, 361)) self.graphicsView.setObjectName("graphicsView") self.splitter = QtWidgets.QSplitter(self.centralwidget) self.splitter.setGeometry(QtCore.QRect(10, 380, 471, 41)) self.splitter.setOrientation(QtCore.Qt.Horizontal) self.splitter.setObjectName("splitter") self.pushButton = QtWidgets.QPushButton(self.splitter) font = QtGui.QFont() font.setPointSize(14) font.setBold(True) font.setWeight(75) self.pushButton.setFont(font) self.pushButton.setObjectName("pushButton") self.pushButton_2 = QtWidgets.QPushButton(self.splitter) font = QtGui.QFont() font.setPointSize(14) font.setBold(True) font.setWeight(75) self.pushButton_2.setFont(font) self.pushButton_2.setObjectName("pushButton_2") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 497, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.pushButton.clicked.connect(lambda: self.draw()) self.pushButton_2.clicked.connect(lambda: self.clear()) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "Draw")) self.pushButton_2.setText(_translate("MainWindow", "Clear")) def draw(self): x = np.random.normal(size=1000) y = np.random.normal(size=(3, 1000)) self.graphicsView.clear() for i in range(3): self.graphicsView.plot(x, y[i], pen=(i, 3)) def clear(self): self.graphicsView.clear()
def clear_graphics(graphics_view: PlotWidget): """ static method for clearing content in all graphics Parameters ---------- graphics_view : PlotWidget graphics view to place chart """ Assertor.assert_data_types([graphics_view], [PlotWidget]) graphics_view.clear()
class LookupTableWithGraph(QtGui.QWidget): def __init__(self, name='LOOKPUP TABLE', init_table={}): QtGui.QWidget.__init__(self) self.gridLayout = QtGui.QGridLayout(self) self.name = name #table self.table = LookupTable(init_table) #self.table.add_row() self.table.values_updated_signal.connect(self.values_updated_slot) #graph graphSetOptions(antialias=True) self.graph = PlotWidget() self.graph.setTitle(self.name) self.graph.setLabel('left', 'OUTPUT') self.graph.setLabel('bottom', 'INPUT') self.graph.showGrid(x=True, y=True) self.graph.setBackground((235, 236, 237)) self.pen = mkPen(color=(46, 142, 226), width=3, style=QtCore.Qt.DashLine) self.gridLayout.addWidget(self.table, 0, 0) self.gridLayout.addWidget(self.graph, 0, 1) self.values_updated_slot() def values_updated_slot(self): x_vect = [] y_vect = [] y_max = 0 y_min = 0 x_max = 0 for x_val in self.table.lookup_table: y_val = self.table.lookup_table[x_val] x_vect.append(x_val) y_vect.append(y_val) if y_val > y_max: y_max = y_val if y_val < y_min: y_min = y_val if x_val > x_max: x_max = x_val self.graph.clear() self.graph.setYRange(y_min - float(y_min) / 10, y_max + float(y_max) / 10) self.graph.setXRange(0, x_max + float(x_max) / 10) self.graph.plot(x_vect, y_vect, symbol='o', pen=self.pen) def get_table(self): return self.table.get_table()
def clear_graphics(graphics_view: PlotWidget, table_view: QTableView): """ static method for clearing content in all graphics Parameters ---------- graphics_view : PlotWidget graphics view to place chart table_view : QTableView table view to link graphics_view """ Assertor.assert_data_types([graphics_view, table_view], [PlotWidget, QTableView]) table_view.setModel(None) table_view.clearSpans() graphics_view.clear()
class LoggerWindow(QMainWindow): @staticmethod def gen(max, val=0): while val <= max: val += 1 if val == max: val = 0 yield val def __init__( self, title="", update_time=300, *args, **kwargs, ): super(LoggerWindow, self).__init__(*args, **kwargs) self.graphWidget = PlotWidget() self.setCentralWidget(self.graphWidget) self.setWindowTitle(title) max_x = 10000 self.log = [ deque([0] * max_x, maxlen=max_x), deque([0] * max_x, maxlen=max_x) ] t0 = 0 period = 1 rng = range(0, max_x) rng = map(lambda x: t0 + x * period * 0.001, rng) # self.log[0].extend(range(0, max_x)) self.log[0].extend(rng) self.gnr = self.gen(len(self.log[0])) self.timer = QTimer() self.timer.timeout.connect(self.updater) self.timer.start(update_time) def updater(self): if self.isHidden(): return self.graphWidget.clear() self.graphWidget.plot(self.log[0], self.log[1]) def logValue(self, value): cnt = next(self.gnr) self.log[1][cnt] = value
class GraphUi(QWidget): uiUpdateDelegate = pyqtSignal() def __init__(self): super().__init__() self.resize(600, 600) self.uiUpdateDelegate.connect(self.uiUpdater) pg.setConfigOption('background', 'w') self.Graph = PlotWidget(self) self.Graph.setGeometry(QRect(0, 0, 600, 500)) self.Graph.setFrameShape(QFrame.NoFrame) self.Graph.setObjectName("Graph") self.Graph.showGrid(x=True, y=True) def uiUpdater(self): self.Graph.clear() self.Graph.plot(temperature, pen=pg.mkPen('r', width=2)) self.Graph.plot(humidity, pen=pg.mkPen('b', width=2))
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 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 Ui_Dialog(object): def __init__(self) : self.c = 1 self.dx = 0.1 self.n = 1 def setupUi(self, Dialog): Dialog.setObjectName("Equation de transport") Dialog.resize(996, 388) Dialog.setWindowIcon(QtGui.QIcon(r'D:\Cours\Aero2\GP\Transport\Numerix.jpg')) Dialog.setFixedSize(996,388) font = QtGui.QFont() font.setFamily("CMU Bright") font.setPointSize(10) Dialog.setFont(font) self.frame = QtWidgets.QFrame(Dialog) self.frame.setGeometry(QtCore.QRect(20, 10, 361, 81)) self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame.setFrameShadow(QtWidgets.QFrame.Raised) self.frame.setObjectName("frame") self.label = QtWidgets.QLabel(self.frame) self.label.setGeometry(QtCore.QRect(10, 10, 181, 16)) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.frame) self.label_2.setGeometry(QtCore.QRect(200, 10, 161, 16)) self.label_2.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) self.label_2.setMouseTracking(False) self.label_2.setObjectName("label_2") self.L = QtWidgets.QLineEdit(self.frame) self.L.setGeometry(QtCore.QRect(10, 40, 113, 22)) self.L.setObjectName("L") self.tmax = QtWidgets.QLineEdit(self.frame) self.tmax.setGeometry(QtCore.QRect(200, 40, 113, 22)) self.tmax.setObjectName("tmax") self.frame_2 = QtWidgets.QFrame(Dialog) self.frame_2.setGeometry(QtCore.QRect(20, 110, 361, 221)) font = QtGui.QFont() font.setFamily("CMU Serif") font.setPointSize(10) self.frame_2.setFont(font) self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_2.setObjectName("frame_2") self.label_3 = QtWidgets.QLabel(self.frame_2) self.label_3.setGeometry(QtCore.QRect(10, 10, 171, 16)) self.label_3.setObjectName("label_3") self.CI = QtWidgets.QComboBox(self.frame_2) self.CI.setGeometry(QtCore.QRect(10, 50, 91, 22)) font = QtGui.QFont() font.setFamily("CMU Serif") font.setPointSize(10) font.setBold(False) font.setItalic(False) font.setWeight(50) self.CI.setFont(font) self.CI.setStyleSheet("") self.CI.setObjectName("CI") self.CI.addItem("sin(x)") self.CI.addItem("exp(-x^2)") self.CI.addItem("0") self.label_4 = QtWidgets.QLabel(self.frame_2) self.label_4.setGeometry(QtCore.QRect(180, 10, 201, 16)) self.label_4.setObjectName("label_4") self.frame_3 = QtWidgets.QFrame(self.frame_2) self.frame_3.setGeometry(QtCore.QRect(170, 0, 191, 181)) self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_3.setObjectName("frame_3") self.label_5 = QtWidgets.QLabel(self.frame_3) self.label_5.setGeometry(QtCore.QRect(20, 40, 71, 16)) self.label_5.setObjectName("label_5") self.Cl_0 = QtWidgets.QComboBox(self.frame_3) self.Cl_0.setGeometry(QtCore.QRect(20, 70, 90, 22)) self.Cl_0.setObjectName("Cl_0") self.Cl_0.addItem("0") self.Cl_0.addItem("sin(t)") self.label_6 = QtWidgets.QLabel(self.frame_3) self.label_6.setGeometry(QtCore.QRect(20, 110, 71, 16)) self.label_6.setObjectName("label_6") self.Cl_L = QtWidgets.QComboBox(self.frame_3) self.Cl_L.setGeometry(QtCore.QRect(20, 140, 90, 22)) self.Cl_L.setObjectName("Cl_L") self.Cl_L.addItem("0") self.Cl_L.addItem("sin(t)") self.Cl_L.addItem("Aucune") self.label_7 = QtWidgets.QLabel(self.frame_2) self.label_7.setGeometry(QtCore.QRect(10, 100, 151, 16)) self.label_7.setObjectName("label_7") self.Vitesse = QtWidgets.QLineEdit(self.frame_2) self.Vitesse.setGeometry(QtCore.QRect(10, 140, 113, 22)) self.Vitesse.setObjectName("Vitesse") self.Animation = QtWidgets.QCheckBox(Dialog) self.Animation.setGeometry(QtCore.QRect(30, 340, 101, 20)) self.Animation.setObjectName("Animation") self.Plot_btn = QtWidgets.QPushButton(Dialog) self.Plot_btn.setGeometry(QtCore.QRect(220, 340, 93, 28)) self.Plot_btn.setObjectName("Plot_btn") self.Graph = PlotWidget(Dialog) self.Graph.setGeometry(QtCore.QRect(389, 9, 591, 361)) self.Graph.setObjectName("Graph") self.retranslateUi(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog) Dialog.setTabOrder(self.CI, self.Vitesse) Dialog.setTabOrder(self.Vitesse,self.Cl_0) Dialog.setTabOrder(self.Cl_0, self.Cl_L) Dialog.setTabOrder(self.Cl_L, self.Animation) Dialog.setTabOrder(self.Animation, self.Plot_btn) setConfigOptions(antialias=True) self.Plot_btn.clicked.connect(self.plotter) self.Graph.setBackground('w') self.Graph.setLabel('left','y(x,tmax)') self.Graph.setLabel('bottom','x') self.timer = QtCore.QTimer() self.timer.timeout.connect(self.animplotter) def retranslateUi(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_translate("Dialog", "Equation de transport")) self.label.setText(_translate("Dialog", "Longueur de l\'espace :")) self.label_2.setText(_translate("Dialog", "Temps maximum :")) self.label_3.setText(_translate("Dialog", "Conditions initiales :")) self.CI.setItemText(0, _translate("Dialog", "sin(x)")) self.CI.setItemText(1, _translate("Dialog", "exp(-x^2)")) self.CI.setItemText(2, _translate("Dialog", "0")) self.label_4.setText(_translate("Dialog", "Conditions aux limites :")) self.label_5.setText(_translate("Dialog", "En x = 0 :")) self.Cl_0.setItemText(0, _translate("Dialog", "0")) self.Cl_0.setItemText(1, _translate("Dialog", "sin(t)")) self.label_6.setText(_translate("Dialog", "En x = L :")) self.Cl_L.setItemText(0, _translate("Dialog", "0")) self.Cl_L.setItemText(1, _translate("Dialog", "sin(t)")) self.Animation.setText(_translate("Dialog", "Animation")) self.Plot_btn.setText(_translate("Dialog", "Plot !")) self.label_6.setText(_translate("Dialog", "En x = L :")) self.Cl_L.setItemText(0, _translate("Dialog", "0")) self.Cl_L.setItemText(1, _translate("Dialog", "sin(t)")) self.Cl_L.setItemText(2, _translate("Dialog", "Aucune")) self.Animation.setText(_translate("Dialog", "Animation")) self.Plot_btn.setText(_translate("Dialog", "Plot !")) self.label_7.setText(_translate("Dialog", "Vitesse de l\'onde :")) def solve(self) : self.C = self.c*self.dt/self.dx self.Fi = init = self.Finit() self.sol = [] self.solutions = [0 for t in self.T] for t in range(len(self.T)) : for x in range(len(self.Fi)) : self.sol.append( init[x] - self.C*(init[x] - init[x-1]) ) if self.Cl_0.currentText() == 'sin(t)' : self.sol[0] = np.sin(self.T[t]*self.c) elif self.Cl_0.currentText() == '0' : self.sol[0] = 0 if self.Cl_L.currentText() == 'sin(t)' : self.sol[-1] = np.sin(self.T[t]) elif self.Cl_L.currentText() == '0' : self.sol[-1] = 0 init = self.sol self.sol = [] self.solutions[t] = init self.sol = init return self.sol def plotter(self) : self.c = float(self.Vitesse.text()) self.tmaxv = float(self.tmax.text()) self.dt = self.dx/self.c self.Graph.clear() self.X = np.arange(0,float(self.L.text()),self.dx).tolist() self.T = np.arange(0,self.tmaxv,self.dt).tolist() Solution = self.solve() self.Graph.setXRange(0,float(self.L.text())) self.Graph.setYRange(min(Solution)-self.dx,1.1) self.timer.setInterval(self.tmaxv/len(self.T)*10**3) #self.timer.setInterval(50) if self.Animation.isChecked() : self.n = 1 self.my_line = self.Graph.plot(self.X,self.Finit(),name ='t=0', pen = mkPen(color = 'k') ) self.timer.start() else : self.Graph.plot(self.X,self.Finit(),name ='t=0', pen = mkPen(color = 'b') ) self.Graph.plot(self.X,Solution,name ='t=tmax', pen = mkPen(color = 'k') ) def Finit(self) : X = np.arange(0,float(self.L.text()),self.dx) if self.CI.currentText() == 'exp(-x^2)' : return np.exp(-(X-float(self.L.text())/2)**2) elif self.CI.currentText() == 'sin(x)' : return np.sin(X) elif self.CI.currentText() == '0' : return [0 for x in X] def animplotter(self) : try : self.my_line.setData(self.X,self.solutions[self.n]) self.n += 1 except : self.timer.stop()
class RTBSA(QMainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.help_menu = self.menuBar().addMenu("&Help") self.file_menu = self.menuBar().addMenu("&File") self.status_text = QLabel() self.plot = PlotWidget(alpha=0.75) self.ui = Ui_RTBSA() self.ui.setupUi(self) self.setWindowTitle('Real Time BSA') self.loadStyleSheet() self.setUpGraph() self.bsapvs = [ 'GDET:FEE1:241:ENRC', 'GDET:FEE1:242:ENRC', 'GDET:FEE1:361:ENRC', 'GDET:FEE1:362:ENRC' ] self.populateBSAPVs() self.connectGuiFunctions() # Initial number of points self.numPoints = 2800 # Initial number of standard deviations self.stdDevstoKeep = 3.0 # 20ms polling time self.updateTime = 50 # Set initial polynomial fit to 2 self.fitOrder = 2 self.disableInputs() self.abort = True # Used to update plot self.timer = QTimer(self) # self.ratePV = PV('IOC:IN20:EV01:RG01_ACTRATE') self.ratePV = PV("EVNT:SYS0:1:LCLSBEAMRATE") self.menuBar().setStyleSheet( 'QWidget{background-color:grey;color:purple}') self.create_menu() self.create_status_bar() # The PV names self.devices = {"A": "", "B": ""} self.pvObjects = {"A": None, "B": None} # The raw, unsynchronized, unfiltered buffers self.rawBuffers = {"A": empty(2800), "B": empty(2800)} # The times when each buffer finished its last data acquisition self.timeStamps = {"A": None, "B": None} self.synchronizedBuffers = {"A": empty(2800), "B": empty(2800)} # Versions of data buffers A and B that are filtered by standard # deviation. Didn't want to edit those buffers directly so that we could # unfilter or refilter with a different number more efficiently self.filteredBuffers = {"A": empty(2800), "B": empty(2800)} # Text objects that appear on the plot self.text = {"avg": None, "std": None, "slope": None, "corr": None} # All things plot related! self.plotAttributes = { "curve": None, "fit": None, "parab": None, "frequencies": None } # Used for the kill swtich self.counter = {"A": 0, "B": 0} # Used to implement scrolling for time plots self.currIdx = {"A": 0, "B": 0} def getRate(self): # return rtbsaUtils.rateDict[self.ratePV.value] return self.ratePV.value def disableInputs(self): self.ui.fitOrder.setDisabled(True) self.ui.searchInputA.setDisabled(True) self.ui.searchInputB.setDisabled(True) self.ui.labelFitOrder.setDisabled(True) self.ui.bsaListA.setDisabled(True) self.ui.bsaListB.setDisabled(True) self.statusBar().showMessage('Hi there! I missed you!') self.ui.checkBoxPolyFit.setChecked(False) def populateBSAPVs(self): # Generate list of BSA PVS try: BSAPVs = check_output( ['eget', '-ts', 'ds', '-a', 'tag=LCLS.BSA.rootnames']).splitlines()[1:-1] self.bsapvs.extend(BSAPVs) # Backup for eget error except CalledProcessError: print("Unable to pull most recent PV list") # bsaPVs is pulled from the Constants file self.bsapvs.extend(rtbsaUtils.bsaPVs) # TODO un-hardcode machine and add common SPEAR PV's except OSError: print "Other machines coming soon to an RTBSA near you!" pass for pv in self.bsapvs: self.ui.bsaListA.addItem(pv) self.ui.bsaListB.addItem(pv) def connectGuiFunctions(self): # enter 1 is the text input box for device A, and 2 is for B QObject.connect(self.ui.searchInputA, SIGNAL("textChanged(const QString&)"), self.searchA) QObject.connect(self.ui.searchInputB, SIGNAL("textChanged(const QString&)"), self.searchB) # Changes the text in the input box to match the selection from the list self.ui.bsaListA.itemClicked.connect(self.setEnterA) self.ui.bsaListB.itemClicked.connect(self.setEnterB) # Dropdown menu for device A (add common BSA PV's) self.ui.dropdownA.addItems(rtbsaUtils.commonlist) # Make bunch length default selection index = rtbsaUtils.commonlist.index("BLEN:LI24:886:BIMAX") self.ui.dropdownA.setCurrentIndex(index) self.ui.dropdownA.activated.connect(self.inputActivated) # Dropdown menu for device B self.ui.dropdownB.addItems(rtbsaUtils.commonlist) self.ui.dropdownB.activated.connect(self.inputActivated) # All the checkboxes in the Settings section self.ui.checkBoxAvsT.clicked.connect(self.AvsTClick) self.ui.checkBoxBvsA.clicked.connect(self.AvsBClick) self.ui.checkBoxFFT.clicked.connect(self.AFFTClick) self.ui.checkBoxShowAve.clicked.connect(self.avg_click) self.ui.checkBoxShowStdDev.clicked.connect(self.std_click) self.ui.checkBoxCorrCoeff.clicked.connect(self.corr_click) self.ui.checkBoxPolyFit.clicked.connect(self.parab_click) self.ui.checkBoxLinFit.clicked.connect(self.line_click) self.ui.checkBoxShowGrid.clicked.connect(self.showGrid) # All the buttons in the Controls section self.ui.startButton.clicked.connect(self.initializePlot) self.ui.stopButton.clicked.connect(self.stop) self.ui.lclsLogButton.clicked.connect(self.logbook) self.ui.mccLogButton.clicked.connect(self.MCCLog) # fitedit is the text input box for "Order" self.ui.fitOrder.returnPressed.connect(self.fitOrderActivated) # The radio buttons that enable the dropdown menus self.ui.dropdownButtonA.clicked.connect(self.common_1_click) self.ui.dropdownButtonB.clicked.connect(self.common_2_click) # The radio buttons that enable the search bars self.ui.searchButtonA.clicked.connect(self.enter_1_click) self.ui.searchButtonB.clicked.connect(self.enter_2_click) # Pressing enter in the text input boxes for points and std dev triggers # updating the plot self.ui.numPoints.returnPressed.connect(self.points_entered) self.ui.numStdDevs.returnPressed.connect(self.stdDevEntered) # Triggers a redrawing upon pressing enter in the search bar. # Proper usage should be using the search bar to search, and selecting # from the results in the list. If it's not in the list, it's an invalid # PV with no reason to attempt plotting self.ui.searchInputA.returnPressed.connect(self.inputActivated) self.ui.searchInputB.returnPressed.connect(self.inputActivated) def showGrid(self): self.plot.showGrid(self.ui.checkBoxShowGrid.isChecked(), self.ui.checkBoxShowGrid.isChecked()) def setUpGraph(self): layout = QGridLayout() self.ui.widgetPlot.setLayout(layout) layout.addWidget(self.plot, 0, 0) self.plot.showGrid(1, 1) def loadStyleSheet(self): currDir = path.abspath(path.dirname(__file__)) cssFile = path.join(currDir, "style.css") try: with open(cssFile, "r") as f: self.setStyleSheet(f.read()) except IOError: print("Error loading style sheet") pass def create_status_bar(self): palette = QPalette() palette.setColor(palette.Foreground, Qt.magenta) self.statusBar().addWidget(self.status_text, 1) self.statusBar().setPalette(palette) # Effectively an autocomplete def search(self, enter, widget): widget.clear() query = str(enter.text()) for pv in self.bsapvs: if query.lower() in pv.lower(): widget.addItem(pv) def searchA(self): self.search(self.ui.searchInputA, self.ui.bsaListA) def searchB(self): self.search(self.ui.searchInputB, self.ui.bsaListB) def setEnter(self, widget, enter, search, enter_rb): selection = widget.currentItem() enter.textChanged.disconnect() enter.setText(selection.text()) QObject.connect(enter, SIGNAL("textChanged(const QString&)"), search) if not self.abort and enter_rb.isChecked(): self.stop() self.timer.singleShot(250, self.initializePlot) def setEnterA(self): self.setEnter(self.ui.bsaListA, self.ui.searchInputA, self.searchA, self.ui.searchButtonA) def setEnterB(self): self.setEnter(self.ui.bsaListB, self.ui.searchInputB, self.searchB, self.ui.searchButtonB) def correctInput(self, errorMessage, acceptableTxt, textBox): self.statusBar().showMessage(errorMessage, 6000) textBox.setText(acceptableTxt) def correctNumpoints(self, errorMessage, acceptableValue): self.correctInput(errorMessage, str(acceptableValue), self.ui.numPoints) self.numPoints = acceptableValue def correctStdDevs(self, errorMessage, acceptableValue): self.correctInput(errorMessage, str(acceptableValue), self.ui.numStdDevs) self.stdDevstoKeep = acceptableValue def stdDevEntered(self): try: self.stdDevstoKeep = float(self.ui.numStdDevs.text()) if self.stdDevstoKeep <= 0: raise ValueError except ValueError: self.correctStdDevs('Enter a float > 0', 3.0) return def points_entered(self): try: self.numPoints = int(self.ui.numPoints.text()) except ValueError: self.correctNumpoints('Enter an integer, 1 to 2800', 120) return if self.numPoints > 2800: self.correctNumpoints('Max # points is 2800', 2800) return if self.numPoints < 1: self.correctNumpoints('Min # points is 1', 1) return self.reinitialize_plot() ############################################################################ # Where the magic happens (well, where it starts to happen). This # initializes the BSA plotting and then starts a timer to update the plot. ############################################################################ def initializePlot(self): plotTypeIsValid = (self.ui.checkBoxAvsT.isChecked() or self.ui.checkBoxBvsA.isChecked() or self.ui.checkBoxFFT.isChecked()) if not plotTypeIsValid: self.statusBar().showMessage( 'Pick a Plot Type (PV vs. time ' 'or B vs A)', 10000) return self.ui.startButton.setDisabled(True) self.abort = False self.cleanPlot() self.pvObjects["A"], self.pvObjects["B"] = None, None # Plot history buffer for one PV if self.ui.checkBoxAvsT.isChecked(): if self.populateDevices(self.ui.dropdownButtonA, self.ui.dropdownA, self.ui.searchButtonA, self.ui.searchInputA, "A"): self.genPlotAndSetTimer(self.genTimePlotA, self.updateTimePlotA) # Plot for 2 PVs elif self.ui.checkBoxBvsA.isChecked(): if self.updateValsFromInput(): self.genPlotAndSetTimer(self.genPlotAB, self.updatePlotAB) # Plot power spectrum else: if self.populateDevices(self.ui.dropdownButtonA, self.ui.dropdownA, self.ui.searchButtonA, self.ui.searchInputA, "A"): self.genPlotAndSetTimer(self.InitializeFFTPlot, self.updatePlotFFT) def populateDevices(self, common_rb, common, enter_rb, enter, device): if common_rb.isChecked(): self.devices[device] = str(common.currentText()) elif enter_rb.isChecked(): pv = str(enter.text()).strip() # Checks that it's non empty and that it's a BSA pv if pv and pv in self.bsapvs: self.devices[device] = pv else: self.printStatus('Device ' + device + ' invalid. Aborting.') self.ui.startButton.setEnabled(True) return False return True def printStatus(self, message, printToXterm=True): if printToXterm: print message self.statusBar().showMessage(message) def updateValsFromInput(self): if not self.populateDevices(self.ui.dropdownButtonA, self.ui.dropdownA, self.ui.searchButtonA, self.ui.searchInputA, "A"): return False if not self.populateDevices(self.ui.dropdownButtonB, self.ui.dropdownB, self.ui.searchButtonB, self.ui.searchInputB, "B"): return False self.printStatus("Initializing/Synchronizing " + self.devices["A"] + " vs. " + self.devices["B"] + " buffers...") self.initializeBuffers() return True def initializeBuffers(self): # Initial population of our buffers using the HSTBR PV's in our # callback functions self.clearAndUpdateCallbacks("HSTBR", resetTime=True) while ((not self.timeStamps["A"] or not self.timeStamps["B"]) and not self.abort): QApplication.processEvents() self.adjustSynchronizedBuffers(True) # Switch to BR PVs to avoid pulling an entire history buffer on every # update. self.clearAndUpdateCallbacks("BR", resetRawBuffer=True) def clearAndUpdateCallbacks(self, suffix, resetTime=False, resetRawBuffer=False): self.clearAndUpdateCallback("A", suffix, self.callbackA, self.devices["A"], resetTime, resetRawBuffer) self.clearAndUpdateCallback("B", suffix, self.callbackB, self.devices["B"], resetTime, resetRawBuffer) # noinspection PyTypeChecker def clearAndUpdateCallback(self, device, suffix, callback, pvName, resetTime=False, resetRawBuffer=False): self.clearPV(device) # Without the time parameter, we wouldn't get the timestamp self.pvObjects[device] = PV(pvName + suffix, form='time') if resetTime: self.timeStamps[device] = None # Make sure that the initial raw buffer is synchronized and pad with # nans if it's less than 2800 points long if resetRawBuffer: nanArray = empty(2800 - self.synchronizedBuffers[device].size) nanArray[:] = nan self.rawBuffers[device] = \ concatenate([self.synchronizedBuffers[device], nanArray]) self.pvObjects[device].add_callback(callback) # Callback function for Device A # noinspection PyUnusedLocal def callbackA(self, pvname=None, value=None, timestamp=None, **kw): self.updateTimeAndBuffer("A", pvname, timestamp, value) # Callback function for Device B # noinspection PyUnusedLocal def callbackB(self, pvname=None, value=None, timestamp=None, **kw): self.updateTimeAndBuffer("B", pvname, timestamp, value) ############################################################################ # This is where the data is actually acquired and saved to the buffers. # Callbacks are effectively listeners that listen for change, so we # basically put a callback on the PVs of interest (devices A and/or B) so # that every time the value of that PV changes, we get that new value and # append it to our raw data buffer for that device. # Initialization of the buffer is slightly different in that the listener is # put on the history buffer of that PV (denoted by the HSTBR suffix), so # that we just immediately write the previous 2800 points to our raw buffer ############################################################################ def updateTimeAndBuffer(self, device, pvname, timestamp, value): def padRawBufferWithNans(start, end): rtbsaUtils.padWithNans(self.rawBuffers[device], start, end) if "HSTBR" in pvname: self.timeStamps[device] = timestamp # value is the buffer because we're monitoring the HSTBR PV self.rawBuffers[device] = value # Reset the counter every time we reinitialize the plot self.counter[device] = 0 else: if not self.timeStamps[device]: return rate = self.getRate() if rate < 1: return scalingFactor = 1.0 / rate elapsedPulses = round( (timestamp - self.timeStamps[device]) / scalingFactor) currIdx = int((timestamp / scalingFactor) % self.numPoints) if elapsedPulses <= 0: return # Pad the buffer with nans for missed pulses elif elapsedPulses > 1: # noinspection PyTypeChecker lastIdx = int( (self.timeStamps[device] / scalingFactor) % self.numPoints) # Take care of wrap around if currIdx < lastIdx: padRawBufferWithNans(lastIdx + 1, self.numPoints) padRawBufferWithNans(0, currIdx) else: padRawBufferWithNans(lastIdx + 1, currIdx) # Directly index into the raw buffer using the timestamp self.rawBuffers[device][currIdx] = value self.counter[device] += elapsedPulses self.timeStamps[device] = timestamp self.currIdx[device] = currIdx def clearPV(self, device): pv = self.pvObjects[device] if pv: pv.clear_callbacks() pv.disconnect() def adjustSynchronizedBuffers(self, syncByTime=False): numBadShots = self.populateSynchronizedBuffers(syncByTime) blength = 2800 - numBadShots # Make sure the buffer size doesn't exceed the desired number of points if self.numPoints < blength: self.synchronizedBuffers["A"] = \ self.synchronizedBuffers["A"][:self.numPoints] self.synchronizedBuffers["B"] = \ self.synchronizedBuffers["B"][:self.numPoints] # A spin loop that waits until the beam rate is at least 1Hz def waitForRate(self): start_time = time() gotStuckAndNeedToUpdateMessage = False # self.rate is a PV, such that .value is shorthand for .getval while self.ratePV.value < 1: # while self.ratePV.value < 2: # # noinspection PyArgumentList QApplication.processEvents() # if time() - start_time > 0.5: gotStuckAndNeedToUpdateMessage = True self.printStatus("Waiting for beam rate to be at least 1Hz...", False) if gotStuckAndNeedToUpdateMessage: self.printStatus("Running", False) # return rtbsaUtils.rateDict[self.ratePV.value] return self.ratePV.value ############################################################################ # Time 1 is when Device A started acquiring data, and Time 2 is when Device # B started acquiring data. Since they're not guaranteed to start # acquisition at the same time, one data buffer might be ahead of the other, # meaning that the intersection of the two buffers would not include the # first n elements of one and the last n elements of the other. See the # diagram below, where the dotted line represents the time axis (one buffer # is contained by square brackets [], the other by curly braces {}, and the # times where each starts and ends is indicated right underneath). # # # [ { ] } # <----------------------------------------------------------------------> t # t1_start t2_start t1_end t2_end # # # Note that both buffers are of the same size (2800) so that: # (t1_end - t1_start) = (t2_end - t2_start) # # From the diagram, we see that only the time between t2_start and t1_end # contains data from both buffers (t1_start to t2_start only contains data # from buffer 1, and t1_end to t2_end only contains data from buffer 2). # Using that, we can chop the beginning of buffer 1 and the end of buffer 2 # so that we're only left with the overlapping region. # # In order to figure out how many points we need to chop from each buffer # (it's the same number for both since they're both the same size), we # multiply the time delta by the beam rate (yay dimensional analysis!): # seconds * (shots/second) = (number of shots) # # That whole rigmarole only applies to the initial population of the buffers # (where we're pulling the entire history buffer at once using the HSTBR # suffix). From then on, we're indexing into the raw buffers using the # pulse ID modulo 2800, so they're inherently synchronized ############################################################################ def populateSynchronizedBuffers(self, syncByTime): def padSyncBufferWithNans(device, startIdx, endIdx): lag = endIdx - startIdx if lag > 20: print("Reinitializing buffers due to " + str(lag) + " shot lag for device " + device) self.initializeBuffers() else: rtbsaUtils.padWithNans(self.synchronizedBuffers[device], startIdx + 1, endIdx + 1) def checkIndices(device, startIdx, endIdx): # Check for index wraparound if endIdx < startIdx: padSyncBufferWithNans(device, startIdx, self.numPoints - 1) padSyncBufferWithNans(device, 0, endIdx) else: padSyncBufferWithNans(device, startIdx, endIdx) if syncByTime: numBadShots = int( round((self.timeStamps["B"] - self.timeStamps["A"]) * self.getRate())) startA, endA = rtbsaUtils.getIndices(numBadShots, 1) startB, endB = rtbsaUtils.getIndices(numBadShots, -1) self.synchronizedBuffers["A"] = self.rawBuffers["A"][startA:endA] self.synchronizedBuffers["B"] = self.rawBuffers["B"][startB:endB] return abs(numBadShots) else: self.synchronizedBuffers["A"] = self.rawBuffers["A"] self.synchronizedBuffers["B"] = self.rawBuffers["B"] # The timestamps and indices get updated by the callbacks, so we # store the values at the time of buffer-copying timeStampA = self.timeStamps["A"] timeStampB = self.timeStamps["B"] currIdxA = self.currIdx["A"] currIdxB = self.currIdx["B"] diff = timeStampA - timeStampB if diff > 0: checkIndices("A", currIdxB, currIdxA) elif diff < 0: checkIndices("B", currIdxA, currIdxB) return 0 def genPlotAndSetTimer(self, genPlot, updateMethod): if self.abort: return try: genPlot() except UnboundLocalError: self.printStatus('No Data, Aborting Plotting Algorithm') return self.timer = QTimer(self) # Run updateMethod every updatetime milliseconds self.timer.singleShot(self.updateTime, updateMethod) self.printStatus('Running') # noinspection PyTypeChecker def genTimePlotA(self): newData = self.initializeData() if not newData.size: self.printStatus('Invalid PV? Unable to get data. Aborting.') self.ui.startButton.setEnabled(True) return data = newData[:self.numPoints] self.plotAttributes["curve"] = PlotCurveItem(data, pen=1) self.plot.addItem(self.plotAttributes["curve"]) self.plotFit(arange(self.numPoints), data, self.devices["A"]) ############################################################################ # This is the main plotting function for "Plot A vs Time" that gets called # every self.updateTime seconds # noinspection PyTypeChecker ############################################################################ def updateTimePlotA(self): if not self.checkPlotStatus(): return xData, yData = self.filterTimePlotBuffer() if yData.size: self.plotAttributes["curve"].setData(yData) if self.ui.checkBoxAutoscale.isChecked(): mx = max(yData) mn = min(yData) if mx - mn > .00001: self.plot.setYRange(mn, mx) self.plot.setXRange(0, len(yData)) if self.ui.checkBoxShowAve.isChecked(): rtbsaUtils.setPosAndText(self.text["avg"], mean(yData), 0, min(yData), 'AVG: ') if self.ui.checkBoxShowStdDev.isChecked(): rtbsaUtils.setPosAndText(self.text["std"], std(yData), self.numPoints / 4, min(yData), 'STD: ') if self.ui.checkBoxCorrCoeff.isChecked(): self.text["corr"].setText('') if self.ui.checkBoxLinFit.isChecked(): self.text["slope"].setPos(self.numPoints / 2, min(yData)) self.getLinearFit(xData, yData, True) elif self.ui.checkBoxPolyFit.isChecked(): self.text["slope"].setPos(self.numPoints / 2, min(yData)) self.getPolynomialFit(xData, yData, True) self.timer.singleShot(self.updateTime, self.updateTimePlotA) def checkPlotStatus(self): QApplication.processEvents() if self.abort: return False self.waitForRate() # kill switch to stop backgrounded, forgetten GUIs. Somewhere in the # ballpark of 20 minutes assuming 120Hz if self.counter["A"] > 150000: self.stop() self.printStatus("Stopping due to inactivity") return True def filterTimePlotBuffer(self): currIdx = self.currIdx["A"] choppedBuffer = self.rawBuffers["A"][:self.numPoints] # All this nonsense to make it scroll :P Thanks to Ben for the # inspiration! if currIdx > 0: choppedBuffer = concatenate( [choppedBuffer[currIdx:], choppedBuffer[:currIdx]]) xData, yData = rtbsaUtils.filterBuffers(choppedBuffer, lambda x: ~isnan(x), arange(self.numPoints), choppedBuffer) if self.devices["A"] == "BLEN:LI24:886:BIMAX": xData, yData = rtbsaUtils.filterBuffers( yData, lambda x: x < rtbsaUtils.IPK_LIMIT, xData, yData) if self.ui.checkBoxStdDev.isChecked(): stdDevFilterFunc = self.StdDevFilterFunc(mean(yData), std(yData)) xData, yData = rtbsaUtils.filterBuffers(yData, stdDevFilterFunc, xData, yData) return xData, yData def getLinearFit(self, xData, yData, updateExistingPlot): # noinspection PyTupleAssignmentBalance m, b = polyfit(xData, yData, 1) fitData = polyval([m, b], xData) self.text["slope"].setText('Slope: ' + str("{:.3e}".format(m))) if updateExistingPlot: self.plotAttributes["fit"].setData(xData, fitData) else: # noinspection PyTypeChecker self.plotAttributes["fit"] = PlotCurveItem(xData, fitData, 'g-', linewidth=1) def getPolynomialFit(self, xData, yData, updateExistingPlot): co = polyfit(xData, yData, self.fitOrder) pol = poly1d(co) xDataSorted = sorted(xData) fit = pol(xDataSorted) if updateExistingPlot: self.plotAttributes["parab"].setData(xDataSorted, fit) else: # noinspection PyTypeChecker self.plotAttributes["parab"] = PlotCurveItem(xDataSorted, fit, pen=3, size=2) if self.fitOrder == 2: self.text["slope"].setText('Peak: ' + str(-co[1] / (2 * co[0]))) elif self.fitOrder == 3: self.text["slope"].setText( str("{:.2e}".format(co[0])) + 'x^3' + str("+{:.2e}".format(co[1])) + 'x^2' + str("+{:.2e}".format(co[2])) + 'x' + str("+{:.2e}".format(co[3]))) def genPlotAB(self): if self.ui.checkBoxStdDev.isChecked(): self.plotCurveAndFit(self.filteredBuffers["A"], self.filteredBuffers["B"]) else: self.plotCurveAndFit(self.synchronizedBuffers["A"], self.synchronizedBuffers["B"]) def plotCurveAndFit(self, xData, yData): # noinspection PyTypeChecker self.plotAttributes["curve"] = ScatterPlotItem(xData, yData, pen=1, symbol='x', size=5) self.plot.addItem(self.plotAttributes["curve"]) self.plotFit(xData, yData, self.devices["B"] + ' vs. ' + self.devices["A"]) def plotFit(self, xData, yData, title): self.plot.addItem(self.plotAttributes["curve"]) self.plot.setTitle(title) # Fit line if self.ui.checkBoxLinFit.isChecked(): self.getLinearFit(xData, yData, False) self.plot.addItem(self.plotAttributes["fit"]) # Fit polynomial elif self.ui.checkBoxPolyFit.isChecked(): self.ui.fitOrder.setDisabled(False) try: self.getPolynomialFit(xData, yData, False) self.plot.addItem(self.plotAttributes["parab"]) except linalg.linalg.LinAlgError: print "Error getting polynomial fit" ############################################################################ # This is the main plotting function for "Plot B vs A" that gets called # every self.updateTime milliseconds ############################################################################ def updatePlotAB(self): if not self.checkPlotStatus(): return QApplication.processEvents() self.adjustSynchronizedBuffers() self.filterNans() self.filterPeakCurrent() if self.ui.checkBoxStdDev.isChecked(): self.filterStdDev() self.updateLabelsAndFit(self.filteredBuffers["A"], self.filteredBuffers["B"]) else: self.updateLabelsAndFit(self.synchronizedBuffers["A"], self.synchronizedBuffers["B"]) self.timer.singleShot(self.updateTime, self.updatePlotAB) def filterNans(self): def filterFunc(x): return ~isnan(x) self.filterData(self.synchronizedBuffers["A"], filterFunc, True) self.filterData(self.synchronizedBuffers["B"], filterFunc, True) # Need to filter out errant indices from both buffers to keep them # synchronized def filterData(self, dataBuffer, filterFunc, changeOriginal): bufferA, bufferB = rtbsaUtils.filterBuffers( dataBuffer, filterFunc, self.synchronizedBuffers["A"], self.synchronizedBuffers["B"]) if changeOriginal: self.synchronizedBuffers["A"] = bufferA self.synchronizedBuffers["B"] = bufferB else: self.filteredBuffers["A"] = bufferA self.filteredBuffers["B"] = bufferB # This PV gets insane values, apparently def filterPeakCurrent(self): def filterFunc(x): return x < rtbsaUtils.IPK_LIMIT if self.devices["A"] == "BLEN:LI24:886:BIMAX": self.filterData(self.synchronizedBuffers["A"], filterFunc, True) if self.devices["B"] == "BLEN:LI24:886:BIMAX": self.filterData(self.synchronizedBuffers["B"], filterFunc, True) def filterStdDev(self): bufferA = self.synchronizedBuffers["A"] bufferB = self.synchronizedBuffers["B"] self.filterData(bufferA, self.StdDevFilterFunc(mean(bufferA), std(bufferA)), False) self.filterData(bufferB, self.StdDevFilterFunc(mean(bufferB), std(bufferB)), False) def StdDevFilterFunc(self, average, stdDev): return lambda x: abs(x - average) < self.stdDevstoKeep * stdDev # noinspection PyTypeChecker def updateLabelsAndFit(self, bufferA, bufferB): self.plotAttributes["curve"].setData(bufferA, bufferB) try: if self.ui.checkBoxAutoscale.isChecked(): self.setPlotRanges(bufferA, bufferB) minBufferA = nanmin(bufferA) minBufferB = nanmin(bufferB) maxBufferA = nanmax(bufferA) maxBufferB = nanmax(bufferB) if self.ui.checkBoxShowAve.isChecked(): rtbsaUtils.setPosAndText(self.text["avg"], nanmean(bufferB), minBufferA, minBufferB, 'AVG: ') if self.ui.checkBoxShowStdDev.isChecked(): xPos = (minBufferA + (minBufferA + maxBufferA) / 2) / 2 rtbsaUtils.setPosAndText(self.text["std"], nanstd(bufferB), xPos, minBufferB, 'STD: ') if self.ui.checkBoxCorrCoeff.isChecked(): correlation = corrcoef(bufferA, bufferB) rtbsaUtils.setPosAndText(self.text["corr"], correlation.item(1), minBufferA, maxBufferB, "Corr. Coefficient: ") if self.ui.checkBoxLinFit.isChecked(): self.text["slope"].setPos((minBufferA + maxBufferA) / 2, minBufferB) self.getLinearFit(bufferA, bufferB, True) elif self.ui.checkBoxPolyFit.isChecked(): self.text["slope"].setPos((minBufferA + maxBufferA) / 2, minBufferB) self.getPolynomialFit(bufferA, bufferB, True) except ValueError: print "Error updating plot range" def setPlotRanges(self, bufferA, bufferB): mx = nanmax(bufferB) mn = nanmin(bufferB) if mn != mx: self.plot.setYRange(mn, mx) mx = nanmax(bufferA) mn = nanmin(bufferA) if mn != mx: self.plot.setXRange(mn, mx) def InitializeFFTPlot(self): self.genPlotFFT(self.initializeData(), False) # TODO I have no idea what's happening here def genPlotFFT(self, newdata, updateExistingPlot): if not newdata.size: return None newdata = newdata[:self.numPoints] nans, x = isnan(newdata), lambda z: z.nonzero()[0] # interpolate nans newdata[nans] = interp(x(nans), x(~nans), newdata[~nans]) # remove DC component newdata = newdata - mean(newdata) newdata = concatenate([newdata, zeros(self.numPoints * 2)]) ps = abs(fft.fft(newdata)) / newdata.size self.waitForRate() frequencies = fft.fftfreq(newdata.size, 1.0 / self.getRate()) keep = (frequencies >= 0) ps = ps[keep] frequencies = frequencies[keep] idx = argsort(frequencies) if updateExistingPlot: self.plotAttributes["curve"].setData(x=frequencies[idx], y=ps[idx]) else: # noinspection PyTypeChecker self.plotAttributes["curve"] = PlotCurveItem(x=frequencies[idx], y=ps[idx], pen=1) self.plot.addItem(self.plotAttributes["curve"]) self.plot.setTitle(self.devices["A"]) self.plotAttributes["frequencies"] = frequencies return ps # noinspection PyTypeChecker def cleanPlot(self): self.plot.clear() self.text["avg"] = TextItem('', color=(200, 200, 250), anchor=(0, 1)) self.text["std"] = TextItem('', color=(200, 200, 250), anchor=(0, 1)) self.text["slope"] = TextItem('', color=(200, 200, 250), anchor=(0, 1)) self.text["corr"] = TextItem('', color=(200, 200, 250), anchor=(0, 1)) plotLabels = [ self.text["avg"], self.text["std"], self.text["slope"], self.text["corr"] ] for plotLabel in plotLabels: self.plot.addItem(plotLabel) def initializeData(self): self.printStatus("Initializing " + self.devices["A"] + " buffer...", True) if self.ui.dropdownButtonA.isChecked(): self.devices["A"] = str(self.ui.dropdownA.currentText()) elif self.ui.searchButtonA.isChecked(): pv = str(self.ui.searchInputA.text()).strip() if pv and pv in self.bsapvs: self.devices["A"] = pv else: return None else: return None # Initializing our data by putting a callback on the history buffer PV self.clearAndUpdateCallback("A", "HSTBR", self.callbackA, self.devices["A"], True) while (not self.timeStamps["A"]) and not self.abort: QApplication.processEvents() # Removing that callback and manually appending new values to our local # data buffer using the usual PV # TODO ask Ahmed what the BR is for self.clearAndUpdateCallback("A", "BR", self.callbackA, self.devices["A"]) # This was populated in the callback function return self.rawBuffers["A"] ############################################################################ # This is the main plotting function for "Plot A FFT" that gets called # every self.updateTime seconds ############################################################################ def updatePlotFFT(self): if not self.checkPlotStatus(): return ps = self.genPlotFFT(self.rawBuffers["A"], True) if self.ui.checkBoxAutoscale.isChecked(): mx = max(ps) mn = min(ps) if mx - mn > .00001: frequencies = self.plotAttributes["frequencies"] self.plot.setYRange(mn, mx) # noinspection PyTypeChecker self.plot.setXRange(min(frequencies), max(frequencies)) self.timer.singleShot(self.updateTime, self.updatePlotFFT) def AvsTClick(self): if not self.ui.checkBoxAvsT.isChecked(): pass else: self.ui.checkBoxBvsA.setChecked(False) self.ui.checkBoxFFT.setChecked(False) self.AvsBClick() def AvsBClick(self): if not self.ui.checkBoxBvsA.isChecked(): self.ui.groupBoxB.setDisabled(True) self.ui.searchButtonB.setChecked(False) self.ui.searchButtonB.setDisabled(True) self.ui.searchInputB.setDisabled(True) self.ui.dropdownB.setDisabled(True) self.ui.dropdownButtonB.setChecked(False) self.ui.dropdownButtonB.setDisabled(True) else: self.ui.checkBoxAvsT.setChecked(False) self.ui.checkBoxFFT.setChecked(False) self.AvsTClick() self.ui.groupBoxB.setDisabled(False) self.ui.bsaListB.setDisabled(True) self.ui.searchButtonB.setDisabled(False) self.ui.searchInputB.setDisabled(True) self.ui.dropdownButtonB.setDisabled(False) self.ui.dropdownButtonB.setChecked(True) self.ui.dropdownB.setDisabled(False) self.stop() self.timer.singleShot(250, self.initializePlot) def AFFTClick(self): if not self.ui.checkBoxFFT.isChecked(): pass else: self.ui.checkBoxBvsA.setChecked(False) self.ui.checkBoxAvsT.setChecked(False) self.AvsBClick() def avg_click(self): if not self.ui.checkBoxShowAve.isChecked(): self.text["avg"].setText('') def std_click(self): if not self.ui.checkBoxShowStdDev.isChecked(): self.text["std"].setText('') def corr_click(self): if not self.ui.checkBoxCorrCoeff.isChecked(): self.text["corr"].setText('') def enter_1_click(self): if self.ui.searchButtonA.isChecked(): self.ui.searchInputA.setDisabled(False) self.ui.bsaListA.setDisabled(False) self.ui.dropdownButtonA.setChecked(False) self.ui.dropdownA.setDisabled(True) else: self.ui.searchInputA.setDisabled(True) def enter_2_click(self): if self.ui.searchButtonB.isChecked(): self.ui.searchInputB.setDisabled(False) self.ui.bsaListB.setDisabled(False) self.ui.dropdownButtonB.setChecked(False) self.ui.dropdownB.setDisabled(True) else: self.ui.searchInputB.setDisabled(True) def common_1_click(self): if self.ui.dropdownButtonA.isChecked(): self.ui.dropdownA.setEnabled(True) self.ui.searchButtonA.setChecked(False) self.ui.searchInputA.setDisabled(True) self.ui.bsaListA.setDisabled(True) else: self.ui.dropdownA.setEnabled(False) self.inputActivated() def inputActivated(self): if not self.abort: self.stop() self.timer.singleShot(250, self.initializePlot) def common_2_click(self): if self.ui.dropdownButtonB.isChecked(): self.ui.dropdownB.setEnabled(True) self.ui.searchButtonB.setChecked(False) self.ui.searchInputB.setDisabled(True) self.ui.bsaListB.setDisabled(True) else: self.ui.dropdownB.setEnabled(False) self.inputActivated() def line_click(self): self.ui.checkBoxPolyFit.setChecked(False) self.ui.fitOrder.setDisabled(True) self.ui.labelFitOrder.setDisabled(True) self.reinitialize_plot() def fitOrderActivated(self): try: self.fitOrder = int(self.ui.fitOrder.text()) except ValueError: self.statusBar().showMessage('Enter an integer, 1-10', 6000) return if self.fitOrder > 10 or self.fitOrder < 1: self.statusBar().showMessage( 'Really? That is going to be useful' + ' to you? The (already ridiculous)' + ' range is 1-10. Hope you win a ' + 'nobel prize jackass.', 6000) self.ui.fitOrder.setText('2') self.fitOrder = 2 if self.fitOrder != 2: try: self.text["slope"].setText('') except AttributeError: pass def parab_click(self): self.ui.checkBoxLinFit.setChecked(False) if not self.ui.checkBoxPolyFit.isChecked(): self.ui.fitOrder.setDisabled(True) self.ui.labelFitOrder.setDisabled(True) else: self.ui.fitOrder.setEnabled(True) self.ui.labelFitOrder.setEnabled(True) self.reinitialize_plot() # This is a mess, but it works (used if user changes number points, # fit type etc.) def reinitialize_plot(self): self.cleanPlot() # Setup for single PV plotting if self.ui.checkBoxAvsT.isChecked(): self.genTimePlotA() elif self.ui.checkBoxBvsA.isChecked(): self.genPlotAB() else: self.genPlotFFT(self.synchronizedBuffers["A"], False) def logbook(self): rtbsaUtils.logbook('Python Real-Time BSA', 'BSA Data', str(self.numPoints) + ' points', self.plot.plotItem) self.statusBar().showMessage('Sent to LCLS Physics Logbook!', 10000) def MCCLog(self): rtbsaUtils.MCCLog('/tmp/RTBSA.png', '/tmp/RTBSA.ps', self.plot.plotItem) def clearCallbacks(self, device): if self.pvObjects[device]: self.pvObjects[device].clear_callbacks() self.pvObjects[device].disconnect() def stop(self): self.clearCallbacks("A") if self.pvObjects["B"]: self.clearCallbacks("B") self.abort = True self.statusBar().showMessage('Stopped') self.ui.startButton.setDisabled(False) QApplication.processEvents() def create_menu(self): load_file_action = self.create_action("&Save plot", shortcut="Ctrl+S", slot=self.save_plot, tip="Save the plot") quit_action = self.create_action("&Quit", slot=self.close, shortcut="Ctrl+Q", tip="Close the application") rtbsaUtils.add_actions(self.file_menu, (load_file_action, None, quit_action)) about_action = self.create_action("&About", shortcut='F1', slot=self.on_about, tip='About') rtbsaUtils.add_actions(self.help_menu, (about_action, )) def create_action(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action def save_plot(self): file_choices = "PNG (*.png)|*.png" # noinspection PyTypeChecker,PyCallByClass filePath = unicode( QFileDialog.getSaveFileName(self, 'Save file', '', file_choices)) if filePath: self.ui.widgetPlot.canvas.print_figure(filePath, dpi=100) self.statusBar().showMessage('Saved to %s' % filePath, 2000) def on_about(self): msg = ( "Can you read this? If so, congratulations. You are a magical, " + "marvelous troll.") # noinspection PyCallByClass QMessageBox.about(self, "About", msg.strip())
class SpectrometerWidget(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.setLayout(QtGui.QHBoxLayout()) self.resize(700, 500) self.wave = [] self.spec = [] self.time = None @inlineCallbacks def onInit(): # connect to server ipAddress = TEST_SPECTROMETER_SERVER if DEBUG else SPECTROMETER_SERVER protocol = yield getProtocol(ipAddress) # create a client self.client = SpectrometerClient(protocol) self.wave = yield self.client.getWavelengths() self.numberToAverage = 1 self.numberAcquired = 0 self.darkSpectrum = np.zeros(NUM_PIXELS) self.specProcessed = np.zeros(NUM_PIXELS) self.gettingDark = False # set up overall layout: 1 large panel (plot) to left of 1 narrow / # panel (controls) all above 1 skinny panel (timestamp) fullLayout = QtGui.QVBoxLayout() self.layout().addLayout(fullLayout) topHalfLayout = QtGui.QHBoxLayout() fullLayout.addLayout(topHalfLayout) # define the plot self.plotWidget = PlotWidget() self.plot = self.plotWidget.plot() topHalfLayout.addWidget(self.plotWidget, 1) # define the controls panel cpLayout = QtGui.QVBoxLayout() topHalfLayout.addLayout(cpLayout) # define the capture controls (to go on controls panel) capLayout = QtGui.QVBoxLayout() def updatePlot(x, y): x = np.asarray(x) y = np.asarray(y) self.plotWidget.clear() self.plotWidget.plot(x, y, pen=mkPen("w", width=1)) self.plotWidget.addItem(self.cursorVert) self.plotWidget.addItem(self.cursorHori) vertLabel.setText(str(round(self.cursorVert.pos()[0], 2))) horiLabel.setText(str(round(self.cursorHori.pos()[1], 2))) def avgSpec(): oldAvgSpec = self.specProcessed addThis = self.spec - self.darkSpectrum self.numberAcquired += 1 if self.numberAcquired < self.numberToAverage: scale = self.numberAcquired else: scale = self.numberToAverage newAvg = ((scale - 1) * oldAvgSpec + addThis) / scale self.specProcessed = newAvg @inlineCallbacks def capture(): self.spec = yield self.client.getSpectrum() self.spec = np.asarray(self.spec) self.time = yield self.client.getLastTime() yield avgSpec() updatePlot(self.wave, self.specProcessed) self.timestamp.setText("last update: " + str(self.time)) @inlineCallbacks def forcePress(): self.numberAcquired = 0 yield capture() forceButton = QtGui.QPushButton("force") forceButton.clicked.connect(forcePress) capLayout.addWidget(forceButton) autoRunLayout = QtGui.QHBoxLayout() self.freeRunCall = LoopingCall(capture) self.freeRunStatus = False def freeRun(): if self.freeRunStatus: freeButton.setText("start auto") forceButton.setEnabled(True) self.freeRunCall.stop() self.freeRunStatus = False self.numberAcquired = 0 return if not self.freeRunStatus: freeButton.setText("stop auto") forceButton.setEnabled(False) self.freeRunCall.start(autoRateSpin.value(), now=True) self.freeRunStatus = True freeButton = QtGui.QPushButton("start auto") freeButton.clicked.connect(freeRun) autoRunLayout.addWidget(freeButton) def updateAutoRate(): if self.freeRunStatus: self.freeRunCall.stop() self.freeRunCall.start(autoRateSpin.value(), now=True) autoRateSpin = QtGui.QDoubleSpinBox() autoRateSpin.setRange(0.1, 10000.0) autoRateSpin.setValue(0.5) autoRateSpin.setSuffix("s") autoRateSpin.setSingleStep(0.1) autoRateSpin.valueChanged.connect(updateAutoRate) autoRunLayout.addWidget(autoRateSpin) capLayout.addLayout(autoRunLayout) cpLayout.addWidget(LabelWidget("capture", capLayout)) # define the cursor/analysis controls curLayout = QtGui.QVBoxLayout() cpLayout.addWidget(LabelWidget("analysis", curLayout)) self.cursorVert = InfiniteLine( pos=self.wave[NUM_PIXELS / 2], angle=90, pen=mkPen("g", width=0.5), movable=True ) self.cursorHori = InfiniteLine(pos=0, angle=0, pen=mkPen("g", width=0.5), movable=True) self.plotWidget.addItem(self.cursorVert) self.plotWidget.addItem(self.cursorHori) vertLayout = QtGui.QHBoxLayout() vertName = QtGui.QLabel() vertName.setText("wavelength: ") vertLayout.addWidget(vertName) vertLabel = QtGui.QLabel() vertLabel.setText(str(round(self.cursorVert.pos()[0], 2))) vertLayout.addWidget(vertLabel) curLayout.addLayout(vertLayout) horiLayout = QtGui.QHBoxLayout() horiName = QtGui.QLabel() horiName.setText("intensity: ") horiLayout.addWidget(horiName) horiLabel = QtGui.QLabel() horiLabel.setText(str(round(self.cursorHori.pos()[0], 2))) horiLayout.addWidget(horiLabel) curLayout.addLayout(horiLayout) # define the acquisition controls acqLayout = QtGui.QVBoxLayout() cpLayout.addWidget(LabelWidget("acquisition", acqLayout)) # integration integLayout = QtGui.QHBoxLayout() acqLayout.addLayout(integLayout) integTimeLabel = QtGui.QLabel() integTimeLabel.setText("integration: ") integLayout.addWidget(integTimeLabel) def integTimeUpdate(): newTime = integTimeSpin.value() self.client.setIntegrationTime(newTime) integTimeSpin = QtGui.QDoubleSpinBox() integTimeSpin.setRange(0.001, 10) integTimeSpin.setDecimals(3) integTimeSpin.setValue(0.100) integTimeSpin.setSingleStep(0.05) integTimeSpin.setSuffix("s") integTimeSpin.editingFinished.connect(integTimeUpdate) integLayout.addWidget(integTimeSpin) # averaging avgLayout = QtGui.QHBoxLayout() acqLayout.addLayout(avgLayout) avgLabel = QtGui.QLabel() avgLabel.setText("averaging: ") avgLayout.addWidget(avgLabel) def avgUpdate(): self.numberToAverage = avgSpin.value() avgSpin = QtGui.QSpinBox() avgSpin.setRange(1, 10000) avgSpin.setValue(1) avgSpin.valueChanged.connect(avgUpdate) avgLayout.addWidget(avgSpin) # dark spectrum darkLayout = QtGui.QHBoxLayout() acqLayout.addLayout(darkLayout) @inlineCallbacks def getDark(): resetDark() self.gettingDark = True self.numberAcquired = 0 wasInAuto = self.freeRunStatus if self.freeRunStatus: freeRun() # if in auto mode, stop it self.specProcessed = np.zeros(NUM_PIXELS) for specCount in range(self.numberToAverage): yield capture() self.darkSpectrum = self.specProcessed self.specProcessed = np.zeros(NUM_PIXELS) if wasInAuto: freeRun() self.numberAcquired = 0 self.gettingDark = False darkSpecButton = QtGui.QPushButton("dark") darkSpecButton.clicked.connect(getDark) darkLayout.addWidget(darkSpecButton) def resetDark(): self.darkSpectrum = np.zeros(NUM_PIXELS) self.specProcessed = np.zeros(NUM_PIXELS) resetDarkButton = QtGui.QPushButton("reset") resetDarkButton.clicked.connect(resetDark) darkLayout.addWidget(resetDarkButton) # define the timestamp panel self.timestamp = QtGui.QLabel() self.timestamp.setText("last update: never") self.timestamp.setAlignment(QtCore.Qt.AlignCenter) fullLayout.addWidget(self.timestamp) onInit() def refresh(self): time.sleep(0.5) self.update_plot() self.refresh() def closeEvent(self, event): reactor.stop() event.accept()
class SpectrogramWindow(QWidget): """ This is the class for the spectrogram window """ def __init__(self, station_list): super(QWidget, self).__init__() self.layout = QGridLayout(self) self.station_list = station_list self.hidden = False self.spectrogram_1 = PlotWidget(self) self.spectrogram_1.setFixedWidth(400) self.spectrogram_1.setFixedHeight(550) self.spectrogram_2 = PlotWidget(self) self.spectrogram_2.setFixedWidth(400) self.station_box_1 = QComboBox(self) self.station_box_2 = QComboBox(self) self.waiting_traces = [None, None] self.waiting_p_picks = [None, None] self.filter_stats = FilterStats(True) self.spectrogram_threads = [None, None] self.spectrogram_threads[0] = SpectrogramCalculatorThread( self.filter_stats, 0) self.spectrogram_threads[0].signal.connect(self.plotSpectrogram) self.spectrogram_threads[1] = SpectrogramCalculatorThread( self.filter_stats, 1) self.spectrogram_threads[1].signal.connect(self.plotSpectrogram) self.filter_widget = FilterWidget(self, self.filter_stats) self.layout.addWidget(self.spectrogram_1, 0, 0, 1, 2) self.layout.addWidget(self.spectrogram_2, 0, 2, 1, 2) self.layout.addWidget(self.station_box_1, 1, 0) self.layout.addWidget(self.station_box_2, 1, 2) self.layout.addWidget(self.filter_widget, 2, 0) self.station_box_1.activated.connect(self.replotSpectrogram1) self.station_box_2.activated.connect(self.replotSpectrogram2) self.setStationsFromNewEvent() def closeEvent(self, event): """ This function will be called when the spectrogramWindow Closes """ self.hidden = True def replotSpectrogram1(self): """ This function is to be used only by station_box_1 """ self.getTraceForSpectrogramThread(0) def replotSpectrogram2(self): """ This function is to be used only by station_box_2 """ self.getTraceForSpectrogramThread(1) def getTraceForSpectrogramThread(self, spectrogram_id): """ Fetch correct trace for the spectrogram_thread. Choose this from the value from station_box_1 or station_box_2 """ station_name = None if spectrogram_id == 0: station_name = self.station_box_1.currentText() elif spectrogram_id == 1: station_name = self.station_box_2.currentText() trace, p_pick = self.station_list.getCurrentTraceAndPPickForStation( station_name) if trace is None: return self.calculateSpectrogram(trace, p_pick, spectrogram_id) def setStationsFromNewEvent(self): """ Set the focused event to spectrogram window """ stations = [x[0] for x in self.station_list.getOrderedStationList()] if len(stations) < 2: return self.station_box_1.clear() self.station_box_2.clear() for stat in stations: self.station_box_1.addItem(stat) self.station_box_2.addItem(stat) self.station_box_1.setCurrentIndex(0) self.station_box_2.setCurrentIndex(1) self.getTraceForSpectrogramThread(0) self.getTraceForSpectrogramThread(1) def filterChange(self): """ Function that is called when the filters have been changed """ self.getTraceForSpectrogramThread(0) self.getTraceForSpectrogramThread(1) def calculateSpectrogram(self, waveform_trace, p_pick, spectrogram_id): """ Function for calculating a spectrogram """ if self.spectrogram_threads[spectrogram_id].running: self.waiting_traces[spectrogram_id] = waveform_trace self.waiting_p_picks[spectrogram_id] = p_pick self.spectrogram_threads[spectrogram_id].interrupt = True else: self.spectrogram_threads[ spectrogram_id].waveform_trace = waveform_trace self.spectrogram_threads[spectrogram_id].p_pick = p_pick self.spectrogram_threads[spectrogram_id].running = True self.spectrogram_threads[spectrogram_id].start() def plotSpectrogram(self, return_values): """ Function for plotting a spectrogram """ spectrogram_id, spectrogram, sample_frequencies, sample_times = return_values print("Window {0} done".format(spectrogram_id)) self.spectrogram_threads[spectrogram_id].running = False self.spectrogram_threads[spectrogram_id].interrupt = False if self.waiting_traces[spectrogram_id] is not None: self.calculateSpectrogram(self.waiting_traces[spectrogram_id], self.waiting_p_picks[spectrogram_id], spectrogram_id) self.waiting_traces[spectrogram_id] = None self.waiting_p_picks[spectrogram_id] = None if spectrogram is None: return if spectrogram_id == 0: self.spectrogram_1.clear() self.spectrogram_1.addItem(spectrogram) elif spectrogram_id == 1: self.spectrogram_2.clear() self.spectrogram_2.addItem(spectrogram)
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 PyQtGraphDataPlot(QWidget): limits_changed = Signal() def __init__(self, parent=None): super(PyQtGraphDataPlot, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.getPlotItem().addLegend() self._plot_widget.setBackground((255, 255, 255)) self._plot_widget.setXRange(0, 10, padding=0) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._plot_widget.getPlotItem().sigRangeChanged.connect(self.limits_changed) self._curves = {} self._current_vline = None def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False): pen = mkPen(curve_color, width=1) symbol = "o" symbolPen = mkPen(QColor(Qt.black)) symbolBrush = mkBrush(curve_color) # this adds the item to the plot and legend if markers_on: plot = self._plot_widget.plot(name=curve_name, pen=pen, symbol=symbol, symbolPen=symbolPen, symbolBrush=symbolBrush, symbolSize=4) else: plot = self._plot_widget.plot(name=curve_name, pen=pen) self._curves[curve_id] = 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]) del self._curves[curve_id] self._update_legend() def _update_legend(self): # clear and rebuild legend (there is no remove item method for the legend...) self._plot_widget.clear() self._plot_widget.getPlotItem().legend.items = [] for curve in self._curves.values(): self._plot_widget.addItem(curve) if self._current_vline: self._plot_widget.addItem(self._current_vline) def redraw(self): pass def set_values(self, curve_id, data_x, data_y): curve = self._curves[curve_id] curve.setData(data_x, data_y) def vline(self, x, color): if self._current_vline: self._plot_widget.removeItem(self._current_vline) self._current_vline = self._plot_widget.addLine(x=x, pen=color) def set_xlim(self, limits): # TODO: this doesn't seem to handle fast updates well self._plot_widget.setXRange(limits[0], limits[1], padding=0) def set_ylim(self, limits): self._plot_widget.setYRange(limits[0], limits[1], padding=0) def get_xlim(self): x_range, _ = self._plot_widget.viewRange() return x_range def get_ylim(self): _, y_range = self._plot_widget.viewRange() return y_range
class UIMainWindow(object): labels: List[QtWidgets.QLabel] operations_amount_fields: List[QtWidgets.QSpinBox] additional_operations_checkboxes: List[QtWidgets.QCheckBox] procedural_times_output_fields: List[QtWidgets.QLineEdit] oop_times_output_fields: List[QtWidgets.QLineEdit] def __init__(self): self.labels = [] self.operations_amount_fields = [] self.additional_operations_checkboxes = [] self.procedural_times_output_fields = [] self.oop_times_output_fields = [] self.thread_pool = QThreadPool() self.thread_pool.setMaxThreadCount(1) self.main_operations_number = 0 self.execution_times = [[0], [0]] def setup_ui(self, MainWindow): font_size_9 = QtGui.QFont() font_size_9.setPointSize(9) font_size_10 = QtGui.QFont() font_size_10.setPointSize(10) font_size_12 = QtGui.QFont() font_size_12.setPointSize(12) self.central_widget = QtWidgets.QWidget(MainWindow) self.central_widget.setObjectName("central_widget") self.labels.insert(0, QtWidgets.QLabel(self.central_widget)) self.labels[0].setObjectName("label_operation_amount") self.labels[0].setGeometry(QtCore.QRect(10, 40, 91, 16)) self.labels[0].setText( QtCore.QCoreApplication.translate("MainWindow", "Ilość operacji")) self.labels.insert(1, QtWidgets.QLabel(self.central_widget)) self.labels[1].setObjectName("label_operations_select") self.labels[1].setGeometry(QtCore.QRect(110, 40, 141, 16)) self.labels[1].setText( QtCore.QCoreApplication.translate("MainWindow", "Wybór operacji do wykonania")) self.labels.insert(2, QtWidgets.QLabel(self.central_widget)) self.labels[2].setObjectName("label_elapsed_time") self.labels[2].setGeometry(QtCore.QRect(290, 10, 231, 21)) self.labels[2].setText( QtCore.QCoreApplication.translate("MainWindow", "Czasy wykonania (milisekundy)")) self.labels[2].setFont(font_size_12) self.labels.insert(3, QtWidgets.QLabel(self.central_widget)) self.labels[3].setObjectName("label_result_console") self.labels[3].setGeometry(QtCore.QRect(10, 310, 111, 16)) self.labels[3].setText( QtCore.QCoreApplication.translate("MainWindow", "Konsola wynikowa")) self.labels[3].setFont(font_size_10) self.labels.insert(4, QtWidgets.QLabel(self.central_widget)) self.labels[4].setObjectName("label_time_chart_by_approach") self.labels[4].setGeometry(QtCore.QRect(550, 10, 321, 21)) self.labels[4].setText( QtCore.QCoreApplication.translate( "MainWindow", "Wykres czasu działania programu w zależności od podejścia")) self.labels[4].setFont(font_size_9) self.labels.insert(5, QtWidgets.QLabel(self.central_widget)) self.labels[5].setObjectName("label_operations_amount") self.labels[5].setGeometry(QtCore.QRect(550, 260, 321, 30)) self.labels[5].setAlignment(QtCore.Qt.AlignCenter) self.labels[5].setText( QtCore.QCoreApplication.translate("MainWindow", "Ilość operacji (w tysiącach)")) self.labels[5].setFont(font_size_10) self.labels.insert(6, VerticalLabel(self.central_widget)) self.labels[6].setObjectName("label_chart_elapsed_time") self.labels[6].setGeometry(QtCore.QRect(520, 40, 30, 221)) self.labels[6].setLayoutDirection(QtCore.Qt.LeftToRight) self.labels[6].setAutoFillBackground(False) self.labels[6].setScaledContents(False) self.labels[6].setWordWrap(False) self.labels[6].setOpenExternalLinks(False) self.labels[6].setText( QtCore.QCoreApplication.translate("MainWindow", "Czas wykonania (milisekundy)")) self.labels[6].setFont(font_size_10) self.labels.insert(7, QtWidgets.QLabel(self.central_widget)) self.labels[7].setObjectName("label_input_data") self.labels[7].setGeometry(QtCore.QRect(10, 10, 121, 21)) self.labels[7].setText( QtCore.QCoreApplication.translate("MainWindow", "Dane wejściowe")) self.labels[7].setFont(font_size_12) self.labels.insert(8, QtWidgets.QLabel(self.central_widget)) self.labels[8].setObjectName("label_procedural") self.labels[8].setGeometry(QtCore.QRect(290, 40, 107, 26)) self.labels[8].setAlignment(QtCore.Qt.AlignCenter) self.labels[8].setStyleSheet("background-color: #f00") self.labels[8].setText( QtCore.QCoreApplication.translate("MainWindow", "Proceduralnie")) self.labels.insert(9, QtWidgets.QLabel(self.central_widget)) self.labels[9].setObjectName("label_oop") self.labels[9].setGeometry(QtCore.QRect(403, 40, 108, 26)) self.labels[9].setAlignment(QtCore.Qt.AlignCenter) self.labels[9].setStyleSheet("background-color: #0ff") self.labels[9].setText( QtCore.QCoreApplication.translate("MainWindow", "Obiektowo")) self.vertical_line = QtWidgets.QFrame(self.central_widget) self.vertical_line.setObjectName("vertical_line") self.vertical_line.setGeometry(QtCore.QRect(260, 10, 21, 271)) self.vertical_line.setFrameShape(QtWidgets.QFrame.VLine) self.vertical_line.setFrameShadow(QtWidgets.QFrame.Sunken) self.horizontal_line = QtWidgets.QFrame(self.central_widget) self.horizontal_line.setObjectName("horizontal_line") self.horizontal_line.setGeometry(QtCore.QRect(10, 290, 861, 20)) self.horizontal_line.setFrameShape(QtWidgets.QFrame.HLine) self.horizontal_line.setFrameShadow(QtWidgets.QFrame.Sunken) self.operations_amount_widget = QtWidgets.QWidget(self.central_widget) self.operations_amount_widget.setGeometry(QtCore.QRect( 10, 60, 91, 171)) self.operations_amount_widget.setObjectName("operations_amount_widget") self.operations_amount_layout = QtWidgets.QVBoxLayout( self.operations_amount_widget) self.operations_amount_layout.setContentsMargins(0, 0, 0, 0) self.operations_amount_layout.setObjectName("operations_amount_layout") self.operations_amount_fields.insert( 0, QtWidgets.QSpinBox(self.operations_amount_widget)) self.operations_amount_fields[0].setObjectName( "operations_amount_field_0") self.operations_amount_fields[0].setRange(10000, 1000000) self.operations_amount_fields[0].setSingleStep(1000) self.operations_amount_fields[0].setValue(15000) self.operations_amount_layout.addWidget( self.operations_amount_fields[0]) self.operations_amount_fields.insert( 1, QtWidgets.QSpinBox(self.operations_amount_widget)) self.operations_amount_fields[1].setObjectName( "operations_amount_field_1") self.operations_amount_fields[1].setRange(10000, 1000000) self.operations_amount_fields[1].setSingleStep(1000) self.operations_amount_fields[1].setValue(50000) self.operations_amount_layout.addWidget( self.operations_amount_fields[1]) self.operations_amount_fields.insert( 2, QtWidgets.QSpinBox(self.operations_amount_widget)) self.operations_amount_fields[2].setObjectName( "operations_amount_field_2") self.operations_amount_fields[2].setRange(10000, 1000000) self.operations_amount_fields[2].setSingleStep(1000) self.operations_amount_fields[2].setValue(150000) self.operations_amount_layout.addWidget( self.operations_amount_fields[2]) self.operations_amount_fields.insert( 3, QtWidgets.QSpinBox(self.operations_amount_widget)) self.operations_amount_fields[3].setObjectName( "operations_amount_field_3") self.operations_amount_fields[3].setRange(10000, 1000000) self.operations_amount_fields[3].setSingleStep(1000) self.operations_amount_fields[3].setValue(300000) self.operations_amount_layout.addWidget( self.operations_amount_fields[3]) self.operations_amount_fields.insert( 4, QtWidgets.QSpinBox(self.operations_amount_widget)) self.operations_amount_fields[4].setObjectName( "operations_amount_field_4") self.operations_amount_fields[4].setRange(10000, 1000000) self.operations_amount_fields[4].setSingleStep(1000) self.operations_amount_fields[4].setValue(1000000) self.operations_amount_layout.addWidget( self.operations_amount_fields[4]) self.additional_operations_widget = QtWidgets.QWidget( self.central_widget) self.additional_operations_widget.setObjectName( "additional_operations_widget") self.additional_operations_widget.setGeometry( QtCore.QRect(110, 60, 141, 171)) self.additional_operations_layout = QtWidgets.QVBoxLayout( self.additional_operations_widget) self.additional_operations_layout.setObjectName( "additional_operations_layout") self.additional_operations_layout.setContentsMargins(0, 0, 0, 0) self.additional_operations_checkboxes.insert( 0, QtWidgets.QCheckBox(self.additional_operations_widget)) self.additional_operations_checkboxes[0].setObjectName( "additional_operations_checkbox_0") self.additional_operations_checkboxes[0].setEnabled(False) self.additional_operations_checkboxes[0].setChecked(True) self.additional_operations_checkboxes[0].setText( QtCore.QCoreApplication.translate("MainWindow", "Operacji")) self.additional_operations_layout.addWidget( self.additional_operations_checkboxes[0]) self.additional_operations_checkboxes.insert( 1, QtWidgets.QCheckBox(self.additional_operations_widget)) self.additional_operations_checkboxes[1].setObjectName( "additional_operations_checkbox_1") self.additional_operations_checkboxes[1].setText( QtCore.QCoreApplication.translate("MainWindow", "Operacji dodatkowych")) self.additional_operations_layout.addWidget( self.additional_operations_checkboxes[1]) self.additional_operations_checkboxes.insert( 2, QtWidgets.QCheckBox(self.additional_operations_widget)) self.additional_operations_checkboxes[2].setObjectName( "additional_operations_checkbox_2") self.additional_operations_checkboxes[2].setText( QtCore.QCoreApplication.translate("MainWindow", "Operacji dodatkowych")) self.additional_operations_layout.addWidget( self.additional_operations_checkboxes[2]) self.additional_operations_checkboxes.insert( 3, QtWidgets.QCheckBox(self.additional_operations_widget)) self.additional_operations_checkboxes[3].setObjectName( "additional_operations_checkbox_3") self.additional_operations_checkboxes[3].setText( QtCore.QCoreApplication.translate("MainWindow", "Operacji dodatkowych")) self.additional_operations_layout.addWidget( self.additional_operations_checkboxes[3]) self.additional_operations_checkboxes.insert( 4, QtWidgets.QCheckBox(self.additional_operations_widget)) self.additional_operations_checkboxes[4].setObjectName( "additional_operations_checkbox_4") self.additional_operations_checkboxes[4].setText( QtCore.QCoreApplication.translate("MainWindow", "Operacji dodatkowych")) self.additional_operations_layout.addWidget( self.additional_operations_checkboxes[4]) self.operation_times_widget = QtWidgets.QWidget(self.central_widget) self.operation_times_widget.setObjectName("operation_times_widget") self.operation_times_widget.setGeometry(QtCore.QRect( 290, 72, 221, 171)) self.operation_times_layout = QtWidgets.QHBoxLayout( self.operation_times_widget) self.operation_times_layout.setObjectName("operation_times_layout") self.operation_times_layout.setContentsMargins(0, 0, 0, 0) self.procedural_times_output_layout = QtWidgets.QVBoxLayout() self.procedural_times_output_layout.setObjectName( "procedural_times_output_layout") self.procedural_times_output_fields.insert( 0, QtWidgets.QLineEdit(self.operation_times_widget)) self.procedural_times_output_fields[0].setObjectName( "procedural_time_output_fields_0") self.procedural_times_output_fields[0].setAlignment( QtCore.Qt.AlignCenter) self.procedural_times_output_fields[0].setReadOnly(True) self.procedural_times_output_fields[0].setText("-") self.procedural_times_output_layout.addWidget( self.procedural_times_output_fields[0]) self.procedural_times_output_fields.insert( 1, QtWidgets.QLineEdit(self.operation_times_widget)) self.procedural_times_output_fields[1].setObjectName( "procedural_time_output_fields_1") self.procedural_times_output_fields[1].setAlignment( QtCore.Qt.AlignCenter) self.procedural_times_output_fields[1].setReadOnly(True) self.procedural_times_output_fields[1].setText("-") self.procedural_times_output_layout.addWidget( self.procedural_times_output_fields[1]) self.procedural_times_output_fields.insert( 2, QtWidgets.QLineEdit(self.operation_times_widget)) self.procedural_times_output_fields[2].setObjectName( "procedural_time_output_fields_2") self.procedural_times_output_fields[2].setAlignment( QtCore.Qt.AlignCenter) self.procedural_times_output_fields[2].setReadOnly(True) self.procedural_times_output_fields[2].setText("-") self.procedural_times_output_layout.addWidget( self.procedural_times_output_fields[2]) self.procedural_times_output_fields.insert( 3, QtWidgets.QLineEdit(self.operation_times_widget)) self.procedural_times_output_fields[3].setObjectName( "procedural_time_output_fields_3") self.procedural_times_output_fields[3].setAlignment( QtCore.Qt.AlignCenter) self.procedural_times_output_fields[3].setReadOnly(True) self.procedural_times_output_fields[3].setText("-") self.procedural_times_output_layout.addWidget( self.procedural_times_output_fields[3]) self.procedural_times_output_fields.insert( 4, QtWidgets.QLineEdit(self.operation_times_widget)) self.procedural_times_output_fields[4].setObjectName( "procedural_time_output_fields_4") self.procedural_times_output_fields[4].setAlignment( QtCore.Qt.AlignCenter) self.procedural_times_output_fields[4].setReadOnly(True) self.procedural_times_output_fields[4].setText("-") self.procedural_times_output_layout.addWidget( self.procedural_times_output_fields[4]) self.operation_times_layout.addLayout( self.procedural_times_output_layout) self.oop_times_output_layout = QtWidgets.QVBoxLayout() self.oop_times_output_layout.setObjectName("oop_times_output_layout") self.oop_times_output_fields.insert( 0, QtWidgets.QLineEdit(self.operation_times_widget)) self.oop_times_output_fields[0].setObjectName("timeOutputField0") self.oop_times_output_fields[0].setAlignment(QtCore.Qt.AlignCenter) self.oop_times_output_fields[0].setReadOnly(True) self.oop_times_output_fields[0].setText("-") self.oop_times_output_layout.addWidget(self.oop_times_output_fields[0]) self.oop_times_output_fields.insert( 1, QtWidgets.QLineEdit(self.operation_times_widget)) self.oop_times_output_fields[1].setObjectName("timeOutputField1") self.oop_times_output_fields[1].setAlignment(QtCore.Qt.AlignCenter) self.oop_times_output_fields[1].setReadOnly(True) self.oop_times_output_fields[1].setText("-") self.oop_times_output_layout.addWidget(self.oop_times_output_fields[1]) self.oop_times_output_fields.insert( 2, QtWidgets.QLineEdit(self.operation_times_widget)) self.oop_times_output_fields[2].setObjectName("timeOutputField2") self.oop_times_output_fields[2].setAlignment(QtCore.Qt.AlignCenter) self.oop_times_output_fields[2].setReadOnly(True) self.oop_times_output_fields[2].setText("-") self.oop_times_output_layout.addWidget(self.oop_times_output_fields[2]) self.oop_times_output_fields.insert( 3, QtWidgets.QLineEdit(self.operation_times_widget)) self.oop_times_output_fields[3].setObjectName("timeOutputField3") self.oop_times_output_fields[3].setAlignment(QtCore.Qt.AlignCenter) self.oop_times_output_fields[3].setReadOnly(True) self.oop_times_output_fields[3].setText("-") self.oop_times_output_layout.addWidget(self.oop_times_output_fields[3]) self.oop_times_output_fields.insert( 4, QtWidgets.QLineEdit(self.operation_times_widget)) self.oop_times_output_fields[4].setObjectName("timeOutputField4") self.oop_times_output_fields[4].setAlignment(QtCore.Qt.AlignCenter) self.oop_times_output_fields[4].setReadOnly(True) self.oop_times_output_fields[4].setText("-") self.oop_times_output_layout.addWidget(self.oop_times_output_fields[4]) self.operation_times_layout.addLayout(self.oop_times_output_layout) self.calculate_button = QtWidgets.QPushButton(self.central_widget) self.calculate_button.setObjectName("calculate_button") self.calculate_button.setGeometry(QtCore.QRect(10, 240, 241, 41)) self.calculate_button.setText( QtCore.QCoreApplication.translate("MainWindow", "Oblicz")) self.calculate_button.clicked.connect(lambda: self.count()) self.chart = PlotWidget(self.central_widget) self.chart.setObjectName("chart") self.chart.setGeometry(QtCore.QRect(550, 40, 321, 221)) self.chart.showGrid(x=True, y=True) self.console = QtWidgets.QTextBrowser(self.central_widget) self.console.setObjectName("console") self.console.setGeometry(QtCore.QRect(10, 330, 861, 91)) self.console.setAutoFillBackground(False) MainWindow.setObjectName("MainWindow") MainWindow.setFixedSize(880, 430) MainWindow.setCentralWidget(self.central_widget) MainWindow.setWindowTitle( QtCore.QCoreApplication.translate( "MainWindow", "Porównanie czasów operacji wykonanych proceduralnie i obiektowo (M. Liber, P. Lyschik, 2020)" )) QtCore.QMetaObject.connectSlotsByName(MainWindow) def disable_ui(self): self.calculate_button.setEnabled(False) for field in self.operations_amount_fields: field.setEnabled(False) for check_box in self.additional_operations_checkboxes[1:]: check_box.setEnabled(False) def enable_ui(self): self.calculate_button.setEnabled(True) for field in self.operations_amount_fields: field.setEnabled(True) for check_box in self.additional_operations_checkboxes[1:]: check_box.setEnabled(True) def clear_time_tables(self): for field in self.procedural_times_output_fields: field.setText("-") for field in self.oop_times_output_fields: field.setText("-") def is_calculation_finished(self): for element in self.procedural_times_output_fields[:self. main_operations_number - 1]: if element.text() == "-": return False for element in self.oop_times_output_fields[:self. main_operations_number - 1]: if element.text() == "-": return False return True def clear_chart(self): self.chart.clear() def clear_times(self): self.execution_times = [[0], [0]] def clear_console(self): self.console.clear() def clear_data(self): self.clear_time_tables() self.clear_chart() self.clear_times() self.clear_console() def console_print_line(self, message): date_time_now = datetime.datetime.now() current_date_time = date_time_now.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] self.console.append("[{0}] {1}".format(current_date_time, message)) def print_execution_time(self, operation_type, operations_number, execution_time): self.console_print_line( "Wykonanie {0:,} operacji w podejściu {1} zajęło {2} ms.".format( operations_number, operation_type, execution_time).replace(',', ' ')) def get_data(self): data_table = [0, self.operations_amount_fields[0].value()] if self.additional_operations_checkboxes[1].isChecked(): data_table.append(self.operations_amount_fields[1].value()) if self.additional_operations_checkboxes[2].isChecked(): data_table.append(self.operations_amount_fields[2].value()) if self.additional_operations_checkboxes[3].isChecked(): data_table.append(self.operations_amount_fields[3].value()) if self.additional_operations_checkboxes[4].isChecked(): data_table.append(self.operations_amount_fields[4].value()) return data_table def count(self): self.disable_ui() self.clear_data() self.console_print_line("Rozpoczęto obliczenia.") number_of_operations = self.get_data() self.main_operations_number = len(number_of_operations) for i in range(1, len(number_of_operations)): self.multi_thread_execute(number_of_operations[i], operation_procedural) self.multi_thread_execute(number_of_operations[i], operation_objective) def update_procedural(self, result): self.execution_times[0].append(result[0]) self.procedural_times_output_fields[len(self.execution_times[0]) - 2].setText(str(result[0])) self.update_plots() self.print_execution_time("proceduralnym", result[1], self.execution_times[0][-1]) if self.is_calculation_finished(): self.console_print_line("Zakończono obliczenia.") self.enable_ui() def update_objective(self, result): self.execution_times[1].append(result[0]) self.oop_times_output_fields[len(self.execution_times[1]) - 2].setText( str(result[0])) self.update_plots() self.print_execution_time("obiektowym", result[1], self.execution_times[1][-1]) if self.is_calculation_finished(): self.console_print_line("Zakończono obliczenia.") self.enable_ui() def update_plots(self): chart_data_procedural = self.prepare_chart_data(0) self.chart.plot(chart_data_procedural[0], chart_data_procedural[1], name='Proceduralnie', pen=(255, 0, 0), symbol='o', symbolSize=5, symbolPen=(255, 0, 0), symbolBrush=(255, 0, 0)) chart_data_oop = self.prepare_chart_data(1) self.chart.plot(chart_data_oop[0], chart_data_oop[1], name='Obiektowo', pen=(0, 255, 255), symbol='o', symbolSize=5, symbolPen=(0, 255, 255), symbolBrush=(0, 255, 255)) def prepare_chart_data(self, data_id): number_of_operations = self.reduce_data_for_chart_by_thousand( self.get_data()[:len(self.execution_times[data_id])]) times = self.execution_times[data_id] return self.sort_two_tables_by_first(number_of_operations, times) def sort_two_tables_by_first(self, sorted_table, other_table): while True: edition_flag = 0 for i in range(len(sorted_table) - 1): if sorted_table[i] > sorted_table[i + 1]: tmp = sorted_table[i] sorted_table[i] = sorted_table[i + 1] sorted_table[i + 1] = tmp tmp_other = other_table[i] other_table[i] = other_table[i + 1] other_table[i + 1] = tmp_other edition_flag += 1 if edition_flag == 0: return (sorted_table, other_table) def reduce_data_for_chart_by_thousand(self, data): reduced_data = [] for element in data: reduced_data.append(element / 1000) return reduced_data def multi_thread_execute(self, operations_number, operation_type): worker = Worker(operation_type, operations_number) if operation_type == operation_procedural: worker.signals.result.connect(self.update_procedural) else: worker.signals.result.connect(self.update_objective) self.thread_pool.start(worker)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1103, 561) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.Connect_box = QtWidgets.QGroupBox(self.centralwidget) self.Connect_box.setGeometry(QtCore.QRect(10, 10, 191, 121)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.Connect_box.setFont(font) self.Connect_box.setObjectName("Connect_box") self.COM = QtWidgets.QComboBox(self.Connect_box) self.COM.setGeometry(QtCore.QRect(50, 30, 131, 22)) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.COM.setFont(font) self.COM.setLayoutDirection(QtCore.Qt.LeftToRight) self.COM.setObjectName("COM") self.COM.addItem("") self.COM.addItem("") self.COM.addItem("") self.COM.addItem("") self.COM.addItem("") self.COM.addItem("") self.connect = QtWidgets.QPushButton(self.Connect_box) self.connect.setGeometry(QtCore.QRect(20, 70, 151, 41)) font = QtGui.QFont() font.setPointSize(9) font.setBold(False) font.setWeight(50) self.connect.setFont(font) self.connect.setObjectName("connect") self.label = QtWidgets.QLabel(self.Connect_box) self.label.setGeometry(QtCore.QRect(10, 30, 31, 21)) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.label.setFont(font) self.label.setObjectName("label") self.Mode_box = QtWidgets.QGroupBox(self.centralwidget) self.Mode_box.setGeometry(QtCore.QRect(200, 10, 481, 121)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.Mode_box.setFont(font) self.Mode_box.setObjectName("Mode_box") self.Start = QtWidgets.QPushButton(self.Mode_box) self.Start.setGeometry(QtCore.QRect(10, 40, 101, 51)) font = QtGui.QFont() font.setPointSize(9) font.setBold(False) font.setWeight(50) self.Start.setFont(font) self.Start.setObjectName("Start") self.Stop = QtWidgets.QPushButton(self.Mode_box) self.Stop.setGeometry(QtCore.QRect(130, 40, 101, 51)) font = QtGui.QFont() font.setPointSize(9) font.setBold(False) font.setWeight(50) self.Stop.setFont(font) self.Stop.setObjectName("Stop") self.Reset = QtWidgets.QPushButton(self.Mode_box) self.Reset.setGeometry(QtCore.QRect(250, 40, 101, 51)) font = QtGui.QFont() font.setPointSize(9) font.setBold(False) font.setWeight(50) self.Reset.setFont(font) self.Reset.setObjectName("Reset") self.draw_graph = QtWidgets.QPushButton(self.Mode_box) self.draw_graph.setGeometry(QtCore.QRect(370, 40, 101, 51)) font = QtGui.QFont() font.setPointSize(10) font.setBold(False) font.setWeight(50) self.draw_graph.setFont(font) self.draw_graph.setObjectName("draw_graph") self.PIDStatus_box = QtWidgets.QGroupBox(self.centralwidget) self.PIDStatus_box.setGeometry(QtCore.QRect(680, 10, 411, 121)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.PIDStatus_box.setFont(font) self.PIDStatus_box.setObjectName("PIDStatus_box") self.label_6 = QtWidgets.QLabel(self.PIDStatus_box) self.label_6.setGeometry(QtCore.QRect(20, 30, 31, 31)) font = QtGui.QFont() font.setFamily("MS Shell Dlg 2") font.setPointSize(10) font.setBold(False) font.setWeight(50) self.label_6.setFont(font) self.label_6.setObjectName("label_6") self.Kp_data = QtWidgets.QTextEdit(self.PIDStatus_box) self.Kp_data.setGeometry(QtCore.QRect(60, 30, 71, 31)) font = QtGui.QFont() font.setBold(False) font.setWeight(50) self.Kp_data.setFont(font) self.Kp_data.setObjectName("Kp_data") self.label_7 = QtWidgets.QLabel(self.PIDStatus_box) self.label_7.setGeometry(QtCore.QRect(20, 80, 31, 31)) font = QtGui.QFont() font.setFamily("MS Shell Dlg 2") font.setPointSize(10) font.setBold(False) font.setWeight(50) self.label_7.setFont(font) self.label_7.setObjectName("label_7") self.Ki_data = QtWidgets.QTextEdit(self.PIDStatus_box) self.Ki_data.setGeometry(QtCore.QRect(60, 80, 71, 31)) font = QtGui.QFont() font.setBold(False) font.setWeight(50) self.Ki_data.setFont(font) self.Ki_data.setObjectName("Ki_data") self.label_8 = QtWidgets.QLabel(self.PIDStatus_box) self.label_8.setGeometry(QtCore.QRect(190, 30, 31, 31)) font = QtGui.QFont() font.setFamily("MS Shell Dlg 2") font.setPointSize(10) font.setBold(False) font.setWeight(50) self.label_8.setFont(font) self.label_8.setObjectName("label_8") self.Kd_data = QtWidgets.QTextEdit(self.PIDStatus_box) self.Kd_data.setGeometry(QtCore.QRect(230, 30, 71, 31)) font = QtGui.QFont() font.setBold(False) font.setWeight(50) self.Kd_data.setFont(font) self.Kd_data.setObjectName("Kd_data") self.label_9 = QtWidgets.QLabel(self.PIDStatus_box) self.label_9.setGeometry(QtCore.QRect(160, 80, 71, 31)) font = QtGui.QFont() font.setFamily("MS Shell Dlg 2") font.setPointSize(10) font.setBold(False) font.setWeight(50) self.label_9.setFont(font) self.label_9.setObjectName("label_9") self.Setpoint_data = QtWidgets.QTextEdit(self.PIDStatus_box) self.Setpoint_data.setGeometry(QtCore.QRect(230, 80, 71, 31)) font = QtGui.QFont() font.setBold(False) font.setWeight(50) self.Setpoint_data.setFont(font) self.Setpoint_data.setObjectName("Setpoint_data") self.send_PID = QtWidgets.QPushButton(self.PIDStatus_box) self.send_PID.setGeometry(QtCore.QRect(320, 80, 81, 31)) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.send_PID.setFont(font) self.send_PID.setObjectName("send_PID") self.get_PID = QtWidgets.QPushButton(self.PIDStatus_box) self.get_PID.setGeometry(QtCore.QRect(320, 30, 81, 31)) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.get_PID.setFont(font) self.get_PID.setObjectName("get_PID") self.Graph_box = QtWidgets.QGroupBox(self.centralwidget) self.Graph_box.setGeometry(QtCore.QRect(10, 130, 761, 401)) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.Graph_box.setFont(font) self.Graph_box.setObjectName("Graph_box") self.tabWidget = QtWidgets.QTabWidget(self.Graph_box) self.tabWidget.setGeometry(QtCore.QRect(0, 20, 761, 381)) self.tabWidget.setObjectName("tabWidget") self.Velocity_tab = QtWidgets.QWidget() self.Velocity_tab.setObjectName("Velocity_tab") self.Velocity_graph = PlotWidget(self.Velocity_tab) self.Velocity_graph.setGeometry(QtCore.QRect(10, 10, 741, 331)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.Velocity_graph.sizePolicy().hasHeightForWidth()) self.Velocity_graph.setSizePolicy(sizePolicy) self.Velocity_graph.setObjectName("Velocity_graph") self.tabWidget.addTab(self.Velocity_tab, "") self.Position_tab = QtWidgets.QWidget() self.Position_tab.setObjectName("Position_tab") self.Position_graph = PlotWidget(self.Position_tab) self.Position_graph.setGeometry(QtCore.QRect(10, 10, 741, 331)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.Position_graph.sizePolicy().hasHeightForWidth()) self.Position_graph.setSizePolicy(sizePolicy) self.Position_graph.setObjectName("Position_graph") self.tabWidget.addTab(self.Position_tab, "") self.groupBox_10 = QtWidgets.QGroupBox(self.centralwidget) self.groupBox_10.setGeometry(QtCore.QRect(770, 130, 321, 311)) font = QtGui.QFont() font.setFamily("MS Shell Dlg 2") font.setPointSize(10) font.setBold(True) font.setWeight(75) self.groupBox_10.setFont(font) self.groupBox_10.setObjectName("groupBox_10") self.re_se_data = QtWidgets.QTextBrowser(self.groupBox_10) self.re_se_data.setEnabled(True) self.re_se_data.setGeometry(QtCore.QRect(10, 20, 301, 241)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.re_se_data.sizePolicy().hasHeightForWidth()) self.re_se_data.setSizePolicy(sizePolicy) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.re_se_data.setFont(font) self.re_se_data.setObjectName("re_se_data") self.testsend = QtWidgets.QTextEdit(self.groupBox_10) self.testsend.setGeometry(QtCore.QRect(10, 270, 231, 31)) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.testsend.setFont(font) self.testsend.setObjectName("testsend") self.send = QtWidgets.QPushButton(self.groupBox_10) self.send.setGeometry(QtCore.QRect(250, 270, 61, 31)) font = QtGui.QFont() font.setPointSize(8) font.setBold(False) font.setWeight(50) self.send.setFont(font) self.send.setObjectName("send") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.ser = serial.Serial() self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(0) #connect serial self.connect.clicked.connect(self.clickedCONNECT) #enter mode self.Start.clicked.connect(self.clickedStart) self.Stop.clicked.connect(self.clickedStop) self.Reset.clicked.connect(self.clickedReset) #draw graph self.draw_graph.clicked.connect(self.clickeddrawgraph) #set up Position_graph self.Position_graph.setBackground('w') self.Position_graph.showGrid(x=True, y=True) self.Position_graph.setYRange(Y_min, Y_max, padding=0) self.Position_graph.setMouseEnabled(x=False, y=False) #set up Velocity_graph self.Velocity_graph.setBackground('w') self.Velocity_graph.showGrid(x=True, y=True) self.Velocity_graph.setYRange(Y_min, Y_max, padding=0) self.Velocity_graph.setMouseEnabled(x=False, y=False) #get PID status self.get_PID.clicked.connect(self.clickedgetPID) #transmit data # self.send.clicked.connect(self.clickedSEND) self.send_PID.clicked.connect(self.clickedsendPID) #set time for recive function self.timer_getdata = QtCore.QTimer() self.timer_getdata.setInterval(100) self.timer_getdata.timeout.connect(self.recive) #set time run system self.timer_run = QtCore.QTimer() self.timer_run.setInterval(1500) self.timer_run.timeout.connect(self.clickedCONNECT) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.Connect_box.setTitle(_translate("MainWindow", "Connect")) self.COM.setCurrentText(_translate("MainWindow", "COM1")) self.COM.setItemText(0, _translate("MainWindow", "COM1")) self.COM.setItemText(1, _translate("MainWindow", "COM2")) self.COM.setItemText(2, _translate("MainWindow", "COM3")) self.COM.setItemText(3, _translate("MainWindow", "COM4")) self.COM.setItemText(4, _translate("MainWindow", "COM5")) self.COM.setItemText(5, _translate("MainWindow", "COM6")) self.connect.setText(_translate("MainWindow", "CONNECT")) self.label.setText(_translate("MainWindow", "COM:")) self.Mode_box.setTitle(_translate("MainWindow", "Mode")) self.Start.setText(_translate("MainWindow", "START")) self.Stop.setText(_translate("MainWindow", "STOP")) self.Reset.setText(_translate("MainWindow", "RESET")) self.draw_graph.setText(_translate("MainWindow", "DRAW")) self.PIDStatus_box.setTitle(_translate("MainWindow", "PID Status")) self.label_6.setText(_translate("MainWindow", "Kp:")) self.Kp_data.setHtml( _translate( "MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>" )) self.label_7.setText(_translate("MainWindow", "Ki:")) self.Ki_data.setHtml( _translate( "MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>" )) self.label_8.setText(_translate("MainWindow", "Kd:")) self.Kd_data.setHtml( _translate( "MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>" )) self.label_9.setText(_translate("MainWindow", "Setpoint:")) self.Setpoint_data.setHtml( _translate( "MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>" )) self.send_PID.setText(_translate("MainWindow", "Send PID")) self.get_PID.setText(_translate("MainWindow", "Get PID")) self.Graph_box.setTitle(_translate("MainWindow", "Graph")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Velocity_tab), _translate("MainWindow", "Velocity")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Position_tab), _translate("MainWindow", "Position")) self.groupBox_10.setTitle( _translate("MainWindow", "Received/Send data")) self.re_se_data.setHtml( _translate( "MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n" "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;\"><br /></p></body></html>" )) self.send.setText(_translate("MainWindow", "SEND")) #disable button, box self.Start.setEnabled(False) self.Stop.setEnabled(False) self.Reset.setEnabled(False) self.testsend.setEnabled(False) self.send.setEnabled(False) self.re_se_data.setEnabled(False) self.send_PID.setEnabled(False) # self.draw_graph.setEnabled(False) def clickedCONNECT(self): global comconnect, ser, i NameCOM = self.COM.currentText() try: if (comconnect == False): self.ser = serial.Serial(NameCOM, 115200, timeout=2.5) self.COM.setEnabled(False) self.Start.setEnabled(True) self.Stop.setEnabled(True) self.Reset.setEnabled(True) self.re_se_data.setEnabled(True) self.testsend.setEnabled(True) self.send.setEnabled(True) self.send_PID.setEnabled(True) self.draw_graph.setEnabled(False) self.connect.setText('DISCONNECT') self.connect.setStyleSheet('QPushButton {color: red;}') self.re_se_data.append('Serial port ' + NameCOM + ' opened') self.timer_getdata.start() comconnect = True else: self.COM.setEnabled(True) self.ser.close() self.Start.setEnabled(False) self.Stop.setEnabled(False) self.Reset.setEnabled(False) self.re_se_data.setEnabled(False) self.testsend.setEnabled(False) self.send.setEnabled(False) self.send_PID.setEnabled(False) self.draw_graph.setEnabled(True) self.connect.setText('CONNECT') self.connect.setStyleSheet('QPushButton {color: green;}') self.re_se_data.append('Serial port ' + NameCOM + ' closed') self.timer_getdata.stop() self.timer_run.stop() comconnect = False i = 0 except IOError: if (comconnect == False): self.re_se_data.append('Serial port ' + NameCOM + ' opening error') else: self.re_se_data.append('Serial port ' + NameCOM + ' closing error') def clickedStart(self): self.re_se_data.append('Motor is runing') strs_tmp = ['0', '0', '\n'] Startdata_send = ' '.join(strs_tmp) self.ser.write(Startdata_send.encode()) #self.timer_run.start() def clickedStop(self): self.re_se_data.append('Motor stopped') strs_tmp = ['0', '1', '\n'] Stopdata_send = ' '.join(strs_tmp) self.ser.write(Stopdata_send.encode()) def clickedReset(self): global i, axis self.Position_graph.clear() self.Velocity_graph.clear() i = 1 axis = [] self.re_se_data.append('System reseted') strs_tmp = ['0', '2', '\n'] Resetdata_send = ' '.join(strs_tmp) self.ser.write(Resetdata_send.encode()) # def clickedSEND(self): # datasend = self.testsend.toPlainText() # self.re_se_data.append(datasend) # self.ser.write('2'.encode()) #recognize the data test # self.ser.write(datasend.encode()) def clickedgetPID(self): global Kp_send, Ki_send, Kd_send, Setpoint_send, PID_send Kp_send = self.Kp_data.toPlainText() Ki_send = self.Ki_data.toPlainText() Kd_send = self.Kd_data.toPlainText() Setpoint_send = self.Setpoint_data.toPlainText() strs_tmp = ['1', Kp_send, Ki_send, Kd_send, Setpoint_send, '\n'] PID_send = ' '.join(strs_tmp) def clickedsendPID(self): global Kp_send, Ki_send, Kd_send, Setpoint_send, PID_send self.ser.write(PID_send.encode()) def recive(self): global axis, ser, i bytetoread = self.ser.inWaiting() try: if bytetoread > 0: receive_data = self.ser.read(bytetoread) axis = receive_data.split() axis_Velocity[i] = int(str(axis[0], 'UTF-8')) axis_Position[i] = int(str(axis[1], 'UTF-8')) self.re_se_data.append(str(axis[0], 'UTF-8')) self.re_se_data.append(str(axis[1], 'UTF-8')) i += 1 except: self.re_se_data.append('bug roi con ga') def clickeddrawgraph(self): global axis_Position, axis_Velocity pen = pg.mkPen(color=(255, 0, 0), width=3) self.Velocity_graph.plot(time, axis_Velocity, pen=pen) self.Position_graph.plot(time, axis_Position, pen=pen)
class SmartScanGUI(QtGui.QWidget): # oh god i'm so sorry. don't listen to him; he's never sorry. def __init__(self): QtGui.QWidget.__init__(self) self.setLayout(QtGui.QHBoxLayout()) # a dict to store data self.dataMatrix = {} self.refData = {} ########################################## create a plot and associated widget ########################################################### self.plotWidget = PlotWidget() self.layout().addWidget(self.plotWidget,1) def xYPlot(plotWidget,x,y,yerr=None,xerr=None,color='w',name='Current'): thisPlot = plotWidget.plot(x,y,pen=mkPen(color,width=2)) plotWidget.addItem( ErrorBarItem( x=np.asarray(x), y=np.asarray(y), top=np.asarray(yerr) if yerr is not None else None, bottom=np.asarray(yerr) if yerr is not None else None, left=np.asarray(xerr) if xerr is not None else None, right=np.asarray(xerr) if xerr is not None else None, beam=.05, pen=mkPen(color) ) ) # method for updating plot with new data (plot has to be cleared first) def updatePlot(): self.plotWidget.clear() for name, rData in self.refData.iteritems(): xYPlot( self.plotWidget, rData['data'][0], rData['data'][1], yerr=rData['data'][2], color=rData['color'], name=name ) if len(self.dataMatrix.keys()) >= 1: for xVal, yValues in self.dataMatrix.items(): if xVal in self.xVals: oldMean = self.yVals[self.xVals.index(xVal)] thisMean = np.mean(yValues) newMean = (oldMean+thisMean)/2. self.yVals[self.xVals.index(xVal)] = newMean newErr = np.std(yValues)/np.sqrt(len(yValues)) self.errVals[self.xVals.index(xVal)] = newErr else: self.xVals.append(xVal) mean = np.mean(yValues) self.yVals.append(mean) err = np.std(yValues)/np.sqrt(len(yValues)) self.errVals.append(err) xYPlot(self.plotWidget,self.xVals,self.yVals,yerr=self.errVals) ############################################## configure a control panel layout ######################################################## cpLayout = QtGui.QVBoxLayout() self.layout().addLayout(cpLayout) # configure the output widget outputPane = QtGui.QTabWidget() cpLayout.addWidget(LabelWidget('output',outputPane)) @inlineCallbacks def onInit(): ############################################################# VOLTMETER OUTPUT ########################################################### # add volt meter to scan output if DEBUG: vmURL = TEST_VOLTMETER_SERVER else: vmURL = VOLTMETER_SERVER vmProtocol = yield getProtocol(vmURL) vmClient = VoltMeterClient(vmProtocol) vmWidget = VoltMeterOutputWidget(vmClient) outputPane.addTab(vmWidget,'voltmeter') ############################################################# BEGIN INPUTS ########################################################### # configure the input widget inputPane = QtGui.QTabWidget() inputPane.setTabPosition(inputPane.West) cpLayout.addWidget(LabelWidget('input',inputPane),1) # algorithm for scan inputs is: # 0. check to see if input is disabled # 1. create client for server from protocol object # 2. create combo widget to hold interval and list widgets # 3. create interval widget using client object, add to combo # 4. same for list widget # 5. add combo widget to base combo widget (resulting in 2-D tab widget) ############################################################# MANUAL INPUT ########################################################### class ManualInputWidget(QtGui.QWidget): def __init__(self,parentWidget): QtGui.QWidget.__init__(self) self.parentWidget = parentWidget self.done = False def initScan(self): return def checkIfDone(self): return def next(self): result, valid = QtGui.QInputDialog.getDouble( self.parentWidget, 'next x value', 'enter next x value', decimals=6 ) if valid: return result else: return None def cancel(self): return inputPane.addTab( ManualInputWidget(self), 'manual' ) ############################################################# MANUAL SCAN INPUT ########################################################### class ManualScanInputWidget(InputWidget): def __init__(self,parent): spinBoxProps = { 'rangeMin':-100000, 'rangeMax':100000, 'stepMin':.000001, 'stepMax':100000, 'startInit':0, 'stopInit':1, 'stepSizeInit':.1 } def setPosition(position): msgBox = QtGui.QMessageBox() msgBox.setText("next position:\t"+str(position)) msgBox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) msgBox.setDefaultButton(QtGui.QMessageBox.Ok) ret = msgBox.exec_() if ret == QtGui.QMessageBox.Ok: return position elif ret == QtGui.QMessageBox.Cancel: return None InputWidget.__init__(self,lambda(x):None,setPosition,spinBoxProperties = spinBoxProps) inputPane.addTab( ManualScanInputWidget(self), 'manual scan' ) ############################################################# STEPPER MOTOR INPUTS ########################################################### # load in the stepper motor names from config.steppermotor import KDP, BBO, PDL, LID, POL # get stepper motor protocol (how to communicate to stepper motor server) smProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) # define a chunked (cancellable) client for each stepper motor stepperMotorsClients = {} for stepperMotorName in (KDP,BBO,PDL,LID,POL): stepperMotorsClients[stepperMotorName] = ChunkedStepperMotorClient(smProtocol,stepperMotorName) # define an input widget for each stepper motor, each add to input pane for smID,smClient in stepperMotorsClients.items(): spinBoxProps = { 'rangeMin':-100000, 'rangeMax':100000, 'stepMin':1, 'stepMax':100000, 'startInit':0, 'stopInit':100, 'stepSizeInit':1 } thisInputWidget = InputWidget( smClient.getPosition, smClient.setPosition, cancelCommand = smClient.cancel, spinBoxProperties = spinBoxProps ) inputPane.addTab( thisInputWidget, smID ) ############################################################# WAVELENGTH SERVER INPUT ########################################################### ''' # add wavelength client to scan input wlProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) wlClient = WavelengthClient(wlProtocol) spinBoxProps = { 'rangeMin':24100, 'rangeMax':25000, 'stepMin':.01, 'stepMax':900, 'startInit':24200, 'stopInit':24220, 'stepSizeInit':1 } wlInputWidget = InputWidget( wlClient.getWavelength, wlClient.setWavelength, cancelCommand = wlClient.cancelWavelengthSet, spinBoxProperties = spinBoxProps ) inputPane.addTab( wlInputWidget, 'wl' ) ''' ############################################################# POLARIZER SERVER INPUT ########################################################### ''' # get protocol polProtocol = yield getProtocol( TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER ) # define the client polClient = PolarizerClient(polProtocol) # set limits on spinboxes spinBoxProps = { 'rangeMin':-720, 'rangeMax':720, 'stepMin':.01, 'stepMax':720, 'startInit':0, 'stopInit':90, 'stepSizeInit':5 } polInputWidget = InputWidget( polClient.getAngle, polClient.setAngle, cancelCommand = polClient.cancelAngleSet, spinBoxProperties = spinBoxProps ) inputPane.addTab( polInputWidget, 'pol' ) ''' ############################################################# DDG INPUTS ########################################################### # load in the delay generator names from config.delaygenerator import MAV_PUMP_LAMP, MAV_PUMP_QSW, MAV_PROBE_LAMP, MAV_PROBE_QSW, MAV_NOZZLE # load in the delay generator limits from config.delaygenerator import MIN_DELAY, MAX_DELAY, DELAY_RES # get the delay generator protocol dgProtocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER ) dgClient = DelayGeneratorClient(dgProtocol) # define an input widget for each delay generator, each add to input pane for dgName in (MAV_PUMP_LAMP, MAV_PUMP_QSW, MAV_PROBE_LAMP, MAV_PROBE_QSW, MAV_NOZZLE): spinBoxProps = { 'rangeMin':MIN_DELAY, 'rangeMax':MAX_DELAY, 'stepMin':DELAY_RES, 'stepMax':MAX_DELAY-MIN_DELAY, 'startInit':1, 'stopInit':1001, 'stepSizeInit':10 } # because there is one DG client for all DGs (unlike SM client), we use partial to map the client\ # commands to individual DGs so that we preserve as much of the same structure as possible. thisInputWidget = InputWidget( partial(dgClient.getDelay,dgName), partial(dgClient.setPartnerDelay,dgName), spinBoxProperties = spinBoxProps ) inputPane.addTab( thisInputWidget, dgName ) ############################################################# END INPUTS ########################################################### ############################################################# SCANNING ########################################################### #define fundamental scan logic: # 1: ask independent variable to change, wait # 2: measure dependent # 3: perform onStep task with x-y pair (e.g. update plot) class Scan: def __init__(self,inputWidget,outputWidget,onStepFunct,repeats=1,plotWidget=None): self.input = inputWidget self.output = outputWidget self.onStep = onStepFunct self.output.plot = plotWidget self.repeatTotal = repeats self.activeRepeat = 1 self.startScan() def startScan(self): if len(self.input.scanValues) == 0: self.input.initScan() self.output.initScan() self.paused = False self.done = False self.loop() @inlineCallbacks def loop(self): # pause if paused if self.paused: resumeCancelDialog = QtGui.QMessageBox() resumeCancelDialog.setText("the scan has been paused.") resumeCancelDialog.setInformativeText("do you want to cancel the scan?") resumeCancelDialog.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) resumeCancelDialog.setDefaultButton(QtGui.QMessageBox.No) option = resumeCancelDialog.exec_() if option == QtGui.QMessageBox.Yes: #quit the scan self.cancel() return if option == QtGui.QMessageBox.No: #resume the scan self.resume() while self.paused: QtGui.QApplication.processEvents() sleep(.1) # check if done by asking input self.input.checkIfDone() inputDone = self.input.done # if done, finish to clean up if inputDone: self.finish() # if not done, continue onto next point & measure if not inputDone: inputData = yield self.input.next() if inputData == None: yield self.cancel() return else: self.output.setPlotterXVal(inputData) outputDataDefer = self.output.startAcquisition() outputData = yield outputDataDefer yield self.onStep(inputData,outputData) self.loop() def pause(self): self.paused = True def resume(self): self.paused = False def cancel(self): self.done = True self.input.cancel() self.output.cancel() scanToggleClicked() @inlineCallbacks def finish(self): if self.activeRepeat == self.repeatTotal: self.done = True yield self.input.cancel() self.output.cancel() scanToggleClicked() else: self.activeRepeat += 1 if self.activeRepeat % 2 == 0: self.input.initFlipScan() else: self.input.initScan() self.startScan() # define what to do after values are acquired at a position def onStepped(input,output): # unpack scan step data position, output = input, output if position == None or output == None: return else: # update data array if position not in self.dataMatrix.keys(): self.dataMatrix[position] = [] for value in output: self.dataMatrix[position].append(value) # update plot updatePlot() # define scanning start/pause/cancel logic def scanToggleClicked(): if self.scanning: #currently scanning so check if the scan is done, if not this was a pause if not self.thisScan.done: #pause the scan, pop resume/cancel dialog self.thisScan.pause() else: self.scanning = False scanToggleButton.setText("start") return if not self.scanning: #not currently scanning, so start the scan self.scanning = True #gather the agents (classes with specific methods) that progress scan and measure values inputAgent = inputPane.currentWidget() outputAgent = outputPane.currentWidget() updateAgent = onStepped #dump whatever data is in the matrix, prepare the plot for xVal in self.dataMatrix.keys(): del self.dataMatrix[xVal] # clear the lists that the plot uses to plot self.xVals = [] self.yVals = [] self.errVals = [] updatePlot() self.plotWidget.enableAutoRange() #define the scan, which automatically starts it numToRepeat = self.repeatSpinBox.value() self.thisScan = Scan(inputAgent, outputAgent, updateAgent, numToRepeat, self.plotWidget) #rename our button so users know about the other half of this function scanToggleButton.setText("pause/cancel") return self.scanning = False # set up the GUI to have the scan start/pause/cancel button and repeat spinbox scanPane = QtGui.QHBoxLayout() scanToggleButton = QtGui.QPushButton("start") scanToggleButton.clicked.connect(scanToggleClicked) scanPane.addWidget(scanToggleButton) self.repeatSpinBox = QtGui.QSpinBox() self.repeatSpinBox.setRange(1,10000) self.repeatSpinBox.setValue(1) scanPane.addWidget(self.repeatSpinBox) cpLayout.addWidget(LabelWidget('scan',scanPane)) ############################################################# LOAD FUNCTIONS ########################################################### refLayout = QtGui.QHBoxLayout() def onLoadClicked(): dir, filePrefix = filenameGen() dir = join(POOHDATAPATH,dir) refFileName = QtGui.QFileDialog.getOpenFileName(self,'select file', dir,"CSV Files (*.csv)") rData = np.loadtxt(open(refFileName[0],"rb"),delimiter=",") name = refFileName[0].rpartition('/')[2] color = QtGui.QColorDialog.getColor() if 'matrix' in refFileName[0]: xVals = rData[:,0] yVals = [] errVals = [] for rowNum in range(len(xVals)): thisYList = rData[rowNum,1:] yVals.append(np.mean(thisYList)) errVals.append(np.std(thisYList)/np.sqrt(len(thisYList))) self.refData[name] = { 'color': color, 'data': [xVals, yVals, errVals] } else: self.refData[name] = { 'color': color, 'data': [rData[:,0], rData[:,1], rData[:,2]] } updatePlot() loadButton = QtGui.QPushButton('load') loadButton.clicked.connect(onLoadClicked) refLayout.addWidget(SqueezeRow(loadButton)) def onClearClicked(): for refs in self.refData.keys(): del self.refData[refs] updatePlot() clearButton = QtGui.QPushButton('clear all') clearButton.clicked.connect(onClearClicked) refLayout.addWidget(SqueezeRow(clearButton)) cpLayout.addWidget(LabelWidget('reference',refLayout)) ############################################################# SAVE FUNCTIONS ########################################################### saveLayout = QtGui.QHBoxLayout() def onSaveRawClicked(): dataType = np.dtype(np.float32) orderedDataDict = OrderedDict(sorted(self.dataMatrix.items())) data = np.reshape(np.asarray(orderedDataDict.keys(),dtype=dataType),(len(orderedDataDict.keys()),1)) #just x values as a column yVals = np.asarray(orderedDataDict.values(),dtype=dataType) data = np.hstack((data,yVals)) saveFile(data,'matrix') saveRawButton = QtGui.QPushButton('save (raw)') saveRawButton.clicked.connect(onSaveRawClicked) saveLayout.addWidget(SqueezeRow(saveRawButton)) def onSaveStatsClicked(): xData = self.dataMatrix.keys() yData = [] errData = [] for rawValues in self.dataMatrix.values(): yData.append(np.mean(rawValues)) errData.append(np.std(rawValues)/np.sqrt(len(rawValues))) data = np.asarray([xData, yData, errData], dtype=np.dtype(np.float32)) saveFile(np.transpose(data),'stats') saveStatsButton = QtGui.QPushButton('save (stats)') saveStatsButton.clicked.connect(onSaveStatsClicked) saveLayout.addWidget(SqueezeRow(saveStatsButton)) def saveFile(dataToSave,prefix): dir, filePrefix = filenameGen() dir = join(POOHDATAPATH,dir) checkPath(dir) subDir = QtGui.QFileDialog.getExistingDirectory(self,'select folder', dir) desc, valid = QtGui.QInputDialog.getText(self, 'enter file description','description' ) if not valid: desc = None else: saveCSV(dataToSave, subDir=subDir, description=prefix+'_'+desc) cpLayout.addWidget(LabelWidget('save',saveLayout)) onInit() def closeEvent(self, event): if reactor.running: reactor.stop() event.accept()
class VNAPowerSweepWidget(VNAFitWidget): def __init__(self): super(VNAPowerSweepWidget, self).__init__() self.power_start = QDoubleSpinBox() self.power_stop = QDoubleSpinBox() self.power_step = QDoubleSpinBox() self.form_layout.addRow("Power Start", self.power_start) self.form_layout.addRow("Power Stop", self.power_stop) self.form_layout.addRow("Power Stop", self.power_step) self.start_sweep_button = QPushButton("Start Sweep") self.start_sweep_button.clicked.connect(self.start_sweep) self.button_layout.addWidget(self.start_sweep_button) self.traces_plot = ImageView() self.plot_layout.addWidget(self.traces_plot) self.qints_plot = PlotWidget() self.plot_layout.addWidget(self.qints_plot) self.current_power = None self.traces = [] self.qints = [] def start_sweep(self): powers = arange(self.power_start.value(), self.power_stop.value(), self.power_step.value()) vna = self.get_vna() for i, power in enumerate(powers): self.current_power = power vna.set_power(power) self.grab_trace() self.fit_trace() self.save_trace() self.traces.append(self.mags) self.traces_plot.setImage(array(self.traces)) self.qints.append(self.fit_params['qint'].value) self.qints_plot.clear() self.qints_plot.plot(self.powers[:i], self.qints) self.current_power = None g = self.get_h5group() g['freqs'] = vna.get_xaxis() g['powers'] = powers g['qints'] = self.qints g['traces'] = self.traces dataserver_helpers.set_scale(g, 'powers', 'qints') dataserver_helpers.set_scale(g, 'powers', 'traces') dataserver_helpers.set_scale(g, 'powers', 'freqs', dim=1) def get_h5group(self): if self.current_power is not None: dataset = str(self.dataset_edit.text()) self.dataset_edit.setText(dataset + "/%.1f" % self.current_power) g = super(VNAPowerSweepWidget, self).get_h5group() self.dataset_edit.setText(dataset) else: return super(VNAPowerSweepWidget, self).get_h5group() def grab_trace(self): super(VNAPowerSweepWidget, self).grab_trace() power_array = self.get_h5group(use_power_child=False)
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 UiMainWindow(object): def setupUi(self, MainWindow, function): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.data = [] self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.graph = PlotWidget(self.centralwidget) self.graph.setGeometry(QtCore.QRect(20, 20, 371, 251)) self.graph.setObjectName("graph") self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget) self.stackedWidget.setGeometry(QtCore.QRect(420, 20, 331, 281)) self.stackedWidget.setObjectName("stackedWidget") self.rectangles = QtWidgets.QWidget() self.rectangles.setObjectName("rectangles") self.formLayoutWidget = QtWidgets.QWidget(self.rectangles) self.formLayoutWidget.setGeometry(QtCore.QRect(30, 30, 271, 276)) self.formLayoutWidget.setObjectName("formLayoutWidget") self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget) self.formLayout.setContentsMargins(0, 0, 0, 0) self.formLayout.setObjectName("formLayout") self.rect_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_label.setObjectName("rect_label") self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.rect_label) self.rect_left = QtWidgets.QLineEdit(self.formLayoutWidget) self.rect_left.setObjectName("rect_left") self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.rect_left) self.rect_right = QtWidgets.QLineEdit(self.formLayoutWidget) self.rect_right.setObjectName("rect_right") self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.rect_right) self.rect_min = QtWidgets.QLineEdit(self.formLayoutWidget) self.rect_min.setObjectName("rect_min") self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.rect_min) self.rect_max = QtWidgets.QLineEdit(self.formLayoutWidget) self.rect_max.setObjectName("rect_max") self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.rect_max) self.rect_accuracy = QtWidgets.QLineEdit(self.formLayoutWidget) self.rect_accuracy.setObjectName("rect_accuracy") self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.rect_accuracy) self.rect_type = QtWidgets.QComboBox(self.formLayoutWidget) self.rect_type.setObjectName("rect_type") self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.rect_type) self.rect_type.addItem("Левые") self.rect_type.addItem("Правые") self.rect_type.addItem("Середина") self.rect_left_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_left_label.setObjectName("rect_left_label") self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.rect_left_label) self.rect_right_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_right_label.setObjectName("rect_right_label") self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.rect_right_label) self.rect_min_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_min_label.setObjectName("rect_min_label") self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.rect_min_label) self.rect_max_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_max_label.setObjectName("rect_max_label") self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.rect_max_label) self.rect_accuracy_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_accuracy_label.setObjectName("rect_accuracy_label") self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.rect_accuracy_label) self.rect_type_label = QtWidgets.QLabel(self.formLayoutWidget) self.rect_type_label.setObjectName("rect_type_label") self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.rect_type_label) self.start_rect_label = QtWidgets.QPushButton(self.formLayoutWidget) self.start_rect_label.setObjectName("start_rect_label") self.formLayout.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.start_rect_label) self.stackedWidget.addWidget(self.rectangles) self.trapeze = QtWidgets.QWidget() self.trapeze.setObjectName("trapeze") self.formLayoutWidget_2 = QtWidgets.QWidget(self.trapeze) self.formLayoutWidget_2.setGeometry(QtCore.QRect(30, 30, 271, 237)) self.formLayoutWidget_2.setObjectName("formLayoutWidget_2") self.formLayout_3 = QtWidgets.QFormLayout(self.formLayoutWidget_2) self.formLayout_3.setContentsMargins(0, 0, 0, 0) self.formLayout_3.setObjectName("formLayout_3") self.start_trapeze_label = QtWidgets.QPushButton( self.formLayoutWidget_2) self.start_trapeze_label.setObjectName("start_trapeze_label") self.formLayout_3.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.start_trapeze_label) self.trapeze_label = QtWidgets.QLabel(self.formLayoutWidget_2) self.trapeze_label.setObjectName("trapeze_label") self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.trapeze_label) self.trapeze_right = QtWidgets.QLineEdit(self.formLayoutWidget_2) self.trapeze_right.setObjectName("trapeze_right") self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.trapeze_right) self.trapeze_left = QtWidgets.QLineEdit(self.formLayoutWidget_2) self.trapeze_left.setObjectName("trapeze_left") self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.trapeze_left) self.trapeze_left_label = QtWidgets.QLabel(self.formLayoutWidget_2) self.trapeze_left_label.setObjectName("trapeze_left_label") self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.trapeze_left_label) self.trapeze_right_label = QtWidgets.QLabel(self.formLayoutWidget_2) self.trapeze_right_label.setObjectName("trapeze_right_label") self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.trapeze_right_label) self.trapeze_accuracy = QtWidgets.QLineEdit(self.formLayoutWidget_2) self.trapeze_accuracy.setObjectName("trapeze_accuracy") self.formLayout_3.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.trapeze_accuracy) self.trapeze_min = QtWidgets.QLineEdit(self.formLayoutWidget_2) self.trapeze_min.setObjectName("trapeze_min") self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.trapeze_min) self.trapeze_min_label = QtWidgets.QLabel(self.formLayoutWidget_2) self.trapeze_min_label.setObjectName("trapeze_min_label") self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.trapeze_min_label) self.trapeze_max = QtWidgets.QLineEdit(self.formLayoutWidget_2) self.trapeze_max.setObjectName("trapeze_max") self.formLayout_3.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.trapeze_max) self.trapeze_max_label = QtWidgets.QLabel(self.formLayoutWidget_2) self.trapeze_max_label.setObjectName("trapeze_max_label") self.formLayout_3.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.trapeze_max_label) self.trapeze_accuracy_label = QtWidgets.QLabel(self.formLayoutWidget_2) self.trapeze_accuracy_label.setObjectName("trapeze_accuracy_label") self.formLayout_3.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.trapeze_accuracy_label) self.stackedWidget.addWidget(self.trapeze) self.simpson = QtWidgets.QWidget() self.simpson.setObjectName("simpson") self.formLayoutWidget_3 = QtWidgets.QWidget(self.simpson) self.formLayoutWidget_3.setGeometry(QtCore.QRect(30, 30, 271, 231)) self.formLayoutWidget_3.setObjectName("formLayoutWidget_3") self.formLayout_5 = QtWidgets.QFormLayout(self.formLayoutWidget_3) self.formLayout_5.setContentsMargins(0, 0, 0, 0) self.formLayout_5.setObjectName("formLayout_5") self.start_simpson_label = QtWidgets.QPushButton( self.formLayoutWidget_3) self.start_simpson_label.setObjectName("start_simpson_label") self.formLayout_5.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.start_simpson_label) self.simpson_label = QtWidgets.QLabel(self.formLayoutWidget_3) self.simpson_label.setObjectName("simpson_label") self.formLayout_5.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.simpson_label) self.simpson_left = QtWidgets.QLineEdit(self.formLayoutWidget_3) self.simpson_left.setObjectName("simpson_left") self.formLayout_5.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.simpson_left) self.simpson_right = QtWidgets.QLineEdit(self.formLayoutWidget_3) self.simpson_right.setObjectName("simpson_right") self.formLayout_5.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.simpson_right) self.simpson_min = QtWidgets.QLineEdit(self.formLayoutWidget_3) self.simpson_min.setObjectName("simpson_min") self.formLayout_5.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.simpson_min) self.simpson_max = QtWidgets.QLineEdit(self.formLayoutWidget_3) self.simpson_max.setObjectName("simpson_max") self.formLayout_5.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.simpson_max) self.simpson_accuracy = QtWidgets.QLineEdit(self.formLayoutWidget_3) self.simpson_accuracy.setObjectName("simpson_accuracy") self.formLayout_5.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.simpson_accuracy) self.simpson_left_label = QtWidgets.QLabel(self.formLayoutWidget_3) self.simpson_left_label.setObjectName("simpson_left_label") self.formLayout_5.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.simpson_left_label) self.simpson_right_label = QtWidgets.QLabel(self.formLayoutWidget_3) self.simpson_right_label.setObjectName("simpson_right_label") self.formLayout_5.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.simpson_right_label) self.simpson_min_label = QtWidgets.QLabel(self.formLayoutWidget_3) self.simpson_min_label.setObjectName("simpson_min_label") self.formLayout_5.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.simpson_min_label) self.simpson_max_label = QtWidgets.QLabel(self.formLayoutWidget_3) self.simpson_max_label.setObjectName("simpson_max_label") self.formLayout_5.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.simpson_max_label) self.simpson_accuracy_label = QtWidgets.QLabel(self.formLayoutWidget_3) self.simpson_accuracy_label.setObjectName("simpson_accuracy_label") self.formLayout_5.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.simpson_accuracy_label) self.stackedWidget.addWidget(self.simpson) self.table = QtWidgets.QTableView(self.centralwidget) self.table.setGeometry(QtCore.QRect(55, 341, 691, 211)) self.table.setObjectName("table") self.graph.showGrid(x=True, y=True) self.error = QtWidgets.QLabel(self.centralwidget) self.error.setGeometry(QtCore.QRect(300, 300, 270, 16)) self.error.setText("") self.error.setObjectName("error") self.save = QtWidgets.QPushButton(self.centralwidget) self.save.setGeometry(QtCore.QRect(150, 300, 121, 24)) self.save.setObjectName("save") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(630, 300, 121, 28)) self.pushButton.setObjectName("pushButton") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) self.function = function self.pushButton.clicked.connect(self.change_method) self.start_simpson_label.clicked.connect(self.simpson_init) self.start_rect_label.clicked.connect(self.rect_init) self.start_trapeze_label.clicked.connect(self.trapeze_init) self.save.clicked.connect(self.save_to_file) self.update_graph(-10, 10) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.rect_label.setText( _translate("MainWindow", "Метод прямоугольников")) self.rect_left_label.setText(_translate("MainWindow", "Левая граница")) self.rect_right_label.setText( _translate("MainWindow", "Правая граница")) self.rect_min_label.setText( _translate("MainWindow", "Минимум интервалов")) self.rect_max_label.setText( _translate("MainWindow", "Максимум интервалов")) self.rect_accuracy_label.setText(_translate("MainWindow", "Точность")) self.rect_type_label.setText(_translate("MainWindow", "Тип метода")) self.start_rect_label.setText(_translate("MainWindow", "Рассчитать")) self.start_trapeze_label.setText(_translate("MainWindow", "Рассчитать")) self.trapeze_label.setText(_translate("MainWindow", "Метод трапеций")) self.trapeze_left_label.setText( _translate("MainWindow", "Левая граница")) self.trapeze_right_label.setText( _translate("MainWindow", "Правая граница")) self.trapeze_min_label.setText( _translate("MainWindow", "Минимум интервалов")) self.trapeze_max_label.setText( _translate("MainWindow", "Максимум интервалов")) self.trapeze_accuracy_label.setText( _translate("MainWindow", "Точность")) self.start_simpson_label.setText(_translate("MainWindow", "Рассчитать")) self.simpson_label.setText(_translate("MainWindow", "Метод Симпсона")) self.simpson_left_label.setText( _translate("MainWindow", "Левая граница")) self.simpson_right_label.setText( _translate("MainWindow", "Правая граница")) self.simpson_min_label.setText( _translate("MainWindow", "Минимум интервалов")) self.simpson_max_label.setText( _translate("MainWindow", "Максимум интервалов")) self.simpson_accuracy_label.setText( _translate("MainWindow", "Точность")) self.save.setText(_translate("MainWindow", "Сохранить в файл")) self.pushButton.setText(_translate("MainWindow", "Сменить метод")) def update_graph(self, a, b): delta = abs(b - a) / 100 values = [] plots = [] for i in range(100): plots.append(a + i * delta) values.append(self.function(a + i * delta)) self.graph.clear() self.graph.plot(plots, values) def change_method(self): index = self.stackedWidget.currentIndex() if index > 1: index = 0 else: index = index + 1 self.stackedWidget.setCurrentIndex(index) def simpson_init(self): try: a = float(self.simpson_left.text()) b = float(self.simpson_right.text()) acc = float(self.simpson_accuracy.text()) min_intervals = float(self.simpson_min.text()) max_intervals = float(self.simpson_max.text()) if not validate_params(a, b, min_intervals, max_intervals): raise ValueError self.error.setText('') delta = abs(b - a) self.update_graph(a - delta * 0.1, b + delta * 0.1) data = imath.simpson(self.function, a, b, acc, min_intervals, max_intervals) self.data = data model = tablemodel.TableModel(data, ["Sum", "N"]) self.table.setModel(model) self.table.update() except ValueError: self.error.setText('Invalid params') except imath.RequirementException: self.error.setText("Convergence requirements faild") except imath.BadParamsExceptions: self.error.setText('Invalid params') def rect_init(self): try: a = float(self.rect_left.text()) b = float(self.rect_right.text()) acc = float(self.rect_accuracy.text()) min_intervals = float(self.rect_min.text()) max_intervals = float(self.rect_max.text()) if not validate_params(a, b, min_intervals, max_intervals): raise ValueError self.error.setText('') delta = abs(b - a) self.update_graph(a - delta * 0.1, b + delta * 0.1) if self.rect_type.currentIndex() == 0: data = imath.rectangles_left(self.function, a, b, acc, min_intervals, max_intervals) elif self.rect_type.currentIndex() == 1: data = imath.rectangles_right(self.function, a, b, acc, min_intervals, max_intervals) elif self.rect_type.currentIndex() == 2: data = imath.rectangles_middle(self.function, a, b, acc, min_intervals, max_intervals) self.data = data model = tablemodel.TableModel(data, ["Sum", "N"]) self.table.setModel(model) self.table.update() except ValueError: self.error.setText('Invalid params') except imath.RequirementException: self.error.setText("Convergence requirements faild") except imath.BadParamsExceptions: self.error.setText('Invalid params') def trapeze_init(self): try: a = float(self.trapeze_left.text()) b = float(self.trapeze_right.text()) acc = float(self.trapeze_accuracy.text()) min_intervals = float(self.trapeze_min.text()) max_intervals = float(self.trapeze_max.text()) if not validate_params(a, b, min_intervals, max_intervals): raise ValueError self.error.setText('') delta = abs(b - a) self.update_graph(a - delta * 0.1, b + delta * 0.1) data = imath.trapeze(self.function, a, b, acc, min_intervals, max_intervals) self.data = data model = tablemodel.TableModel(data, ["Sum", "N"]) self.table.setModel(model) self.table.update() except ValueError: self.error.setText("Invalid Params") except imath.RequirementException: self.error.setText("Convergence requirements faild") except imath.BadParamsExceptions: self.error.setText('Invalid params') def save_to_file(self): openfile = QtGui.QFileDialog.getOpenFileName(self, 'Open file')[0] f = open(openfile, 'w') data = self.data for d in data: f.write(','.join(list(map(str, d)))) f.close()
class PyQtGraphDataPlot(QWidget): limits_changed = Signal() def __init__(self, parent=None): super(PyQtGraphDataPlot, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.getPlotItem().addLegend() self._plot_widget.setBackground((255, 255, 255)) self._plot_widget.setXRange(0, 10, padding=0) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._plot_widget.getPlotItem().sigRangeChanged.connect( self.limits_changed) self.bins = 10 self.window = 100 self._curves = {} self._current_vline = None def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False): pen = mkPen(curve_color, width=1) # this adds the item to the plot and legend plot = self._plot_widget.plot(stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) self._curves[curve_id] = 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]) del self._curves[curve_id] self._update_legend() def _update_legend(self): # clear and rebuild legend (there is no remove item method for the legend...) self._plot_widget.clear() self._plot_widget.getPlotItem().legend.items = [] for curve in self._curves.values(): self._plot_widget.addItem(curve) if self._current_vline: self._plot_widget.addItem(self._current_vline) def redraw(self): pass def set_values(self, curve_id, data_x, data_y): curve = self._curves[curve_id] if len(data_y) > 0: y, x = numpy.histogram(data_y[-self.window:], self.bins) curve.setData(x, y) else: curve.clear() self._plot_widget.autoRange() def vline(self, x, color): if self._current_vline: self._plot_widget.removeItem(self._current_vline) self._current_vline = self._plot_widget.addLine(x=x, pen=color) def set_xlim(self, limits): # TODO: this doesn't seem to handle fast updates well self._plot_widget.setXRange(limits[0], limits[1], padding=0) def set_ylim(self, limits): self._plot_widget.setYRange(limits[0], limits[1], padding=0) def get_xlim(self): x_range, _ = self._plot_widget.viewRange() return x_range def get_ylim(self): _, y_range = self._plot_widget.viewRange() return y_range
class Ui_Op2(object): def setupUi(self, Op2): listChem = Equilibrium() Op2.setObjectName("Op2") Op2.resize(950, 640) Op2.setMinimumSize(QtCore.QSize(950, 640)) Op2.setMaximumSize(QtCore.QSize(950, 640)) Op2.setWindowIcon(QtGui.QIcon('images\Icone.jpg')) Op2.setFocusPolicy(QtCore.Qt.NoFocus) Op2.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) self.centralwidget = QtWidgets.QWidget(Op2) self.centralwidget.setObjectName("centralwidget") self.line = QtWidgets.QFrame(self.centralwidget) self.line.setGeometry(QtCore.QRect(0, -1, 951, 16)) self.line.setFrameShape(QtWidgets.QFrame.HLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.line_2 = QtWidgets.QFrame(self.centralwidget) self.line_2.setGeometry(QtCore.QRect(0, 470, 961, 20)) self.line_2.setFrameShape(QtWidgets.QFrame.HLine) self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) self.line_2.setObjectName("line_2") self.graphicPlot = QtWidgets.QPushButton(self.centralwidget) self.graphicPlot.setGeometry(QtCore.QRect(480, 520, 161, 51)) font = QtGui.QFont() font.setPointSize(11) font.setBold(True) font.setWeight(75) self.graphicPlot.setFont(font) self.graphicPlot.setObjectName("graphicPlot") self.graphics1 = PlotWidget(self.centralwidget) self.graphics1.setGeometry(QtCore.QRect(10, 10, 461, 401)) self.graphics1.setBackground('w') self.graphics1.showGrid(x=True, y=True) self.graphics1.setObjectName("graphics1") self.graphics2 = PlotWidget(self.centralwidget) self.graphics2.setGeometry(QtCore.QRect(480, 10, 461, 401)) self.graphics2.setBackground('w') self.graphics2.showGrid(x=True, y=True) self.graphics2.setObjectName("graphics2") self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) self.verticalLayoutWidget.setGeometry(QtCore.QRect(310, 520, 171, 51)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout( self.verticalLayoutWidget) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setObjectName("verticalLayout_2") self.pconst = QtWidgets.QRadioButton(self.verticalLayoutWidget) self.pconst.setEnabled(True) self.pconst.setCheckable(True) self.pconst.setChecked(False) self.pconst.setObjectName("pconst") self.verticalLayout_2.addWidget(self.pconst) self.tconst = QtWidgets.QRadioButton(self.verticalLayoutWidget) self.tconst.setChecked(True) self.tconst.setObjectName("tconst") self.verticalLayout_2.addWidget(self.tconst) self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget) self.horizontalLayoutWidget.setGeometry(QtCore.QRect( 310, 490, 331, 31)) self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget") self.horizontalLayout = QtWidgets.QHBoxLayout( self.horizontalLayoutWidget) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.horizontalLayout.setObjectName("horizontalLayout") spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.changeTextVar = QtWidgets.QLabel(self.horizontalLayoutWidget) font = QtGui.QFont() font.setPointSize(11) font.setBold(True) font.setWeight(75) self.changeTextVar.setFont(font) self.changeTextVar.setObjectName("changeTextVar") self.horizontalLayout.addWidget(self.changeTextVar) self.databox = QtWidgets.QLineEdit(self.horizontalLayoutWidget) font = QtGui.QFont() font.setPointSize(10) self.databox.setFont(font) self.databox.setValidator(QtGui.QDoubleValidator()) self.databox.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor)) self.databox.setToolTipDuration(1) self.databox.setObjectName("databox") self.horizontalLayout.addWidget(self.databox) self.changeTextUni = QtWidgets.QLabel(self.horizontalLayoutWidget) font = QtGui.QFont() font.setPointSize(11) font.setBold(True) font.setWeight(75) self.changeTextUni.setFont(font) self.changeTextUni.setObjectName("changeTextUni") self.horizontalLayout.addWidget(self.changeTextUni) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget) self.gridLayoutWidget.setGeometry(QtCore.QRect(260, 420, 431, 53)) self.gridLayoutWidget.setObjectName("gridLayoutWidget") self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget) self.gridLayout_2.setContentsMargins(0, 0, 0, 0) self.gridLayout_2.setObjectName("gridLayout_2") self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.label_2.setFont(font) self.label_2.setAlignment(QtCore.Qt.AlignCenter) self.label_2.setObjectName("label_2") self.gridLayout_2.addWidget(self.label_2, 0, 1, 1, 1) self.label = QtWidgets.QLabel(self.gridLayoutWidget) font = QtGui.QFont() font.setPointSize(10) font.setBold(True) font.setWeight(75) self.label.setFont(font) self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setObjectName("label") self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1) self.comp2 = QtWidgets.QComboBox(self.gridLayoutWidget) font = QtGui.QFont() self.comp2.addItems(listChem.chemComp()) font.setPointSize(9) self.comp2.setFont(font) self.comp2.setObjectName("comp2") self.gridLayout_2.addWidget(self.comp2, 1, 1, 1, 1) self.comp1 = QtWidgets.QComboBox(self.gridLayoutWidget) font = QtGui.QFont() self.comp1.addItems(listChem.chemComp()) font.setPointSize(9) self.comp1.setFont(font) self.comp1.setObjectName("comp1") self.gridLayout_2.addWidget(self.comp1, 1, 0, 1, 1) Op2.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(Op2) self.menubar.setGeometry(QtCore.QRect(0, 0, 950, 21)) self.menubar.setObjectName("menubar") self.menuTools = QtWidgets.QMenu(self.menubar) self.menuTools.setObjectName("menuTools") self.menuAbout = QtWidgets.QMenu(self.menubar) self.menuAbout.setObjectName("menuAbout") Op2.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(Op2) self.statusbar.setObjectName("statusbar") Op2.setStatusBar(self.statusbar) self.actionsave2Excel = QtWidgets.QAction(Op2) self.actionsave2Excel.setObjectName("actionsave2Excel") #self.actionsavePlot = QtWidgets.QAction(Op2) #self.actionsavePlot.setObjectName("actionsavePlot") #self.addElement = QtWidgets.QAction(Op2) #self.addElement.setObjectName("addElement") self.about = QtWidgets.QAction(Op2) self.about.setObjectName("about") #self.removeElement = QtWidgets.QAction(Op2) #self.removeElement.setObjectName("removeElement") self.menuTools.addAction(self.actionsave2Excel) #self.menuTools.addAction(self.actionsavePlot) self.menuTools.addSeparator() #self.menuTools.addAction(self.addElement) #self.menuTools.addAction(self.removeElement) self.menuAbout.addAction(self.about) self.menubar.addAction(self.menuTools.menuAction()) self.menubar.addAction(self.menuAbout.menuAction()) self.retranslateUi(Op2) QtCore.QMetaObject.connectSlotsByName(Op2) self.pconst.toggled.connect(lambda: self.selected(self.pconst) ) #Selection RadioButton Pressão Constante self.tconst.toggled.connect(lambda: self.selected( self.tconst)) #Selection RadioButton Temperatura Constante self.graphicPlot.clicked.connect( lambda: self.call(float(self.databox.text( )), self.changeTextUni.text())) #Call the plot function self.actionsave2Excel.triggered.connect(lambda: self.saveData()) self.about.triggered.connect(lambda: self.aboutMsg()) def retranslateUi(self, Op2): _translate = QtCore.QCoreApplication.translate Op2.setWindowTitle(_translate("Op2", "Op_2 App")) self.graphicPlot.setText(_translate("Op2", "Plot")) self.pconst.setText(_translate("Op2", "Constant pressure ")) self.tconst.setText(_translate("Op2", "Constant temperature ")) self.changeTextVar.setText(_translate("Op2", "Temperature")) self.changeTextUni.setText(_translate("Op2", "K")) self.label_2.setText(_translate("Op2", "Substance 2")) self.label.setText(_translate("Op2", "Substance 1")) self.menuTools.setTitle(_translate("Op2", "Tools")) self.menuAbout.setTitle(_translate("Op2", "About")) self.actionsave2Excel.setText(_translate("Op2", "Save data to Excel")) #self.actionsavePlot.setText(_translate("Op2", "Salvar gráficos")) #self.addElement.setText(_translate("Op2", "Adicionar Elemento")) self.about.setText(_translate("Op2", "about")) #self.removeElement.setText(_translate("Op2", "Remover Elemento")) def selected(self, b): if b.text() == "Constant pressure ": if b.isChecked() == True: self.changeTextVar.setText('Pressure') self.changeTextUni.setText("bar") elif b.text() == "Constant temperature ": if b.isChecked() == True: self.changeTextVar.setText('Temperature') self.changeTextUni.setText("K") def call(self, data, signal, n=1000): self.graphics1.clear(), self.graphics2.clear() x = np.arange(0, 1.0 + (1 / n), (1 / n)) y, P, T = np.zeros(np.size(x)), np.zeros(np.size(x)), np.zeros( np.size(x)) if signal == "bar": #Erase float_files if os.path.exists('float_files\\pconstdata.txt'): os.remove('float_files\\pconstdata.txt') try: data = open('float_files\\pconstdata.txt', 'a') newData = Equilibrium( lchem=[self.comp1.currentText(), self.comp2.currentText()], p=float(self.databox.text())) self.A, self.B, self.C, self.Tmax, self.Tmin, self.DG = newData.compData( ) Tsat = ( self.B / (self.A - np.log10(float(self.databox.text())))) - self.C data.write('Temperature [K], x, y\n') for i in range(np.size(x)): T0 = np.sum(np.asarray([x[i], 1 - x[i]]) * Tsat) while (True): a12 = 10**(self.A[0] - self.A[1] - (self.B[0] / (T0 + self.C[0])) + (self.B[1] / (T0 + self.C[1]))) coef = UNIFAC(T=T0, xs=[x[i], 1 - x[i]], chemgroups=self.DG) P2sat = (float(self.databox.text()) / (x[i] * coef[0] * a12 + (1 - x[i]) * coef[1])) Tn = (self.B[1] / (self.A[1] - np.log10(P2sat))) - self.C[1] if (abs(Tn - T0) < 0.001): break T0 = Tn T[i] = T0 y[i] = 1 - ((1 - x[i]) * coef[1] * P2sat) / (float( self.databox.text())) data.write( str(round(T[i], 4)) + ', ' + str(round(x[i], 4)) + ', ' + str(round(y[i], 4))) data.write('\n') self.graphics1.plot(x, y, pen='r') self.graphics1.plot(x, x, pen='r') self.graphics1.setLabel('left', 'Gas composition of ' + self.comp1.currentText(), color='r', size=20) self.graphics1.setLabel('bottom', 'Liquid composition of ' + self.comp1.currentText(), color='b', size=20) self.graphics2.plot(x, T, pen='g') self.graphics2.plot(y, T, pen='k') self.graphics2.setLabel('left', 'Temperature of ' + self.comp1.currentText() + ' [K]', color='r', size=20) self.graphics2.setLabel('bottom', 'Composition of ' + self.comp1.currentText(), color='b', size=20) data.close() except: print('error') elif signal == "K": #Erase float_files if os.path.exists('float_files\\tconstdata.txt'): os.remove('float_files\\tconstdata.txt') try: data = open('float_files\\tconstdata.txt', 'a') newData = Equilibrium( lchem=[self.comp1.currentText(), self.comp2.currentText()], t=float(self.databox.text())) self.A, self.B, self.C, self.Tmax, self.Tmin, self.DG = newData.compData( ) Pvap = 10**(self.A - (self.B / (float(self.databox.text()) + self.C))) data.write('Pressure [bar], x, y\n') for i in range(np.size(x)): actCoef = UNIFAC(T=float(self.databox.text()), xs=[x[i], 1 - x[i]], chemgroups=self.DG) P[i] = np.sum(Pvap * np.asarray(actCoef) * np.asarray([x[i], 1 - x[i]])) y[i] = ((x[i] * actCoef[0] * Pvap[0])) / P[i] data.write( str(round(P[i], 4)) + ', ' + str(round(x[i], 4)) + ', ' + str(round(y[i], 4))) data.write('\n') self.graphics1.plot(x, y, pen='r') self.graphics1.plot(x, x, pen='r') self.graphics1.setLabel('left', 'Gas composition of ' + self.comp1.currentText(), color='r', size=20) self.graphics1.setLabel('bottom', 'Liquid composition of ' + self.comp1.currentText(), color='b', size=20) self.graphics2.plot(x, P, pen='b') self.graphics2.plot(y, P, pen='r') self.graphics2.setLabel('left', 'Pressure of ' + self.comp1.currentText() + ' [bar]', color='r', size=20) self.graphics2.setLabel('bottom', 'Composition of ' + self.comp1.currentText(), color='b', size=20) data.close() except: print('Error!') def saveData(self): if self.changeTextUni.text() == 'bar': try: filename = QtWidgets.QFileDialog.getSaveFileName( caption='Salvar arquivo', directory='c:\\', filter='(*.xlsx)', initialFilter='') data = pd.read_csv('float_files\\pconstdata.txt', sep=', ') data.to_excel(excel_writer=filename[0]) os.remove('float_files\\pconstdata.txt') except: pass elif self.changeTextUni.text() == 'K': try: filename = QtWidgets.QFileDialog.getSaveFileName( caption='Salvar arquivo', directory='c:\\', filter='(*.xlsx)', initialFilter='') data = pd.read_csv('float_files\\tconstdata.txt', sep=', ') data.to_excel(excel_writer=filename[0]) os.remove('float_files\\tconstdata.txt') except: pass def aboutMsg(self): msg = QtWidgets.QMessageBox() msg.setWindowTitle('Sobre') msg.setWindowIcon(QtGui.QIcon('images\Icone.jpg')) msg.setText( 'Programa desenvolvido para calcular o equilíbrio de fase líquido-vapor de um sistema binário com fase vapor ideal e fase liquída não ideal cujo' + ' coeficiente de atividade é obtido por meio do método UNIFAC') x = msg.exec_()
class Aditi(QMainWindow): def __init__(self): QMainWindow.__init__(self) # title self.setWindowTitle("Aditi") self.setDockOptions(QMainWindow.VerticalTabs | QMainWindow.AnimatedDocks) #self.showMaximized() # model self.rawfiles_by_short_path = {} self.xic_by_rawfile_short_path = {} self.tic_by_rawfile_short_path = {} self.spec_by_rawfile_short_path = {} self.inf_line_tic_item = None self.curr_scan_id_by_short_path = {} # menu self.file_menu = self.menuBar().addMenu('&File') #self.file_menu.setTearOffEnabled(False) open_action = QAction("&Open...", self) open_action.setToolTip("Open a rawfile") open_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_O)) self.file_menu.addAction(open_action) open_action.triggered.connect(self.show_open_dialog) exit_action = QAction("&Exit", self) exit_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q)) self.file_menu.addAction(exit_action) exit_action.triggered.connect(self.quit) self.tab_widget = QTabWidget(self) # spectrum plot Widget self.graphics_layout_widget = GraphicsLayoutWidget(parent=self.tab_widget) self.graphics_layout_widget.keyPressEvent = self.handle_key_press_event self.graphics_layout_widget.useOpenGL(False) self.graphics_layout_widget.setAntialiasing(False) self.plot_widget_tic = self.graphics_layout_widget.addPlot(title="TIC(s)", labels={'left': "Intensity", 'bottom': "Retention Time (sec)"}) self.plot_widget_tic.showGrid(x=True, y=True) self.graphics_layout_widget.nextRow() self.plot_widget_spectrum = self.graphics_layout_widget.addPlot(title="Spectrum", labels={'left': "Intensity", 'bottom': "m/z"}) self.plot_widget_spectrum.showGrid(x=True, y=True) # finally add tab self.tab_widget.addTab(self.graphics_layout_widget, "Spectrum") # Xic plotWidget self.plot_widget_xic = PlotWidget(name="MainPlot", labels={'left': "Intensity", 'bottom': "Retention Time (sec)"}) self.plot_widget_xic.showGrid(x=True, y=True) self.tab_widget.addTab(self.plot_widget_xic, "Xic extraction") self.setCentralWidget(self.tab_widget) self.statusBar().showMessage("Ready") # dock 1 self.rawfile_dock_widget = QDockWidget("Rawfiles") self.rawfile_table_view = QTableView() self.rawfile_table_view.horizontalHeader().setVisible(False) self.rawfile_table_view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.rawfile_dock_widget.setWidget(self.rawfile_table_view) self.rawfile_model = QStandardItemModel() self.rawfile_model.setHorizontalHeaderLabels(["Rawfiles"]) self.rawfile_table_view.setModel(self.rawfile_model) self.rawfile_model.itemChanged.connect(self.item_changed) self.addDockWidget(0x2, self.rawfile_dock_widget) # xic dock widget extraction parameter self.xic_dock_widget = QDockWidget("Xic extraction") self.xic_widget = XicWidget() self.xic_widget.plotButton.clicked.connect(self.plot) self.xic_dock_widget.setWidget(self.xic_widget) self.addDockWidget(0x2, self.xic_dock_widget) def handle_key_press_event(self, evt): if self.inf_line_tic_item is None: return times = [] if evt.key() == Qt.Key_Left: for rawfile in self.rawfiles_by_short_path.values()[:1]: if not rawfile.is_checked: continue curr_scan_id = self.curr_scan_id_by_short_path[rawfile.short_path] scan_ids = rawfile.reader.rt_by_scan_id_by_ms_level[1].keys() idx = scan_ids.index(curr_scan_id) times.append(rawfile.reader.rt_by_scan_id_by_ms_level[1][scan_ids[idx - 1]]) self.curr_scan_id_by_short_path[rawfile.short_path] = scan_ids[idx - 1] elif evt.key() == Qt.Key_Right: for rawfile in self.rawfiles_by_short_path.values()[:1]: if not rawfile.is_checked: continue curr_scan_id = self.curr_scan_id_by_short_path[rawfile.short_path] scan_ids = rawfile.reader.rt_by_scan_id_by_ms_level[1].keys() idx = scan_ids.index(curr_scan_id) times.append(rawfile.reader.rt_by_scan_id_by_ms_level[1][scan_ids[idx + 1]]) self.curr_scan_id_by_short_path[rawfile.short_path] = scan_ids[idx + 1] self._plot_spectrum() if times: self.inf_line_tic_item.setPos(sum(times) / float(len(times))) def _plot_spectrum(self): self.plot_widget_spectrum.clear() min_mz, max_mz = 1e9, 0 min_int, max_int = 1e10, 0 for rawfile in self.rawfiles_by_short_path.values(): if not rawfile.is_checked: continue scan_id, mzs, intensities = rawfile.reader.get_scan(self.curr_scan_id_by_short_path[rawfile.short_path]) min_mz = min(min_mz, mzs[0]) max_mz = max(max_mz, mzs[-1]) min_int = min(min_int, min(intensities)) max_int = max(max_int, max(intensities)) item = BarGraphItem(x=mzs, height=intensities, width=0.01, pen=rawfile.qcolor, brush=rawfile.qcolor) self.plot_widget_spectrum.addItem(item) self.plot_widget_spectrum.setLimits(xMin=min_mz, xMax=max_mz, yMin=min_int, yMax=max_int) def plot_spectrum(self, ev): #clear if ev.button() == Qt.RightButton: return self.plot_widget_spectrum.clear() vb = self.plot_widget_tic.vb mouse_point = vb.mapSceneToView(ev.scenePos()) t = mouse_point.x() if self.inf_line_tic_item is None: self.inf_line_tic_item = InfiniteLine(pos=t, angle=90) self.plot_widget_tic.addItem(self.inf_line_tic_item) self.inf_line_tic_item.setMovable(True) else: self.inf_line_tic_item.setPos(t) min_mz, max_mz = 1e9, 0 min_int, max_int = 1e10, 0 for rawfile in self.rawfiles_by_short_path.values(): if not rawfile.is_checked: continue scan_id, mzs, intensities = rawfile.reader.get_scan_for_time(t) self.curr_scan_id_by_short_path[rawfile.short_path] = scan_id min_mz = min(min_mz, mzs[0]) max_mz = max(max_mz, mzs[-1]) min_int = min(min_int, min(intensities)) max_int = max(max_int, max(intensities)) item = BarGraphItem(x=mzs, height=intensities, width=0.01, pen=rawfile.qcolor, brush=rawfile.qcolor) self.plot_widget_spectrum.addItem(item) self.plot_widget_spectrum.setLimits(xMin=min_mz, xMax=max_mz, yMin=min_int, yMax=max_int) def item_changed(self, item): print "item changed", item.text() s = item.text() if item.checkState(): self.rawfiles_by_short_path[s].is_checked = True else: self.rawfiles_by_short_path[s].is_checked = False #self.qApp.emit(SIGNAL('redraw()')) self.update_plot_() def show_open_dialog(self): files = QFileDialog(self).getOpenFileNames() if files: preload = Preloader(files, self) preload.loaded.connect(self.update_rawfile_model) preload.start() def update_rawfile_model(self, obj): files, r = obj[0], obj[1] n = len(files) not_database = [] min_time, max_time = 1e9, 0 min_int, max_int = 1e9, 0 for i, f in enumerate(files): i_f = float(i) c = WithoutBlank.get_color(i_f / n, asQColor=True) c_ = WithoutBlank.get_color(i_f / n, asQColor=True) filename = f.split("\\")[-1] abs_path = str(f.replace("\\", "\\\\")) if r[i]: rawfile = Rawfile(abs_path, c, filename) self.rawfiles_by_short_path[filename] = rawfile #[MzDBReader(abs_path), c, True] self.rawfile_model.appendRow(Aditi.get_coloured_root_item(filename, c, c_)) times, intensities = rawfile.reader.get_tic() min_time = min(min_time, min(times)) max_time = max(max_time, max(times)) min_int = min(min_int, min(intensities)) max_int = max(max_int, max(intensities)) self.plot_widget_tic.plot(times, intensities, pen=mkPen(color=rawfile.qcolor, width=1.3)) else: not_database.append(str(filename)) self.plot_widget_tic.setLimits(xMin=min_time, xMax=max_time, yMin=min_int, yMax=max_int) self.plot_widget_tic.scene().sigMouseClicked.connect(self.plot_spectrum) if not_database: v = "\n".join(not_database) QMessageBox.information(self, "Error", "The following files are not valid sqlite database:\n" + v) @staticmethod def get_coloured_root_item(filepath, color, colorr): root = QStandardItem(filepath) gradient = QLinearGradient(-100, -100, 100, 100) gradient.setColorAt(0.7, colorr) gradient.setColorAt(1, color) root.setBackground(QBrush(gradient)) root.setEditable(False) root.setCheckState(Qt.Checked) root.setCheckable(True) return root def quit(self): res = QMessageBox.warning(self, "Exiting...", "Are you sure ?", QMessageBox.Ok | QMessageBox.Cancel) if res == QMessageBox.Cancel: return QtGui.qApp.quit() def plot(self): #clear pw self.plot_widget_xic.clear() # check sample checked checked_files = [rawfile for rawfile in self.rawfiles_by_short_path.values() if rawfile.is_checked] mz = self.xic_widget.mzSpinBox.value() mz_tol = self.xic_widget.mzTolSpinBox.value() mz_diff = mz * mz_tol / 1e6 min_mz, max_mz = mz - mz_diff, mz + mz_diff #Thread implementation not as fast # args = [(data[0], min_mz, max_mz, data[2]) for data in checked_files] # extractor_thread = Extractor(args, self) # extractor_thread.extracted.connect(self._plot) # extractor_thread.start() min_time_val, max_time_val = 10000, 0 min_int_val, max_int_val = 1e9, 0 for rawfile in checked_files: t1 = time.clock() times, intensities = rawfile.reader.get_xic(min_mz, max_mz) print "elapsed: ", time.clock() - t1 # min_time_val = min(min_time_val, times[0]) # max_time_val = max(max_time_val, times[-1]) # min_int_val = min(min_int_val, min(intensities)) # max_int_val = max(max_int_val, max(intensities)) item = self.plot_widget_xic.plot(times, intensities, pen=mkPen(color=rawfile.qcolor, width=1.3)) item.curve.setClickable(True) def on_curve_clicked(): if not rawfile.is_highlighted: item.setPen(mkPen(color=rawfile.qcolor, width=4)) rawfile.is_highlighted = True else: item.setPen(mkPen(color=rawfile.qcolor, width=2)) rawfile.is_highlighted = False item.sigClicked.connect(on_curve_clicked) #item.sigHovered = on_curve_clicked self.xic_by_rawfile_short_path[rawfile.short_path] = item self.plot_widget_xic.setTitle(title="Xic@" + str(mz)) #self.plot_widget_xic.setLimits(xMin=min_time_val, xMax=max_time_val, yMin=min_int_val, yMax=max_int_val) def update_plot_(self): for rawfile in self.rawfiles_by_short_path.viewvalues(): if rawfile.is_checked: try: self.plot_widget_xic.addItem(self.xic_by_rawfile_short_path[rawfile.short_path]) except KeyError: mz = self.xic_widget.mzSpinBox.value() mz_tol = self.xic_widget.mzTolSpinBox.value() mz_diff = mz * mz_tol / 1e6 min_mz, max_mz = mz - mz_diff, mz + mz_diff times, intensities = rawfile.reader.get_xic(min_mz, max_mz) item = self.plot_widget_xic.plot(times, intensities, pen=mkPen(color=rawfile.qcolor, width=2)) self.xic_by_rawfile_short_path[rawfile.short_path] = item else: try: #self.plot_widget_xic.removeItem(self.xic_by_rawfile_short_path[rawfile.short_path]) self.xic_by_rawfile_short_path[rawfile.short_path].hide() except KeyError: pass
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 Ui_MainWindow(object): test_points = [(0.0, 1.0), (0.2, 1.02), (0.4, 1.08), (0.6, 1.12), (0.8, 1.34), (1.0, 1.54), (1.2, 1.81), (1.4, 2.15)] interpolation_ins = Interpolation() def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(816, 480) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.groupBox = QtWidgets.QGroupBox(self.centralwidget) self.groupBox.setGeometry(QtCore.QRect(10, 10, 121, 151)) self.groupBox.setTitle("") self.groupBox.setObjectName("groupBox") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox) self.verticalLayout_2.setObjectName("verticalLayout_2") self.label = QtWidgets.QLabel(self.groupBox) self.label.setWordWrap(True) self.label.setObjectName("label") self.verticalLayout_2.addWidget(self.label) self.editAppendX = QtWidgets.QLineEdit(self.groupBox) self.editAppendX.setAlignment(QtCore.Qt.AlignCenter) self.editAppendX.setObjectName("editAppendX") self.verticalLayout_2.addWidget(self.editAppendX) self.editAppendY = QtWidgets.QLineEdit(self.groupBox) self.editAppendY.setAlignment(QtCore.Qt.AlignCenter) self.editAppendY.setObjectName("editAppendY") self.verticalLayout_2.addWidget(self.editAppendY) self.appendPointBtn = QtWidgets.QPushButton(self.groupBox) self.appendPointBtn.setObjectName("appendPointBtn") self.appendPointBtn.clicked.connect(self.appendPointBtn_clicked) self.verticalLayout_2.addWidget(self.appendPointBtn) self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget) self.groupBox_2.setGeometry(QtCore.QRect(10, 230, 121, 131)) self.groupBox_2.setTitle("") self.groupBox_2.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.groupBox_2.setObjectName("groupBox_2") self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_2) self.verticalLayout.setObjectName("verticalLayout") self.label_2 = QtWidgets.QLabel(self.groupBox_2) self.label_2.setWordWrap(True) self.label_2.setObjectName("label_2") self.verticalLayout.addWidget(self.label_2) self.editFindX = QtWidgets.QLineEdit(self.groupBox_2) self.editFindX.setAlignment(QtCore.Qt.AlignCenter) self.editFindX.setObjectName("editFindX") self.verticalLayout.addWidget(self.editFindX) self.interpolateBtn = QtWidgets.QPushButton(self.groupBox_2) self.interpolateBtn.setObjectName("interpolateBtn") self.interpolateBtn.clicked.connect(self.interpolateBtn_clicked) self.verticalLayout.addWidget(self.interpolateBtn) # chart self.graphicsView = PlotWidget(self.centralwidget) self.graphicsView.setGeometry(QtCore.QRect(170, 10, 621, 430)) self.graphicsView.setObjectName("graphicsView") self.graphicsView0 = PlotWidget(self.centralwidget) self.graphicsView0.setGeometry(QtCore.QRect(170, 10, 621, 430)) self.graphicsView0.setObjectName("graphicsView0") self.graphicsView0.hide() # Aitken table self.aitkenTable = QtWidgets.QTableWidget(self.centralwidget) self.aitkenTable.setGeometry(QtCore.QRect(170, 10, 621, 430)) self.aitkenTable.setObjectName("aitkenTable") self.aitkenTable.setColumnCount(self.interpolation_ins.get_width() + 3) header = self.aitkenTable.horizontalHeader() header.setResizeMode(0, QtWidgets.QHeaderView.ResizeToContents) self.aitkenTable.hide() # Lagrangian polynomial self.lagrangianTextBrowser = QtWidgets.QTextBrowser(self.centralwidget) self.lagrangianTextBrowser.setGeometry(QtCore.QRect(170, 10, 621, 430)) self.lagrangianTextBrowser.setObjectName("lagrangianTextBrowser") self.lagrangianTextBrowser.hide() self.clearPointsBtn = QtWidgets.QPushButton(self.centralwidget) self.clearPointsBtn.setGeometry(QtCore.QRect(10, 180, 121, 32)) self.clearPointsBtn.setObjectName("clearPointsBtn") self.clearPointsBtn.clicked.connect(self.clear_points) self.labelY = QtWidgets.QLabel(self.centralwidget) self.labelY.setGeometry(QtCore.QRect(15, 370, 130, 31)) self.labelY.setObjectName("labelY") self.labelY0 = QtWidgets.QLabel(self.centralwidget) self.labelY0.setGeometry(QtCore.QRect(15, 390, 130, 31)) self.labelY0.setObjectName("labelY0") self.comboBox = QtWidgets.QComboBox(self.centralwidget) self.comboBox.setGeometry(QtCore.QRect(5, 420, 151, 26)) self.comboBox.setObjectName("comboBox") self.comboBox.addItems([ "Lagrangian Graph", "Aitken Graph", "Aitken Table", "Lagrangian Polynomial" ]) self.comboBox.activated.connect(self.select_view) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 816, 22)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.label.setText(_translate("MainWindow", "Append point to graph")) self.editAppendY.setPlaceholderText(_translate("MainWindow", "Y")) self.editAppendX.setPlaceholderText(_translate("MainWindow", "X")) self.appendPointBtn.setText(_translate("MainWindow", "Add Point")) self.label_2.setText( _translate("MainWindow", "Find Y for point with X coordinate")) self.labelY.setText(_translate("MainWindow", "Aitken Y: ")) self.labelY0.setText(_translate("MainWindow", "Lgrngn Y: ")) self.editFindX.setPlaceholderText(_translate("MainWindow", "X")) self.interpolateBtn.setText(_translate("MainWindow", "Interpolate")) self.clearPointsBtn.setText(_translate("MainWindow", "Clear Points")) self.comboBox.setItemText(0, _translate("MainWindow", "Lagrangian Graph")) self.comboBox.setItemText(1, _translate("MainWindow", "Aitken Graph")) self.comboBox.setItemText(2, _translate("MainWindow", "Aitken Table")) self.comboBox.setItemText( 3, _translate("MainWindow", "Lagrangian Polynomial")) def clear_points(self): self.graphicsView.clear() self.graphicsView0.clear() self.interpolation_ins.clear_points() self.aitkenTable.clear() self.lagrangianTextBrowser.clear() def select_view(self, i): print(i) self.comboBox.setCurrentIndex(i) if i == 0: self.graphicsView.show() self.graphicsView0.hide() self.aitkenTable.hide() self.lagrangianTextBrowser.hide() elif i == 1: self.graphicsView.hide() self.graphicsView0.show() self.aitkenTable.hide() self.lagrangianTextBrowser.hide() elif i == 2: self.graphicsView.hide() self.graphicsView0.hide() self.aitkenTable.show() self.lagrangianTextBrowser.hide() elif i == 3: self.graphicsView.hide() self.graphicsView0.hide() self.aitkenTable.hide() self.lagrangianTextBrowser.show() def update_Aitken(self, points): self.aitkenTable.setRowCount(len(points)) for i in range(len(points)): for j in range(len(points[0])): self.aitkenTable.setItem( i, j, QtWidgets.QTableWidgetItem(str(points[i][j]))) def update_Lagrangian(self): if not self.interpolation_ins.lagrangian: self.interpolation_ins.build_Lagrangian() self.lagrangianTextBrowser.clear() for i in self.interpolation_ins.lagrangian: self.lagrangianTextBrowser.append(i) self.lagrangianTextBrowser.append("\n") def add_default_points(self): if not len(self.interpolation_ins.get_points()): for (x, y) in self.test_points: p = Point(x, y) self.interpolation_ins.add_point(p) def appendPointBtn_clicked(self): try: x = float(self.editAppendX.text()) y = float(self.editAppendY.text()) p = Point(x, y) except Exception as e: print("-" * 50 + "\n", e) self.add_default_points() else: self.interpolation_ins.add_point(p) points = self.interpolation_ins.get_points() self.update_Lagrangian() self.update_Aitken(self.interpolation_ins.init_Aitken()) self.editAppendX.setText("") self.editAppendY.setText("") massiv_x = self.scatter() self.small_interval_lagrangian(massiv_x) self.small_interval_Aitken(massiv_x) def scatter(self, step=0.01): points = self.interpolation_ins.get_points() start, end = points[0].get_x(), points[-1].get_x() massiv_x = np.arange(start, end, step) return massiv_x def small_interval_lagrangian(self, massiv_x): massiv_y = [] for x in massiv_x: self.interpolation_ins.set_interpolation_point_x(x) y = self.interpolation_ins.Lagrangian_method() massiv_y.append(y) self.graphicsView.clear() self.graphicsView.plot(massiv_x, massiv_y) def small_interval_Aitken(self, massiv_x): massiv_y = [] xs, ys = self.interpolation_ins.get_split_points() for x in massiv_x: y = self.interpolation_ins.method(x, xs, ys) massiv_y.append(y) self.graphicsView0.clear() self.graphicsView0.plot(massiv_x, massiv_y, pen=pyqtgraph.mkPen('g')) def interpolateBtn_clicked(self): try: x = float(self.editFindX.text()) except Exception as e: print("Exception: ", e) return if not self.interpolation_ins.get_points(): print("No points for interpolation") else: self.select_view(0) self.interpolation_ins.set_interpolation_point_x(x) xs, ys = self.interpolation_ins.get_split_points() y_E = self.interpolation_ins.method(x, xs, ys) y = self.interpolation_ins.test() y_L = self.interpolation_ins.Lagrangian_method() text = "Aitken Y: " + str(y_E) self.labelY.setText(text) text = "Lagrangian Y: " + str(y_L) self.labelY0.setText(text) if self.interpolation_ins.is_in_interval(x): self.update_Aitken(self.interpolation_ins.get_table()) self.graphicsView.plot([x], [y_E], pen=None, symbol='o') self.graphicsView0.plot([x], [y_L], pen=pyqtgraph.mkPen('r'), symbol='o')
class Ui_MainWindow(object): accuracy_vals = [] recording_vals = np.zeros([ 960 * 10 * 10, ]) microphone_recorder = None train_thread = None recorder_thread = None ser_inference_model = SER_Inference_Model() ser_online_model = SER_Online_Model() label_7_line_nr = 0 play_th = None def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") MainWindow.resize(1300, 900) qr = MainWindow.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) MainWindow.move(qr.topLeft()) self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setSpacing(0) self.gridLayout_2.setObjectName("gridLayout_2") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setContentsMargins(10, 10, 10, 10) self.verticalLayout.setSpacing(2) self.verticalLayout.setObjectName("verticalLayout") self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget) self.groupBox_4.setMinimumSize(QtCore.QSize(670, 860)) self.groupBox_4.setObjectName("groupBox_4") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(40, 400, 400, 20)) self.label_2.setMaximumSize(QtCore.QSize(16777215, 20)) self.label_2.setObjectName("label_2") self.progressBar = QtWidgets.QProgressBar(self.centralwidget) self.progressBar.setGeometry(QtCore.QRect(40, 400, 500, 40)) self.progressBar.setMinimumSize(QtCore.QSize(500, 40)) self.progressBar.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.progressBar.setStyleSheet(COMPLETED_STYLE_ANGRY) self.progressBar.setProperty("value", 0) self.progressBar.setObjectName("progressBar") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(40, 460, 400, 20)) self.label_3.setMaximumSize(QtCore.QSize(16777215, 20)) self.label_3.setObjectName("label_3") self.progressBar_2 = QtWidgets.QProgressBar(self.centralwidget) self.progressBar_2.setGeometry(QtCore.QRect(40, 460, 500, 40)) self.progressBar_2.setMinimumSize(QtCore.QSize(500, 40)) self.progressBar_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.progressBar_2.setStyleSheet(COMPLETED_STYLE_HAPPY) self.progressBar_2.setProperty("value", 0) self.progressBar_2.setObjectName("progressBar_2") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(40, 520, 400, 20)) self.label_4.setMaximumSize(QtCore.QSize(16777215, 20)) self.label_4.setObjectName("label_4") self.progressBar_3 = QtWidgets.QProgressBar(self.centralwidget) self.progressBar_3.setGeometry(QtCore.QRect(40, 520, 500, 40)) self.progressBar_3.setMinimumSize(QtCore.QSize(500, 40)) self.progressBar_3.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.progressBar_3.setStyleSheet(COMPLETED_STYLE_SAD) self.progressBar_3.setProperty("value", 0) self.progressBar_3.setObjectName("progressBar_3") self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setGeometry(QtCore.QRect(40, 570, 400, 20)) self.label_5.setMaximumSize(QtCore.QSize(16777215, 20)) self.label_5.setObjectName("label_5") self.progressBar_4 = QtWidgets.QProgressBar(self.centralwidget) self.progressBar_4.setGeometry(QtCore.QRect(40, 560, 500, 40)) self.progressBar_4.setMinimumSize(QtCore.QSize(500, 40)) self.progressBar_4.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.progressBar_4.setProperty("value", 0) self.progressBar_4.setObjectName("progressBar_4") self.graphicsView = PlotWidget(self.groupBox_4) self.graphicsView.setGeometry(QtCore.QRect(10, 30, 650, 400)) self.graphicsView.setObjectName("graphicsView") self.verticalLayout.addWidget(self.groupBox_4) self.gridLayout_2.addLayout(self.verticalLayout, 0, 0, 1, 1) self.gridLayout.addLayout(self.gridLayout_2, 0, 3, 1, 1) self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout_2.setContentsMargins(10, 10, 10, 10) self.verticalLayout_2.setSpacing(2) self.verticalLayout_2.setObjectName("verticalLayout_2") self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget) self.groupBox_3.setMinimumSize(QtCore.QSize(603, 110)) self.groupBox_3.setObjectName("groupBox_3") self.comboBox_2 = QtWidgets.QComboBox(self.groupBox_3) self.comboBox_2.setGeometry(QtCore.QRect(105, 72, 441, 30)) self.comboBox_2.setObjectName("comboBox_2") self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_3) self.lineEdit_2.setGeometry(QtCore.QRect(105, 35, 441, 30)) self.lineEdit_2.setObjectName("lineEdit_2") self.label_9 = QtWidgets.QLabel(self.groupBox_3) self.label_9.setGeometry(QtCore.QRect(10, 37, 90, 30)) self.label_9.setObjectName("label_9") self.label_10 = QtWidgets.QLabel(self.groupBox_3) self.label_10.setGeometry(QtCore.QRect(60, 71, 40, 30)) self.label_10.setObjectName("label_10") self.pushButtonInfPlay = QtWidgets.QPushButton(self.groupBox_3) self.pushButtonInfPlay.setGeometry(QtCore.QRect(550, 72, 48, 30)) self.pushButtonInfPlay.setObjectName("pushButtonInfPlay") self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget) self.groupBox_2.setMinimumSize(QtCore.QSize(600, 280)) self.groupBox_2.setObjectName("groupBox_2") self.label_18 = QtWidgets.QLabel(self.groupBox_2) self.label_18.setGeometry(QtCore.QRect(10, 75, 205, 25)) self.label_18.setObjectName("label_18") self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox_2) self.radioButton_3.setGeometry(QtCore.QRect(215, 77, 165, 25)) self.radioButton_3.setChecked(True) self.radioButton_3.setAutoRepeat(False) self.radioButton_3.setObjectName("radioButton_3") self.radioButton_4 = QtWidgets.QRadioButton(self.groupBox_2) self.radioButton_4.setGeometry(QtCore.QRect(325, 77, 120, 25)) self.radioButton_4.setObjectName("radioButton_4") self.label_8 = QtWidgets.QLabel(self.groupBox_2) self.label_8.setGeometry(QtCore.QRect(10, 243, 94, 25)) self.label_8.setObjectName("label_8") self.lineEdit = QtWidgets.QLineEdit(self.groupBox_2) self.lineEdit.setGeometry(QtCore.QRect(75, 240, 70, 30)) self.lineEdit.setObjectName("lineEdit") self.label_17 = QtWidgets.QLabel(self.groupBox_2) self.label_17.setGeometry(QtCore.QRect(460, 243, 110, 30)) self.label_17.setObjectName("label_17") self.label_19 = QtWidgets.QLabel(self.groupBox_2) self.label_19.setGeometry(QtCore.QRect(570, 243, 30, 30)) self.label_19.setObjectName("label_19") self.comboBox = QtWidgets.QComboBox(self.groupBox_2) self.comboBox.setGeometry(QtCore.QRect(125, 38, 460, 30)) self.comboBox.setMinimumSize(QtCore.QSize(200, 0)) self.comboBox.setFocusPolicy(QtCore.Qt.WheelFocus) self.comboBox.setMaxVisibleItems(10) self.comboBox.setIconSize(QtCore.QSize(16, 16)) self.comboBox.setObjectName("comboBox") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.label = QtWidgets.QLabel(self.groupBox_2) self.label.setGeometry(QtCore.QRect(10, 36, 105, 30)) self.label.setObjectName("label") self.label_11 = QtWidgets.QLabel(self.groupBox_2) self.label_11.setGeometry(QtCore.QRect(10, 100, 130, 30)) self.label_11.setObjectName("label_11") self.horizontalSlider = QtWidgets.QSlider(self.groupBox_2) self.horizontalSlider.setGeometry(QtCore.QRect(138, 109, 430, 17)) self.horizontalSlider.setMaximum(10) self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider.setObjectName("horizontalSlider") self.label_12 = QtWidgets.QLabel(self.groupBox_2) self.label_12.setGeometry(QtCore.QRect(570, 102, 31, 30)) self.label_12.setObjectName("label_12") self.label_15 = QtWidgets.QLabel(self.groupBox_2) self.label_15.setGeometry(QtCore.QRect(10, 132, 121, 25)) self.label_15.setObjectName("label_15") self.horizontalSlider_2 = QtWidgets.QSlider(self.groupBox_2) self.horizontalSlider_2.setGeometry(QtCore.QRect(138, 137, 430, 17)) self.horizontalSlider_2.setMaximum(10) self.horizontalSlider_2.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_2.setObjectName("horizontalSlider_2") self.label_16 = QtWidgets.QLabel(self.groupBox_2) self.label_16.setGeometry(QtCore.QRect(570, 134, 31, 25)) self.label_16.setObjectName("label_15") self.ooda_check_box = QtWidgets.QCheckBox(self.groupBox_2) self.ooda_check_box.setGeometry(QtCore.QRect(15, 160, 120, 31)) self.ooda_check_box.setObjectName("checkBoxOODA") self.horizontalSlider_ooda = QtWidgets.QSlider(self.groupBox_2) self.horizontalSlider_ooda.setGeometry(QtCore.QRect(138, 168, 430, 17)) self.horizontalSlider_ooda.setMaximum(9) self.horizontalSlider_ooda.setMinimum(1) self.horizontalSlider_ooda.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_ooda.setObjectName("horizontalSlider_ooda") self.label_ooda = QtWidgets.QLabel(self.groupBox_2) self.label_ooda.setGeometry(QtCore.QRect(570, 164, 31, 25)) self.label_ooda.setObjectName("label_ooda") self.label_13 = QtWidgets.QLabel(self.groupBox_2) self.label_13.setGeometry(QtCore.QRect(10, 197, 121, 25)) self.label_13.setObjectName("label_13") self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.groupBox_2) self.doubleSpinBox.setGeometry(QtCore.QRect(121, 197, 100, 31)) self.doubleSpinBox.setDecimals(5) self.doubleSpinBox.setSingleStep(1e-05) self.doubleSpinBox.setObjectName("doubleSpinBox") self.verticalLayout_2.addWidget(self.groupBox_2) self.groupBox = QtWidgets.QGroupBox(self.centralwidget) self.groupBox.setMinimumSize(QtCore.QSize(30, 70)) self.groupBox.setObjectName("groupBox") self.radioButton = QtWidgets.QRadioButton(self.groupBox) self.radioButton.setGeometry(QtCore.QRect(10, 30, 60, 30)) self.radioButton.setChecked(True) self.radioButton.setObjectName("radioButton") self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox) self.radioButton_2.setGeometry(QtCore.QRect(100, 30, 226, 30)) self.radioButton_2.setObjectName("radioButton_2") self.pushButton = QtWidgets.QPushButton(self.groupBox) self.pushButton.setGeometry(QtCore.QRect(250, 30, 100, 30)) self.pushButton.setMaximumSize(QtCore.QSize(100, 16777215)) self.pushButton.setIconSize(QtCore.QSize(16, 16)) self.pushButton.setObjectName("pushButton") self.pushButtonStop = QtWidgets.QPushButton(self.groupBox) self.pushButtonStop.setGeometry(QtCore.QRect(380, 30, 100, 30)) self.pushButtonStop.setMaximumSize(QtCore.QSize(100, 16777215)) self.pushButtonStop.setIconSize(QtCore.QSize(16, 16)) self.pushButtonStop.setObjectName("pushButtonStop") self.verticalLayout_2.addWidget(self.groupBox) self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget) self.groupBox_5.setMinimumSize(QtCore.QSize(30, 155)) self.groupBox_5.setObjectName("groupBox_5") self.verticalLayout_2.addWidget(self.groupBox_3) self.verticalLayout_2.addWidget(self.groupBox_5) self.graphicsViewRec = PlotWidget(self.groupBox_5) self.graphicsViewRec.setGeometry(QtCore.QRect(115, 37, 480, 110)) self.graphicsViewRec.setObjectName("graphicsViewRec") self.graphicsViewRec.setYRange(-20000, 20000, padding=0) self.graphicsViewRec.setXRange(0, 10 * 125 * 94, padding=0) self.pushButtonRecord = QtWidgets.QPushButton(self.groupBox_5) self.pushButtonRecord.setGeometry(QtCore.QRect(10, 37, 100, 30)) self.pushButtonRecord.setMaximumSize(QtCore.QSize(100, 16777215)) self.pushButtonRecord.setIconSize(QtCore.QSize(16, 16)) self.pushButtonRecord.setObjectName("pushButtonRecord") self.pushButtonStopRecord = QtWidgets.QPushButton(self.groupBox_5) self.pushButtonStopRecord.setGeometry(QtCore.QRect(10, 77, 100, 30)) self.pushButtonStopRecord.setMaximumSize(QtCore.QSize(100, 16777215)) self.pushButtonStopRecord.setIconSize(QtCore.QSize(16, 16)) self.pushButtonStopRecord.setObjectName("pushButtonStopRecord") self.pushButtonPlay = QtWidgets.QPushButton(self.groupBox_5) self.pushButtonPlay.setGeometry(QtCore.QRect(10, 117, 100, 30)) self.pushButtonPlay.setMaximumSize(QtCore.QSize(100, 16777215)) self.pushButtonPlay.setIconSize(QtCore.QSize(16, 16)) self.pushButtonPlay.setObjectName("pushButtonPlay") self.tabs = QtWidgets.QTabWidget(self.groupBox_4) self.tabs.setGeometry(QtCore.QRect(10, 440, 600, 400)) self.tabs.setMinimumHeight(400) self.tabs.setMinimumWidth(600) self.tabs.setIconSize(QtCore.QSize(30, 300)) self.tableWidget = QtWidgets.QTableWidget() self.tableWidget.setRowCount(5) self.tableWidget.setColumnCount(5) self.tableWidget.setHorizontalHeaderLabels( ["Angry", "Happy", "Sad", "Normal", " Total "]) # self.tableWidget.setVerticalHeaderLabels( ["Angry", "Happy", "Sad", "Normal", "Total"]) # self.tableWidget.setItem(0, 0, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(0, 1, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(0, 2, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(0, 4, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(1, 0, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(1, 1, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(1, 2, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(1, 3, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(1, 4, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(2, 0, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(2, 1, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(2, 2, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(2, 3, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(2, 4, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(3, 0, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(3, 1, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(3, 2, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(3, 3, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(3, 4, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(4, 0, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(4, 1, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(4, 2, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(4, 3, QtWidgets.QTableWidgetItem("0")) self.tableWidget.setItem(4, 4, QtWidgets.QTableWidgetItem("0")) self.tableWidget.item(4, 4).setBackground(QtGui.QColor(102, 140, 255)) self.tableWidget.item(3, 3).setBackground(QtGui.QColor(125, 125, 125)) self.tableWidget.item(2, 2).setBackground(QtGui.QColor(125, 125, 125)) self.tableWidget.item(1, 1).setBackground(QtGui.QColor(125, 125, 125)) self.tableWidget.item(0, 0).setBackground(QtGui.QColor(125, 125, 125)) for i in range(5): for j in range(5): self.tableWidget.item(i, j).setFlags(QtCore.Qt.ItemIsEnabled) self.tabs.resize(650, 425) self.label_7 = QtWidgets.QLabel(self.groupBox_4) self.label_7.setMinimumSize(QtCore.QSize(600, 425)) self.label_7.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor)) self.label_7.setStyleSheet("font: 9pt \"Sans Serif\";\n" "background-color: rgb(0, 0, 0);") self.label_7.setFrameShadow(QtWidgets.QFrame.Raised) self.label_7.setLineWidth(4) self.label_7.setTextFormat(QtCore.Qt.AutoText) self.label_7.setScaledContents(True) self.label_7.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.label_7.setWordWrap(True) self.label_7.setIndent(0) self.label_7.setOpenExternalLinks(False) self.label_7.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse) self.label_7.setObjectName("label_7") self.verticalLayoutTable = QtWidgets.QVBoxLayout() self.verticalLayoutTable.setSizeConstraint( QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayoutTable.setContentsMargins(33, 95, 33, 70) self.verticalLayoutTable.setSpacing(9) self.verticalLayoutTable.setObjectName("verticalLayoutTable") self.label_total = QtWidgets.QLabel(self.groupBox_4) self.label_total.setObjectName("label_nr") self.tab2 = QtWidgets.QWidget() self.tabs.addTab(self.label_7, "Logs") self.tabs.addTab(self.tab2, "Confusion matrix") self.tab2.layout = self.verticalLayoutTable self.tab2.layout.addWidget(self.tableWidget) self.tab2.layout.addWidget(self.label_total) self.tab2.setLayout(self.tab2.layout) self.verticalLayout_2.addWidget(self.label_2) self.verticalLayout_2.addWidget(self.progressBar) self.verticalLayout_2.addWidget(self.label_3) self.verticalLayout_2.addWidget(self.progressBar_2) self.verticalLayout_2.addWidget(self.label_4) self.verticalLayout_2.addWidget(self.progressBar_3) self.verticalLayout_2.addWidget(self.label_5) self.verticalLayout_2.addWidget(self.progressBar_4) self.gridLayout.addLayout(self.verticalLayout_2, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.actionReset = QtWidgets.QAction(MainWindow) self.actionReset.setObjectName("actionReset") self.retranslateUi(MainWindow) self.lineEdit_2.setText("Inference") self.lineEdit.setText("10") self.horizontalSlider_2.setValue(5) self.change_label_16() self.horizontalSlider.setValue(8) self.change_label_12() self.horizontalSlider_ooda.setValue(8) self.change_label_ooda() self.doubleSpinBox.setValue(0.0001) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.fill_file() self.ooda_check_box.setChecked(False) self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED) self.horizontalSlider_ooda.setEnabled(False) self.pushButton.clicked.connect(lambda: self.on_start_button_clicked()) self.pushButtonStop.clicked.connect( lambda: self.on_buttonStop_clicked()) self.pushButtonRecord.clicked.connect( lambda: self.on_buttonRecord_clicked()) self.pushButtonPlay.clicked.connect(lambda: self.play_recording()) self.pushButtonInfPlay.clicked.connect( lambda: self.play_recording(self.comboBox_2.currentText())) self.pushButtonStopRecord.clicked.connect( lambda: self.on_buttonStopRecord_clicked()) self.lineEdit_2.returnPressed.connect(lambda: self.fill_file()) self.radioButton_2.toggled.connect(lambda: self.init_inference()) self.horizontalSlider.valueChanged.connect( lambda: self.change_label_12()) self.horizontalSlider_2.valueChanged.connect( lambda: self.change_label_16()) self.horizontalSlider_ooda.valueChanged.connect( lambda: self.change_label_ooda()) self.ooda_check_box.stateChanged.connect( lambda: self.change_horizontal_ooda()) self.print_accuracy_graph(0) def refresh_label_7(self): self.label_7_line_nr = 0 _translate = QtCore.QCoreApplication.translate self.label_7.setText( _translate( "MainWindow", "<html><head/><body><p><span style=\" font-weight:600; color:#55ff7f;\"> ...</span></p></body></html>" )) def refresh_graphics_view(self): self.graphicsView.clear() self.accuracy_vals = [] self.print_accuracy_graph(0) def refresh_rec_graphics_view(self): self.recording_vals = np.zeros([ 960 * 10 * 10, ]) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle( _translate("MainWindow", "Speech Emotion Recognizer")) self.groupBox_4.setTitle(_translate("MainWindow", "Statistics")) self.groupBox_5.setTitle(_translate("MainWindow", "Recording")) self.label_2.setText(_translate("MainWindow", "Angry")) self.label_3.setText(_translate("MainWindow", "Happy")) self.label_4.setText(_translate("MainWindow", "Sad")) self.label_5.setText(_translate("MainWindow", "Neutral")) self.groupBox_3.setTitle( _translate("MainWindow", "Pick a file to classify")) self.label_9.setText(_translate("MainWindow", "Folder path:")) self.label_10.setText(_translate("MainWindow", "File:")) self.pushButtonInfPlay.setText(_translate("MainWindow", "Play")) self.groupBox_2.setTitle(_translate("MainWindow", "Model settings")) self.radioButton_3.setText(_translate("MainWindow", "End-to-end")) self.radioButton_4.setText(_translate("MainWindow", "Hand-Crafted")) self.label_8.setText(_translate("MainWindow", "Epochs:")) self.label_18.setText( _translate("MainWindow", "Feature extraction tehnioque:")) self.label_11.setText(_translate("MainWindow", "Train / Test Ratio:")) self.label_12.setText(_translate("MainWindow", "1")) self.label_13.setText(_translate("MainWindow", "Learning Rate:")) self.label_15.setText(_translate("MainWindow", "Dropout Rate:")) self.label_16.setText(_translate("MainWindow", "1")) self.label_17.setText(_translate("MainWindow", "Current epoch:")) self.label_19.setText(_translate("MainWindow", "0")) self.label_ooda.setText(_translate("MainWindow", "0")) self.label_total.setText( _translate("MainWindow", "Numarul total de intrari = 0")) self.comboBox.setItemText(0, _translate("MainWindow", "EMO-DB")) self.comboBox.setItemText(1, _translate("MainWindow", "SAVEE")) self.comboBox.setItemText(2, _translate("MainWindow", "RAVDESS")) self.comboBox.setItemText(3, _translate("MainWindow", "ENTERFACE")) self.comboBox.setItemText(4, _translate("MainWindow", "EMOVO")) self.comboBox.setItemText(5, _translate("MainWindow", "MAV")) self.comboBox.setItemText(6, _translate("MainWindow", "MELD")) self.comboBox.setItemText(7, _translate("MainWindow", "JL")) self.comboBox.setItemText(7, _translate("MainWindow", "INRP")) self.comboBox.setItemText(8, _translate("MainWindow", "MULTIPLE")) self.ooda_check_box.setText(_translate("MainWindow", "OODA loop")) self.label.setText(_translate("MainWindow", "Select dataset:")) self.groupBox.setTitle(_translate("MainWindow", "Actions")) self.radioButton.setToolTip( _translate( "MainWindow", "<html><head/><body><p align=\"center\"><br/></p></body></html>" )) self.radioButton.setText(_translate("MainWindow", "Train")) self.radioButton_2.setText(_translate("MainWindow", "Inference")) self.pushButton.setText(_translate("MainWindow", "Start")) self.pushButtonStop.setText(_translate("MainWindow", "Stop")) self.pushButtonRecord.setText(_translate("MainWindow", "Record")) self.pushButtonPlay.setText(_translate("MainWindow", "Play")) self.pushButtonStopRecord.setText(_translate("MainWindow", "Stop")) self.label_7.setText( _translate( "MainWindow", "<html><head/><body><p><span style=\" font-weight:600; color:#55ff7f;\"> ...</span></p></body></html>" )) self.actionReset.setText(_translate("MainWindow", "Reset")) self.pushButtonRecord.setEnabled(False) self.pushButtonStopRecord.setEnabled(False) self.pushButtonStop.setEnabled(False) self.pushButtonPlay.setEnabled(False) self.pushButtonInfPlay.setEnabled(False) self.progressBar.setEnabled(False) self.progressBar_2.setEnabled(False) self.progressBar_3.setEnabled(False) self.progressBar_4.setEnabled(False) self.label_2.setEnabled(False) self.label_3.setEnabled(False) self.label_4.setEnabled(False) self.label_5.setEnabled(False) self.groupBox_3.setEnabled(False) self.groupBox_5.setEnabled(False) self.graphicsViewRec.setYRange(-20000, 20000, padding=0) self.graphicsViewRec.setXRange(0, 10 * 960 * 10, padding=0) self.graphicsViewRec.getPlotItem().hideButtons() self.graphicsViewRec.getPlotItem().hideAxis('left') self.graphicsViewRec.getPlotItem().hideAxis('bottom') def print_accuracy_graph(self, accuracy): self.accuracy_vals.append(accuracy) self.graphicsView.plot(self.accuracy_vals) def print_recording_graph(self, frames=None): self.graphicsViewRec.clear() self.recording_vals[0:9 * 960 * 10] = self.recording_vals[1 * 960 * 10:10 * 10 * 960] self.recording_vals[9 * 960 * 10:10 * 960 * 10] = frames self.graphicsViewRec.plot(self.recording_vals) def print_stats_model(self, string): self.print_in_label_7(string) def print_label_19(self, epoch): self.label_19.setText(epoch) def print_accuracy_matrix(self, matrix): for i in range(matrix.shape[0]): for j in range(matrix.shape[1]): self.tableWidget.setItem( i, j, QtWidgets.QTableWidgetItem(str(matrix[i][j]))) for i in range(4): self.tableWidget.setItem( 4, i, QtWidgets.QTableWidgetItem(str(np.sum(matrix[:, i])))) self.tableWidget.setItem( i, 4, QtWidgets.QTableWidgetItem(str(np.sum(matrix[i])))) self.tableWidget.setItem( 4, 4, QtWidgets.QTableWidgetItem(str(np.sum(np.diag(matrix))))) self.tableWidget.item(4, 4).setBackground(QtGui.QColor(102, 140, 255)) self.tableWidget.item(3, 3).setBackground(QtGui.QColor(125, 125, 125)) self.tableWidget.item(2, 2).setBackground(QtGui.QColor(125, 125, 125)) self.tableWidget.item(1, 1).setBackground(QtGui.QColor(125, 125, 125)) self.tableWidget.item(0, 0).setBackground(QtGui.QColor(125, 125, 125)) for i in range(5): for j in range(5): self.tableWidget.item(i, j).setFlags(QtCore.Qt.ItemIsEnabled) def open_alert_dialog(self, title="Alert", text="...", info="..."): msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Critical) msg.setWindowTitle(title) msg.setText(text) msg.setInformativeText(info) msg.setStandardButtons(QtWidgets.QMessageBox.Ok) msg.exec_() def on_start_button_clicked(self): if self.radioButton.isChecked(): # training self.pushButton.setEnabled(False) self.pushButtonStop.setEnabled(True) self.radioButton_2.setEnabled(False) self.refresh_label_7() self.refresh_graphics_view() self.train_thread = Train_App(self) self.train_thread.print_accuracy_signal.connect( self.print_accuracy_graph) self.train_thread.print_stats.connect(self.print_stats_model) self.train_thread.print_matrix.connect(self.print_accuracy_matrix) self.train_thread.print_epoch.connect(self.print_label_19) self.train_thread.start() elif self.radioButton_2.isChecked(): # inference vals = self.ser_inference_model.inference( self.comboBox_2.currentText()) * 100 self.progressBar.setValue(vals[0]) self.progressBar_2.setValue(vals[1]) self.progressBar_3.setValue(vals[2]) self.progressBar_4.setValue(vals[3]) self.print_in_label_7(str(list(map('{:.8f}'.format, vals)))) pass def on_buttonStop_clicked(self): if self.train_thread != None: self.train_thread.stopFlag = True pass def change_label_16(self): self.label_16.setText(str(float(self.horizontalSlider_2.value()) / 10)) def change_label_12(self): self.label_12.setText(str(float(self.horizontalSlider.value()) / 10)) def change_label_ooda(self): self.label_ooda.setText( str(float(self.horizontalSlider_ooda.value()) / 10)) def change_horizontal_ooda(self): if self.ooda_check_box.isChecked(): self.horizontalSlider_ooda.setStyleSheet(SLYDER_ENABLED) self.horizontalSlider_ooda.setEnabled(True) else: self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED) self.horizontalSlider_ooda.setEnabled(False) self.label_ooda.setEnabled(self.ooda_check_box.isChecked()) def fill_file(self): self.ser_inference_model.files = get_files_from_directory( self.lineEdit_2.text()) self.comboBox_2.clear() for file in self.ser_inference_model.files: self.comboBox_2.addItem(file) if self.radioButton_2.isChecked(): # inference self.pushButton.setEnabled(True) self.pushButtonInfPlay.setEnabled(True) self.ser_inference_model.init_model(self.lineEdit_2.text()) if self.ser_inference_model.model == None: self.open_alert_dialog( title="Missing Inference inference_files Alert", text= "We could no find any inference_files to classify in the stated folder.", info= "You can continue the inference process by using the online model." ) self.pushButton.setEnabled(False) self.pushButtonInfPlay.setEnabled(False) self.ser_online_model.init_online_model() def init_inference(self): if self.radioButton_2.isChecked(): # inference if self.radioButton_4.isChecked(): self.open_alert_dialog( title= "Inference is not available for hand-crafted extraction", text= "Hand-crafted feature extraction is used only as a baseline.", info= "Please train your model using the end-to-ed extraction method in order to make inference available." ) self.radioButton.setChecked(True) self.radioButton_2.setChecked(False) return if [f for f in os.listdir("model") if not f.startswith('.')] == []: self.open_alert_dialog( title="Missing model for Inference", text="There is no machine learning model to be loaded.", info= "Please use the training mode to train a model before inference." ) self.radioButton.setChecked(True) self.radioButton_2.setChecked(False) return self.pushButtonRecord.setEnabled(True) self.pushButtonInfPlay.setEnabled(True) self.progressBar.setEnabled(True) self.progressBar_2.setEnabled(True) self.progressBar_3.setEnabled(True) self.progressBar_4.setEnabled(True) self.label_2.setEnabled(True) self.label_3.setEnabled(True) self.label_4.setEnabled(True) self.label_5.setEnabled(True) self.groupBox_3.setEnabled(True) self.groupBox_5.setEnabled(True) self.groupBox_2.setEnabled(False) self.horizontalSlider.setStyleSheet(SLYDER_DISABLED) self.horizontalSlider.setEnabled(False) self.horizontalSlider_2.setStyleSheet(SLYDER_DISABLED) self.horizontalSlider_2.setEnabled(False) self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED) self.horizontalSlider_ooda.setEnabled(False) self.ser_inference_model.init_model(self.lineEdit_2.text()) if self.ser_inference_model.model == None: self.open_alert_dialog( title="Missing Inference inference_files Alert", text= "We could no find any inference_files to classify in the stated folder.", info= "You can continue the inference process by using the online model." ) self.pushButton.setEnabled(False) self.pushButtonInfPlay.setEnabled(False) self.ser_online_model.init_online_model() elif self.ser_inference_model.session != None and self.radioButton.isChecked( ): self.pushButton.setEnabled(True) self.groupBox_2.setEnabled(True) self.pushButtonRecord.setEnabled(False) self.pushButtonInfPlay.setEnabled(False) self.pushButtonStopRecord.setEnabled(False) self.progressBar.setValue(0) self.progressBar.setEnabled(False) self.progressBar_2.setValue(0) self.progressBar_2.setEnabled(False) self.progressBar_3.setValue(0) self.progressBar_3.setEnabled(False) self.progressBar_4.setValue(0) self.progressBar_4.setEnabled(False) self.label_2.setEnabled(False) self.label_3.setEnabled(False) self.label_4.setEnabled(False) self.label_5.setEnabled(False) self.groupBox_3.setEnabled(False) self.groupBox_5.setEnabled(False) self.horizontalSlider.setStyleSheet(SLYDER_ENABLED) self.horizontalSlider.setEnabled(True) self.horizontalSlider_2.setStyleSheet(SLYDER_ENABLED) self.horizontalSlider_2.setEnabled(True) self.change_horizontal_ooda() self.ser_inference_model.close_model() def on_buttonRecord_clicked(self): self.refresh_rec_graphics_view() self.microphone_recorder = MicrophoneRecorder() if not self.microphone_recorder.check_device_availability(): return self.recorder_thread = Record_App(self, self.microphone_recorder) self.recorder_thread.print_recording_signal.connect( self.print_recording_graph) self.recorder_thread.start() self.pushButtonStopRecord.setEnabled(True) self.pushButton.setEnabled(False) self.pushButtonInfPlay.setEnabled(False) self.pushButtonPlay.setEnabled(False) def on_buttonStopRecord_clicked(self): import librosa import pyaudio self.microphone_recorder.close() vals = [] if np.array(self.microphone_recorder.get_frames()).shape[0] > 30: self.pushButtonPlay.setEnabled(True) self.microphone_recorder.save_to_wav() frames, _ = librosa.load("output.wav", 16000) vals = self.ser_online_model.online(frames, 44100) * 100 else: self.pushButtonPlay.setEnabled(False) vals = [0 for _ in range(4)] self.progressBar.setValue(vals[0]) self.progressBar_2.setValue(vals[1]) self.progressBar_3.setValue(vals[2]) self.progressBar_4.setValue(vals[3]) self.print_in_label_7(str(list(map('{:.8f}'.format, vals)))) self.pushButton.setEnabled(True) self.pushButtonRecord.setEnabled(True) self.pushButtonStopRecord.setEnabled(False) self.pushButtonInfPlay.setEnabled(True) self.pushButtonPlay.setEnabled(True) def print_in_label_7(self, str): _translate = QtCore.QCoreApplication.translate self.label_7_line_nr += 1 if self.label_7_line_nr >= 24: txt = self.label_7.text().split("<html>") txt = "<html>".join(txt[1:25]) self.label_7.setText( _translate( "MainWindow", txt + "<html><head/><body><span style=\" font-weight:600; color:#55ff7f;\">" + str + "</span></body></html>")) else: self.label_7.setText( _translate( "MainWindow", self.label_7.text() + "<html><head/><body><span style=\" font-weight:600; color:#55ff7f;\">" + str + "</span></body></html>")) import time def play_recording(self, file="output.wav"): self.play_th = Play_App(self, file) self.play_th.start()
class MaskInterpolator(QWidget): """ Define masks based on an image file for two frames, then interpolate the masks for the intermediate frames. Also includes options to apply these masks to a target file. """ def __init__(self, parent=None): super(MaskInterpolator, self).__init__(parent=parent) self.initUI() def initUI(self): # Main layout self.win = QWidget() L_master = QGridLayout(self.win) self.win.setWindowTitle("Mask interpolator") # Widget alignment widget_align = Qt.AlignLeft # Display the masks, when defined self.plotWidget = PlotWidget() L_master.addWidget(self.plotWidget, 0, 0, 1, 2, alignment=widget_align) # Button to select the first mask file self.B_select_mask_0 = QPushButton("Choose mask channel file 1", parent=self.win) self.B_select_mask_0.clicked.connect(self.B_select_mask_0_callback) L_master.addWidget(self.B_select_mask_0, 1, 0, 1, 1, alignment=widget_align) # Show the currently selected mask file 1 self.mask_file_0_label = QLabel(parent=self.win) L_master.addWidget(self.mask_file_0_label, 2, 0, 1, 1, alignment=widget_align) # Generate the first set of masks self.B_generate_masks_0 = QPushButton("Draw mask 1", parent=self.win) self.B_generate_masks_0.clicked.connect(self.B_generate_masks_0_callback) L_master.addWidget(self.B_generate_masks_0, 3, 0, 1, 1, alignment=widget_align) # Alternatively, load masks from an existing file self.B_load_mask_0 = QPushButton("Load mask 1", parent=self.win) self.B_load_mask_0.clicked.connect(self.B_load_mask_0_callback) L_master.addWidget(self.B_load_mask_0, 4, 0, 1, 1, alignment=widget_align) # Button to select the second mask file self.B_select_mask_1 = QPushButton("Choose mask channel file 2", parent=self.win) self.B_select_mask_1.clicked.connect(self.B_select_mask_1_callback) L_master.addWidget(self.B_select_mask_1, 5, 0, 1, 1, alignment=widget_align) # Show the currently selected mask file 2 self.mask_file_1_label = QLabel(parent=self.win) L_master.addWidget(self.mask_file_1_label, 6, 0, 1, 1, alignment=widget_align) # Generate the first set of masks self.B_generate_masks_1 = QPushButton("Draw mask 2", parent=self.win) self.B_generate_masks_1.clicked.connect(self.B_generate_masks_1_callback) L_master.addWidget(self.B_generate_masks_1, 7, 0, 1, 1, alignment=widget_align) # Alternatively, load masks from an existing file self.B_load_mask_1 = QPushButton("Load mask 2", parent=self.win) self.B_load_mask_1.clicked.connect(self.B_load_mask_1_callback) L_master.addWidget(self.B_load_mask_1, 8, 0, 1, 1, alignment=widget_align) # Apply the set of masks to a file self.B_apply = QPushButton("Apply masks", parent=self) self.B_apply.clicked.connect(self.B_apply_callback) L_master.addWidget(self.B_apply, 9, 0, 1, 1, alignment=widget_align) # Show the main window self.win.show() ## CORE FUNCTIONS def get_currdir(self): """ Get the last directory that was accessed by the user. If no directory was previously accessed, then this is just the same directory as the image file. """ if not hasattr(self, "_currdir"): self.set_currdir(os.getcwd()) return self._currdir def set_currdir(self, path): """ Set the directory returned by self.get_currdir(). args ---- path : str, a file path or directory path. If a file path, its parent directory is used. """ if os.path.isfile(path): self._currdir = os.path.split(os.path.abspath(path))[0] elif os.path.isdir(path): self._currdir = path def update_label(self, text, label=0): """ args ---- text : str, text to display in the QLabel label : 0 or 1, corresponding to self.mask_file_0_label or self.mask_file_1_label respectively """ if label == 0: self.mask_file_0_label.setText(text) elif label == 1: self.mask_file_1_label.setText(text) def select_mask_file(self, index): """ Prompt the user to select an image file to user for masking. args ---- index : int, either 0 or 1. If 0, the first mask file is selected and otherwise the second mask is selected """ path = getOpenFilePath(self.win, "Select masking channel file %d" % (index+1), "Image files (*.tif *.tiff *.nd2)", initialdir=self.get_currdir()) self.set_currdir(path) self.update_label("{} (no masks defined)".format(path), label=index) setattr(self, "mask_path_{}".format(index), path) # Delete previously defined masks, if any if hasattr(self, "mask_edges_{}".format(index)): delattr(self, "mask_edges_{}".format(index)) def load_mask(self, index, trial_interpolate=False, plot=False): """ Load preexisting masks from a file. """ # Prompt the user to enter a mask definitions file path = getOpenFilePath(self.win, "Select mask definitions %d" % (index+1), "Mask edge or image files (*.csv *.tif *.tiff *.nd2)", initialdir=self.get_currdir()) self.set_currdir(path) # Delete the previously defined masks, if any if hasattr(self, "mask_path_{}".format(index)): delattr(self, "mask_path_{}".format(index)) if hasattr(self, "mask_edges_{}".format(index)): delattr(self, "mask_edges_{}".format(index)) # Calculate edges from this mask ext = os.path.splitext(path)[-1] if ext == ".csv": try: df = pd.read_csv(path) for c in ["filename", "mask_index", "y", "x", "vertex"]: assert c in df.columns except: print("File {} not in the correct format; must be a CSV with " \ "the 'filename', 'mask_index', 'y', 'x', and 'vertex' " \ "columns".format(path)) return # Take only the first mask encountered mask_indices = df["mask_index"].unique() points = [np.asarray(df.loc[df["mask_index"] == mask_indices[0], ["y", "x"]])] elif ext in [".tif", ".tiff", ".nd2"]: with ImageReader(path) as f: mask_im = f.get_frame(0) edges = get_edges(mask_im>0) points = [get_ordered_mask_points(edges, max_points=200)] setattr(self, "mask_edges_{}".format(index), points) setattr(self, "mask_path_{}".format(index), path) self.update_label("{} ({} masks defined)".format(path, len(points)), index) # Show a trial interpolation (only if the other # mask is also defined) if trial_interpolate and hasattr(self, "mask_edges_{}".format(1-index)): interpolator = QuotMaskInterpolator( [self.mask_edges_0[0], self.mask_edges_1[0]], [0, 100], n_vertices=101, interp_kind="linear", plot=False, ) self.plot_mask_edges_interpolated(interpolator) elif plot: edges_0 = getattr(self, "mask_edges_0") if hasattr(self, "mask_edges_0") else None edges_1 = getattr(self, "mask_edges_1") if hasattr(self, "mask_edges_1") else None self.plot_mask_edges(edges_0=edges_0, edges_1=edges_1) def generate_masks(self, index, plot=False, trial_interpolate=False): """ Prompt the user to define some masks. args ---- index : int, either 0 or 1. If 0, generate masks from self.mask_path_0. If 1, generate masks from self.mask_path_1. plot : bool, update the plot with the new masks trial_interpolate : bool, show a trial interpolation """ # If the user has not yet selected a mask file, bail if not hasattr(self, "mask_path_{}".format(index)): print("Mask file {} not selected".format(index)) return else: path = getattr(self, "mask_path_{}".format(index)) # Prompt the user to enter some masks ex = Masker(path, dialog_mode=True, parent=self.win) # If the user accepts the definitions, save if ex.exec_() == QDialog.Accepted: setattr(self, "mask_edges_{}".format(index), ex.return_val) self.update_label("{} ({} masks defined)".format(path, len(ex.return_val)), index) # Show a trial interpolation (only if the other # mask is also defined) if trial_interpolate and hasattr(self, "mask_edges_{}".format(1-index)): interpolator = QuotMaskInterpolator( [self.mask_edges_0[0], self.mask_edges_1[0]], [0, 100], n_vertices=101, interp_kind="linear", plot=False, ) self.plot_mask_edges_interpolated(interpolator) elif plot: edges_0 = getattr(self, "mask_edges_0") if hasattr(self, "mask_edges_0") else None edges_1 = getattr(self, "mask_edges_1") if hasattr(self, "mask_edges_1") else None self.plot_mask_edges(edges_0=edges_0, edges_1=edges_1) else: print("Dialog canceled") def plot_mask_edges(self, edges_0=None, edges_1=None): """ Plot a set of mask edges on the raw image. args ---- edges_0 : list of 2D ndarray of shape (n_points, 2), the YX coordinates of each mask in the first set edges_1 : list of 2D ndarray of shape (n_points, 2), the YX coordinates of each mask in the second set """ self.plotWidget.clear() if not edges_0 is None: for mask_edge in edges_0: M = np.concatenate((mask_edge, np.array([mask_edge[0,:]])), axis=0) self.plotWidget.plot(M[:,0], M[:,1], pen=(127, 253, 186)) if not edges_1 is None: for mask_edge in edges_1: M = np.concatenate((mask_edge, np.array([mask_edge[0,:]])), axis=0) self.plotWidget.plot(M[:,0], M[:,1], pen=(36, 255, 28)) def plot_mask_edges_interpolated(self, quot_mask_interpolator): """ Plot the interpolated set of mask edges. args ---- quot_mask_interpolated : quot.mask.MaskInterpolator """ E = quot_mask_interpolator.mask_edges mask_edges_0 = [E[:,0,:]] mask_edges_1 = [E[:,1,:]] self.plot_mask_edges(edges_0=mask_edges_0, edges_1=mask_edges_1) for j in range(E.shape[0]): self.plotWidget.plot( [mask_edges_0[0][j,0], mask_edges_1[0][j,0]], [mask_edges_0[0][j,1], mask_edges_1[0][j,1]], pen=(255, 165, 28) ) def apply_masks(self, mode="single_point"): """ Apply the currently defined masks to a set of localizations. """ if not hasattr(self, "mask_edges_0"): print("Must define masks before applying to an image") return # Prompt the user to select a file to apply the masks to locs_file = getOpenFilePath(self.win, "Select localization CSV", "CSV files (*.csv)", initialdir=self.get_currdir()) self.set_currdir(locs_file) locs = pd.read_csv(locs_file) # Only one set of masks defined - run static masking if not hasattr(self, "mask_edges_1"): mask_edges = [self.mask_edges_0[0]] mask_frames = [0] # Both sets of masks defined - run mask interpolation else: mask_edges = [self.mask_edges_0[0], self.mask_edges_1[0]] mask_frames = [0, int(locs["frame"].max()+1)] # Generate the mask interpolator print("Generating interpolator...") interpolator = QuotMaskInterpolator(mask_edges, mask_frames, n_vertices=101, interp_kind="linear", plot=False) # Plot the interpolated masks self.plot_mask_edges_interpolated(interpolator) # Run interpolation on the target set of localizations print("Running masking on the set of localizations...") locs["mask_index"] = interpolator(locs[['y', 'x']], locs['frame'], progress_bar=True) print(locs["mask_index"].unique()) if mode == "single_point": locs = locs.join( locs.groupby("trajectory")["mask_index"].max().rename("_mask_index"), on="trajectory" ) locs["mask_index"] = locs["_mask_index"] locs = locs.drop("_mask_index", axis=1) elif mode == "all_points": locs = locs.join( (locs.groupby("trajectory")["mask_index"].nunique() != 1).rename("_cross_border"), on="trajectory" ) locs.loc[locs["_cross_border"], "mask_index"] = 0 locs = locs.drop("_cross_border", axis=1) # Save to the same file print("Saving masked localizations to new files...") out_file_inside = "{}_in_mask.csv".format(os.path.splitext(locs_file)[0]) out_file_outside = "{}_outside_mask.csv".format(os.path.splitext(locs_file)[0]) locs[locs["mask_index"]>0].to_csv(out_file_inside, index=False) locs[locs["mask_index"]==0].to_csv(out_file_outside, index=False) print(locs["mask_index"].unique()) print("Finished applying mask to localizations; now plotting...") point_sets = [ interpolator.interpolate(frame)for frame \ in np.linspace( 0, int(locs["frame"].max()), 50 ).astype(np.int64) ] show_mask_assignments( point_sets, locs, mask_col="mask_index", max_points_scatter=5000 ) print("Finished plotting") ## WIDGET CALLBACKS def B_select_mask_0_callback(self): self.select_mask_file(0) def B_load_mask_0_callback(self): self.load_mask(0, plot=True, trial_interpolate=True) def B_select_mask_1_callback(self): self.select_mask_file(1) def B_generate_masks_0_callback(self): self.generate_masks(0, plot=True, trial_interpolate=True) def B_load_mask_1_callback(self): self.load_mask(1, plot=True, trial_interpolate=True) def B_generate_masks_1_callback(self): self.generate_masks(1, trial_interpolate=True, plot=True) def B_apply_callback(self): # Prompt the user to select the way to apply masks options = ["by_localization", "single_point", "all_points"] box = SingleComboBoxDialog("Method by which trajectories are assigned to masks", options, init_value="single_point", title="Assignment mode", parent=self) box.exec_() if box.Accepted: mode = box.return_val else: print("Dialog not accepted") return self.apply_masks(mode=mode)
class Ui_MainWindow(QDialog): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(926, 645) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.widget = PlotWidget(self.centralwidget) self.widget.setGeometry(QtCore.QRect(20, 30, 611, 381)) self.widget.setObjectName("widget") self.widget.setBackground('w') self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(660, 430, 112, 34)) self.pushButton.setObjectName("pushButton") self.pushButton.clicked.connect(self.browsefiles) #click function self.buttonclear = QtWidgets.QPushButton(self.centralwidget) self.buttonclear.setGeometry(QtCore.QRect(500, 450, 112, 34)) self.buttonclear.setObjectName("clearbutton") self.buttonclear.clicked.connect(self.cleargraph) #click function self.horizontalScrollBar = QtWidgets.QScrollBar(self.centralwidget) self.horizontalScrollBar.setGeometry(QtCore.QRect(10, 430, 621, 20)) self.horizontalScrollBar.setOrientation(QtCore.Qt.Horizontal) self.horizontalScrollBar.setObjectName("horizontalScrollBar") self.verticalScrollBar = QtWidgets.QScrollBar(self.centralwidget) self.verticalScrollBar.setGeometry(QtCore.QRect(640, 40, 20, 381)) self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical) self.verticalScrollBar.setObjectName("verticalScrollBar") self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) self.verticalLayoutWidget.setGeometry(QtCore.QRect(689, 19, 181, 401)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setObjectName("verticalLayout") self.checkBoxTemp = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxTemp.setEnabled(True) self.checkBoxTemp.setObjectName("checkBoxTemp") self.checkBoxTemp.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxTemp) self.checkBoxPres = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxPres.setObjectName("checkBoxPres") self.checkBoxPres.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxPres) self.checkBoxPH = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxPH.setObjectName("checkBoxPH") self.checkBoxPH.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxPH) self.checkBoxDO2 = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxDO2.setObjectName("checkBoxDO2") self.checkBoxDO2.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxDO2) self.checkBoxAIR = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxAIR.setObjectName("checkBoxAIR") self.checkBoxAIR.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxAIR) self.checkBoxO2 = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxO2.setObjectName("checkBoxO2") self.checkBoxO2.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxO2) self.checkBoxCO2 = QtWidgets.QCheckBox(self.verticalLayoutWidget) self.checkBoxCO2.setObjectName("checkBoxCO2") self.checkBoxCO2.stateChanged.connect(self.checked_item) self.verticalLayout.addWidget(self.checkBoxCO2) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 926, 31)) self.menubar.setObjectName("menubar") self.menuCharts = QtWidgets.QMenu(self.menubar) self.menuCharts.setObjectName("menuCharts") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.menubar.addAction(self.menuCharts.menuAction()) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "Export")) self.buttonclear.setText(_translate("MainWindow", "Clear")) self.checkBoxTemp.setText(_translate("MainWindow", "Temperature - Red")) self.checkBoxPres.setText(_translate("MainWindow", "Pressure - Orange")) self.checkBoxPH.setText(_translate("MainWindow", "pH - Yellow")) self.checkBoxDO2.setText(_translate("MainWindow", "dO2 - Green")) self.checkBoxAIR.setText(_translate("MainWindow", "Airflow - Blue")) self.checkBoxO2.setText(_translate("MainWindow", "O2 Flow - Purple")) self.checkBoxCO2.setText(_translate("MainWindow", "CO2 Flow - Pink")) self.menuCharts.setTitle(_translate("MainWindow", "Charts")) def browsefiles(self): fname = QFileDialog.getSaveFileName(self, 'Open File', 'D:\Documents') def cleargraph(self): if self.checkBoxTemp.isChecked(): self.checkBoxTemp.setCheckState(0) self.widget.clear() if self.checkBoxPres.isChecked(): self.checkBoxPres.setCheckState(0) self.widget.clear() if self.checkBoxPH.isChecked(): self.checkBoxPH.setCheckState(0) self.widget.clear() if self.checkBoxDO2.isChecked(): self.checkBoxDO2.setCheckState(0) self.widget.clear() if self.checkBoxAIR.isChecked(): self.checkBoxAIR.setCheckState(0) self.widget.clear() if self.checkBoxO2.isChecked(): self.checkBoxO2.setCheckState(0) self.widget.clear() if self.checkBoxCO2.isChecked(): self.checkBoxCO2.setCheckState(0) self.widget.clear() def checked_item(self): if self.checkBoxTemp.isChecked(): x = [1, 2, 3] y = [2, 3, 4] pen = pg.mkPen(color=(255, 0, 0), width=3) self.widget.plot(x, y, pen=pen) if self.checkBoxPres.isChecked(): x = [2, 3, 4] y = [2, 3, 4] pen = pg.mkPen(color=(255, 155, 55), width=3) self.widget.plot(x, y, pen=pen) if self.checkBoxPH.isChecked(): x = [3, 4, 5] y = [2, 3, 4] pen = pg.mkPen(color=(255, 255, 0), width=3) self.widget.plot(x, y, pen=pen) if self.checkBoxDO2.isChecked(): x = [4, 5, 6] y = [2, 3, 4] pen = pg.mkPen(color=(100, 200, 50), width=3) self.widget.plot(x, y, pen=pen) if self.checkBoxAIR.isChecked(): x = [5, 6, 7] y = [2, 3, 4] pen = pg.mkPen(color=(0, 0, 255), width=3) self.widget.plot(x, y, pen=pen) if self.checkBoxO2.isChecked(): x = [6, 7, 8] y = [2, 3, 4] pen = pg.mkPen(color=(200, 0, 255), width=3) self.widget.plot(x, y, pen=pen) if self.checkBoxCO2.isChecked(): x = [7, 8, 9] y = [2, 3, 4] pen = pg.mkPen(color=(248, 24, 148), width=3) self.widget.plot(x, y, pen=pen)
class Ui_StateWise(object): def setupUi(self, StateWise): QtGui.QFontDatabase.addApplicationFont( resource_path("Pictures/BankGothic Md BT.ttf")) StateWise.setObjectName("StateWise") StateWise.resize(546, 539) StateWise.setFixedSize(StateWise.size()) self.centralwidget = QtWidgets.QWidget(StateWise) self.centralwidget.setObjectName("centralwidget") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(0, 0, 546, 60)) font = QtGui.QFont() font.setFamily("BankGothic Md BT") font.setPointSize(18) font.setBold(False) font.setWeight(50) self.label.setFont(font) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(20, 100, 300, 41)) font = QtGui.QFont() font.setFamily("BankGothic Md BT") font.setPointSize(14) font.setBold(False) font.setWeight(50) self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.comboBox = QtWidgets.QComboBox(self.centralwidget) self.comboBox.setGeometry(QtCore.QRect(360, 110, 161, 22)) self.comboBox.setObjectName("comboBox") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(20, 150, 126, 60)) font = QtGui.QFont() font.setFamily("BankGothic Md BT") font.setPointSize(11) font.setBold(True) font.setWeight(100) self.label_3.setFont(font) self.label_3.setObjectName("label_3") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(145, 150, 126, 60)) font = QtGui.QFont() font.setFamily("BankGothic Md BT") font.setPointSize(11) font.setBold(True) font.setWeight(100) self.label_4.setFont(font) self.label_4.setObjectName("label_4") self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setGeometry(QtCore.QRect(270, 150, 126, 60)) font = QtGui.QFont() font.setFamily("BankGothic Md BT") font.setPointSize(11) font.setBold(True) font.setWeight(100) self.label_5.setFont(font) self.label_5.setObjectName("label_5") self.label_6 = QtWidgets.QLabel(self.centralwidget) self.label_6.setGeometry(QtCore.QRect(395, 150, 126, 60)) font = QtGui.QFont() font.setFamily("BankGothic Md BT") font.setPointSize(11) font.setBold(True) font.setWeight(100) self.label_6.setFont(font) self.label_6.setObjectName("label_6") self.graphWidget = PlotWidget(self.centralwidget) self.graphWidget.setGeometry(QtCore.QRect(20, 230, 501, 251)) self.graphWidget.setObjectName("graphWidget") StateWise.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(StateWise) self.menubar.setGeometry(QtCore.QRect(0, 0, 546, 26)) self.menubar.setObjectName("menubar") StateWise.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(StateWise) self.statusbar.setObjectName("statusbar") StateWise.setStatusBar(self.statusbar) self.comboBox.currentIndexChanged.connect(self.updates) StateWise.setStyleSheet("background-color:#fff9ea") self.comboBox_2 = QtWidgets.QComboBox(self.centralwidget) self.comboBox_2.setGeometry(QtCore.QRect(360, 485, 161, 22)) self.comboBox_2.setObjectName("comboBox_2") self.comboBox_2.currentIndexChanged.connect(self.updateGraph) self.retranslateUi(StateWise) QtCore.QMetaObject.connectSlotsByName(StateWise) def updateGraph(self): val = self.comboBox.currentText() stateCode = stateDict[val] stateDC = statedaily.loc[statedaily["Status"] == "Confirmed"] stateDR = statedaily.loc[statedaily["Status"] == "Recovered"] stateDD = statedaily.loc[statedaily["Status"] == "Deceased"] stateDCVal = list(stateDC[stateCode]) stateDRVal = list(stateDR[stateCode]) stateDDVal = list(stateDD[stateCode]) stateDates = list(stateDC["Date"]) tmp = self.comboBox_2.currentText() if (tmp == "Confirmed"): self.plot(stateDates, stateDCVal) if (tmp == "Recovered"): self.plot(stateDates, stateDRVal, c1='#C0E5C8', c2='#E4F4E8', c3='#29A746') if (tmp == "Deceased"): self.plot(stateDates, stateDDVal, c1='#706CC3', c2='#E3E2F3', c3='#3D37AD') def updates(self): _translate = QtCore.QCoreApplication.translate val = self.comboBox.currentText() state = statewise.loc[statewise['State'] == val] confirmed = int(state['Confirmed']) recovered = int(state['Recovered']) deaths = int(state['Deaths']) active = int(state['Active']) self.label_3.setText( _translate("StateWise", "Confirmed:" + "\n" + str(confirmed))) self.label_4.setText( _translate("StateWise", "Active:" + "\n" + str(active))) self.label_5.setText( _translate("StateWise", "Recovered:" + "\n" + str(recovered))) self.label_6.setText( _translate("StateWise", "Deceased:" + "\n" + str(deaths))) stateCode = stateDict[val] stateDC = statedaily.loc[statedaily["Status"] == "Confirmed"] stateDR = statedaily.loc[statedaily["Status"] == "Recovered"] stateDD = statedaily.loc[statedaily["Status"] == "Deceased"] stateDCVal = list(stateDC[stateCode]) stateDRVal = list(stateDR[stateCode]) stateDDVal = list(stateDD[stateCode]) stateDates = list(stateDC["Date"]) self.plot(stateDates, stateDCVal) self.updateGraph() def plot(self, x, y, c1="#FF6282", c2="#FFE0E6", c3="#FF083B"): xdict = dict(enumerate(x)) xax = self.graphWidget.getAxis('bottom') xax.setTicks([xdict.items()]) pen = pg.mkPen( color=c1, width=5, ) self.graphWidget.clear() #self.graphWidget.setLabel('left', "<span style=\"color:#017CFF;font-size:20px;background-color:#EFF7FF\"> Active </span>") #self.graphWidget.setLabel('bottom',"<span style=\"color:#29A746;font-size:20px;background-color:#E4F4E8\"> Recovered </span>") self.data_line = self.graphWidget.plot(list(xdict), y, pen=pen, symbol='o', symbolSize=10, symbolBrush=(c3)) self.graphWidget.setBackground(c2) def retranslateUi(self, StateWise): _translate = QtCore.QCoreApplication.translate StateWise.setWindowTitle(_translate("StateWise", "Statewise Analysis")) self.label.setText(_translate("StateWise", "Statewise Analysis")) self.label.setStyleSheet( 'color: #FD7F15;background-color: #FFF3D0;background-image:url("");qproperty-alignment: AlignCenter;' ) self.label_2.setText(_translate("StateWise", " Select a State/U.T :")) self.label_2.setStyleSheet( 'color: #FC9274;background-color: #FEE5D9;background-image:url("");' ) self.label_3.setStyleSheet( 'color: #FF2D58;background-color: #F8CCCA;background-image:url("");qproperty-alignment: AlignCenter;' ) self.label_4.setStyleSheet( 'color: #017CFF;background-color: #EFF7FF;background-image:url("");qproperty-alignment: AlignCenter;' ) self.label_5.setStyleSheet( 'color:#29A746;background-color: #E4F4E8;background-image:url("");qproperty-alignment: AlignCenter;' ) self.label_6.setStyleSheet( 'color:#767E85;background-color: #F6F6F7;background-image:url("");qproperty-alignment: AlignCenter;' ) self.comboBox.addItems(StateList) self.comboBox_2.addItems(["Confirmed", "Recovered", "Deceased"]) self.comboBox_2.setStyleSheet("background-color:white")
class PyQtGraphDataPlot(QWidget): limits_changed = Signal() def __init__(self, parent=None): super(PyQtGraphDataPlot, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.getPlotItem().addLegend() self._plot_widget.setBackground((255, 255, 255)) self._plot_widget.setXRange(0, 10, padding=0) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._plot_widget.getPlotItem().sigRangeChanged.connect( self.limits_changed) self._curves = {} self._current_vline = None def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False): pen = mkPen(curve_color, width=1) symbol = "o" symbolPen = mkPen(QColor(Qt.black)) symbolBrush = mkBrush(curve_color) # this adds the item to the plot and legend if markers_on: plot = self._plot_widget.plot(name=curve_name, pen=pen, symbol=symbol, symbolPen=symbolPen, symbolBrush=symbolBrush, symbolSize=4) else: plot = self._plot_widget.plot(name=curve_name, pen=pen) self._curves[curve_id] = 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]) del self._curves[curve_id] self._update_legend() def _update_legend(self): # clear and rebuild legend (there is no remove item method for the legend...) self._plot_widget.clear() self._plot_widget.getPlotItem().legend.items = [] for curve in self._curves.values(): self._plot_widget.addItem(curve) if self._current_vline: self._plot_widget.addItem(self._current_vline) def redraw(self): pass def set_values(self, curve_id, data_x, data_y): curve = self._curves[curve_id] curve.setData(data_x, data_y) def vline(self, x, color): if self._current_vline: self._plot_widget.removeItem(self._current_vline) self._current_vline = self._plot_widget.addLine(x=x, pen=color) def set_xlim(self, limits): # TODO: this doesn't seem to handle fast updates well self._plot_widget.setXRange(limits[0], limits[1], padding=0) def set_ylim(self, limits): self._plot_widget.setYRange(limits[0], limits[1], padding=0) def get_xlim(self): x_range, _ = self._plot_widget.viewRange() return x_range def get_ylim(self): _, y_range = self._plot_widget.viewRange() return y_range
class MainWindow(QMainWindow, capsula.Ui_MainWindow): def __init__(self): #Initialisation de la GUI, des connections actionneurs/fonctions et des modules supplémentaires non supportés par QtCreator os.chdir("/home/pi/Desktop/Résultats Capsula") #dossier de travail super(self.__class__, self).__init__() self.setupUi(self) #initialisation de la GUI Capsula #Ajout des Widgets non proposés par QtDesigner #Graphe intensité du laser self.graphicsViewLaserBeamProfile = PlotWidget( self.tabWidgetLaserControl) self.graphicsViewLaserBeamProfile.setGeometry( QtCore.QRect(310, 60, 475, 300)) self.graphicsViewLaserBeamProfile.setXRange(0, 480) self.graphicsViewLaserBeamProfile.setYRange(0, 255) self.graphicsViewLaserBeamProfile.setObjectName( "graphicsViewLaserBeamProfile") #Graphe détection self.graphicsViewRealPlot = PlotWidget(self.tabWidgetDetection) self.graphicsViewRealPlot.setGeometry(QtCore.QRect(10, 10, 550, 310)) self.graphicsViewRealPlot.setXRange(0, 400) self.graphicsViewRealPlot.setYRange(0, 1) self.graphicsViewRealPlot.setObjectName("graphicsViewRealPlot") #Message "Making reference, please wait" self.messageBoxBlank = QtGui.QProgressDialog( "Making reference, please wait...", "Cancel", 0, 100, self.tabWidgetDetection) self.messageBoxBlank.setWindowTitle("Wait...") #Initialisation des threads self.thread1 = thread.LoadingBar(self.messageBoxBlank) self.thread2 = thread.MakeBlank(self.messageBoxBlank) #Connexion boutons/méthodes self.checkBoxLaser532nm.clicked.connect( lambda: las.togglelaser532nm(self.checkBoxLaser532nm.isChecked())) self.checkBoxLaser635nm.clicked.connect( lambda: las.togglelaser635nm(self.checkBoxLaser635nm.isChecked())) self.pushButtonDutyCycleM.clicked.connect( lambda: mot.dutyCycleM(int(self.lcdNumberDutyCycleM.value()))) self.pushButtonBlank.clicked.connect(self.makeBlank) self.pushButtonClear.clicked.connect(self.on_init) self.pushButtonChangeDirectionM.clicked.connect(mot.changeDirectionM) self.pushButtonRunAndGoBackM.clicked.connect(mot.runAndGoBackM) self.pushButtonSeeCamera.clicked.connect(lambda: las.cameraStart( self.graphicsViewLaserBeamProfile, self.labelBeamImage, self. labelHHWValue, int(self.lineEditExposureTime.displayText()))) self.pushButtonStart.clicked.connect(self.startAcquisition) self.pushButtonStartMotor.clicked.connect(mot.startM) self.pushButtonStop.clicked.connect(self.stopAcquisition) self.pushButtonStopMotor.clicked.connect(mot.stopM) self.radioButtonContinu.clicked.connect(self.continuousDisplay) self.radioButtonSegmente.clicked.connect(self.segmentedDisplay) #Connexion actions/méthodes self.actionOpen_detection_configuration.triggered.connect( self.openDetectionConfiguration) self.actionOpen_pump_configuration.triggered.connect( self.openPumpConfiguration) self.actionOpen_motor_configuration.triggered.connect( self.openMotorConfiguration) self.actionPause.triggered.connect(self.pauseAcquisition) self.actionQuit.triggered.connect(self.closeEvent) self.actionSave_detection_configuration.triggered.connect( self.saveDetectionConfiguration) self.actionSave_pump_configuration.triggered.connect( self.savePumpConfiguration) self.actionSave_motor_configuration.triggered.connect( self.saveMotorConfiguration) self.actionStart_Aquisition.triggered.connect(self.startAcquisition) self.actionStop_Aquisition.triggered.connect(self.stopAcquisition) #Initialisation timer self.timer = QtCore.QTimer() self.pasDeTemps = int( self.lineEditSamplingPeriod.displayText()) #vitesse d'affichage self.timer.setInterval(self.pasDeTemps) self.timer.timeout.connect( self.update) #connexion timer out/update data #Initialisation graphe self.on_init() #Initialisation lasers GPIO.output(22, True) GPIO.output(32, True) #Déclaration variables self.blankDone = False self.inCaps = False self.noFloatDetected = True self.oldLineEdit = "" self.pause = False self.start = False self.stop = False self.withlVid = False self.withrVid = False #Connexion Rpi/Arduino via USB self.ser = serial.Serial('/dev/ttyACM0', 115200) #Onglet Lasers """voir laser.py""" #Onglet Fluidics """rien pour l'instant""" #Onglet Results def on_init(self): #Initialise la GUI os.chdir("/home/pi/Desktop/Résultats Capsula") #dossier de travail global blank, curve, datan, k, maxi, mini, n, ptr, label, tabCaps #variables utilisées dans plusieurs fonctions self.graphicsViewRealPlot.clear() #efface la courbe du graphe self.graphicsViewRealPlot.setXRange(0, 300) #mise à l'echelle X datan = [0] #initialise le tableau datas normalisées curve = self.graphicsViewRealPlot.plot(datan) #initialise la courbe #initialisation des variables semi-locales k = 0 label = 0 maxi = 0 #maxi et mini sont changés à la première itération mini = 1000 n = 300 ptr = 0 tabCaps = [ ] #initialise le tableau qui stocke les cellules à leur passage self.labelCurrentValue.setText("") #reset l'affichage de Current value self.lcdNumberCapsuleCounter.display(0) #reset le compteur de capsules self.labelConsole.setText("") #reset l'affichage de la mini console self.segmented = True #par défaut : affichage segmenté def makeBlank( self ): #fait la reference et affiche son chargement via les threads if (self.checkBoxLaser635nm.isChecked() | self.checkBoxLaser532nm.isChecked()): #reset des threads self.thread1 = thread.LoadingBar(self.messageBoxBlank) self.thread2 = thread.MakeBlank(self.messageBoxBlank) #start des threads self.thread1.start() self.thread2.start() #autorise l'utilisateur à faire une acquisition self.pushButtonClear.setEnabled(True) self.pushButtonStart.setEnabled(True) self.pushButtonStop.setEnabled(True) self.lcdNumberCapsuleCounter.setEnabled(True) #la référence est désormais fait self.blankDone = True else: info.laserOnFirst() #demande de faire le blanc en premier def startAcquisition(self): #se produit en lançant l'acquisition if self.blankDone: #si la référence a été faite global f, fn, fs, fp #les fichiers seront des variables semi-locales self.on_init() #réinitialise tous les paramètres #récupération du jour et de l'heure de l'acquisiton Ymd = datetime.datetime.now().strftime("%Y-%m-%d") YmdHMS = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S") #vérification et/ou création du dossier de l'acquisition os.makedirs("Datas", exist_ok=True) os.chdir("Datas") os.makedirs(Ymd, exist_ok=True) os.chdir(Ymd) os.chmod( '.', 0o777 ) #changement des droits : tout le monde peut écrire dans le dossier et y supprimer des éléments #création des fichiers de sauvegardes f = open("data" + YmdHMS + ".txt", "w") fn = open("datan" + YmdHMS + ".txt", "w") fs = open("stats" + YmdHMS + ".txt", "w") fp = open("plotbeam" + YmdHMS + ".txt", "w") fs.write("Statistiques de cette acquisiton :\n") os.chdir("/home/pi/Desktop/Résultats Capsula" ) #retour au dossier de travail #Changement des états self.pause = False self.start = True self.stop = False #Lancement de l'acquisition if self.actionLive_and_record_video_with_detection.isChecked( ) and self.actionRecord_video_with_detection.isChecked(): #affiche "Choose only one option" si les deux options sont cochées msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Choose only one option") msg.setWindowTitle("Information") msg.setStandardButtons(QMessageBox.Ok) msg.exec_() elif self.actionLive_and_record_video_with_detection.isChecked(): #pour l'option Live + record : self.pasDeTemps = int( self.lineEditSamplingPeriod.displayText() ) #période d'échantillonage modifiée car l'affichage ralentit le programme self.timer.setInterval(self.pasDeTemps) self.thread3 = thread2.PreviewCam( int(self.lineEditExposureTime.displayText()) ) #initialise le thread d'affichage de la caméra self.thread3.start( ) #affiche la caméra (voir thread_detect_with_vid.py self.withlVid = True #état : live + record self.actionLive_and_record_video_with_detection.setCheckable( False ) #pour ne pas changer l'option en cours d'acquisition self.timer.start() #lance le timer elif self.actionRecord_video_with_detection.isChecked(): #pour l'option record : i = 1 global cam #variable semi-locale self.pasDeTemps = int(self.lineEditSamplingPeriod.displayText( )) #vitesse d'affichage self.timer.setInterval(self.pasDeTemps) #initialisation de la caméra pour filmer (voir camera.py) cam = picamera.PiCamera() cam.resolution = (640, 480) cam.framerate = float(40) cam.shutter_speed = int( self.lineEditExposureTime.displayText()) #vérification et/ou création du dossier de l'acquisition os.makedirs("Datas", exist_ok=True) os.chdir("Datas") os.makedirs(Ymd, exist_ok=True) os.chdir(Ymd) cam.start_recording("vdata" + YmdHMS + '.h264') #création du fichier os.chdir("/home/pi/Desktop/Résultats Capsula" ) #retour au dossier de travail self.withrVid = True #état : record self.actionRecord_video_with_detection.setCheckable( False ) #pour ne pas changer l'option en cours d'acquisition self.timer.start() #lance le timer else: #sans option : self.pasDeTemps = int(self.lineEditSamplingPeriod.displayText( )) #vitesse d'affichage self.timer.setInterval(self.pasDeTemps) self.timer.start() #lance le timer else: #si la référence n'est pas faite, la faire d'abord info.makeBlankFirst() def update(self): #met à jour les données en temps réel sur le graphe self.ser.write(bytes(b'1')) #demande une donnée à Arduino value = float( self.ser.readline().strip().decode('ascii')) #reçoit la donnée self.saveData(value) #lance saveData #self.capsule(value) #lance capsule self.labelCurrentValue.setText(str(round( value, 5))) #affiche la current value avec 6 chiffres def saveData( self, value): #sauve la donnée dans le txt et l'affiche sur le graphe global curve, datan, ptr, mini, maxi, n, k, blank, label #récupère les variables semi-locales blank = self.thread2.blank #récupère la valeur de reference mini = min(value, mini) #récupère le signal min et max pour le fichier stats maxi = max(value, maxi) #mode affichage segmenté if self.segmented: if len(datan) < 300: #tant que le graphe n'est pas rempli datan.append( value / blank) #normalisation de la donnée par rapport au blanc f.write( str(round((len(datan) - 1) * self.pasDeTemps / 1000, 8)) + "\t" + str(value) + "\n") #écriture dans le txt data fn.write( str(round( (len(datan) - 1) * self.pasDeTemps / 1000, 8)) + "\t" + str(value / blank) + "\n") #écriture dans le txt datan k += 1 else: if k >= 300: #lorsque le tableau est rempli, n'affiche que 300 valeurs k = 0 self.graphicsViewRealPlot.setXRange( n, n + 300) #mise à l'échelle X n += 300 datan[:-1] = datan[1:] #datan est décalé de 1 vers la gauche datan[ -1] = value / blank #ajoute à datan la nouvelle donnée normalisée f.write( str(round((ptr + 300) * self.pasDeTemps / 1000, 8)) + "\t" + str(value) + "\n") #écriture dans le txt data fn.write( str(round( (ptr + 300) * self.pasDeTemps / 1000, 8)) + "\t" + str(value / blank) + "\n") #écriture dans le txt datan ptr += 1 #incrémente le pointeur k += 1 curve.setPos(ptr, 0) #positionne l'origine du graphe #mode affichage continu else: if len(datan) < 300: #tant que le graphe n'est pas rempli datan.append( value / blank) #normalisation de la donnée par rapport au blanc f.write( str(round((len(datan) - 1) * self.pasDeTemps / 1000, 8)) + "\t" + str(value) + "\n") #écriture dans le txt data fn.write( str(round( (len(datan) - 1) * self.pasDeTemps / 1000, 8)) + "\t" + str(value / blank) + "\n") #écriture dans le txt datan else: #lorsque le graphe est rempli, n'affiche que 300 valeurs self.graphicsViewRealPlot.setXRange(ptr, ptr + 300) #mise à l'échelle X datan[:-1] = datan[1:] #data est décalé de 1 vers la gauche datan[-1] = value / blank #ajoute à data la nouvelle donnée f.write( str(round((ptr + 300) * self.pasDeTemps / 1000, 8)) + "\t" + str(value) + "\n") #écriture dans le txt data fn.write( str(round((ptr + 300) * self.pasDeTemps / 1000, )) + "\t" + str(value / blank) + "\n") #écriture dans le txt datan ptr += 1 #incrémente le pointeur curve.setPos(ptr, 0) #positionne l'origine du graphe label += 1 #incrémente le label curve.setData(datan) #mise à jour du graphe def capsule(self, value): #définit si ce qui est observé est une capsule ou non global datan, d, invabsorption, label, tabCaps, blank try: #si on arrive à récupérer une valeur du seuil de détection lineEdit = self.lineEditDetectionThreshold.displayText( ) #la récupère if lineEdit != self.oldLineEdit: #si le seuil a été changé if lineEdit == "": #si il n'y a pas de seuil self.noFloatDetected = True #état : pas de seuil détecté else: self.noFloatDetected = False #état : seuil détecté self.oldLineEdit = lineEdit #le nouveau devient l'ancien if not self.inCaps: #si on est pas déjà dans une capsule if datan[-1] < float( self.lineEditDetectionThreshold.displayText( )) and label > 3: #si on entre dans une capsule self.inCaps = True #état : on est dans une capsule d = -1 #pour aller chercher la taille de la capsule invabsorption = value / blank #pour définir l'absorption if self.inCaps: #si on est déjà dans une capsule d -= 1 #on décale le début de 1 à gauche if invabsorption > value / blank: #si l'absorption est plus grande invabsorption = value / blank #nouvelle valeur pour l'inverse de l'absorption if datan[-1] > float(self.lineEditDetectionThreshold. displayText()): #si on sort d'une capsule self.inCaps = False #état : on est pas dans une capsule absorption = 1 - invabsorption #calcul de l'absorption while ( 1 - datan[d] ) / absorption < 0.5: #pour trouver la position du début de la capsule d += 1 f = d while ( 1 - datan[f] ) / absorption >= 0.5: #pour trouver la position de la fin de la capsule f += 1 taille = abs(f - d) #calcul de la taille if taille > float(self.lineEditLength.displayText( )): #si la taille de la capsule est assez grande self.lcdNumberCapsuleCounter.display( self.lcdNumberCapsuleCounter.value() + 1) #on incrémente le compteur de 1 tabCaps.append( capsule.Capsule(taille, label - taille, absorption) ) #on ajoute la capsule au tableau de capsules self.labelConsole.setText( tabCaps[-1].afficher() ) #affiche les données de la capsule dans la mini console except ValueError: #si on ne détecte pas de seuil if self.noFloatDetected: #si on n'était pas déjà dans ce cas précedemment print("no float in Detection Threshold") self.noFloatDetected = False def pauseAcquisition(self): #gère les pauses d'acquisition if self.blankDone: #si la référence est faite if not (self.withlVid or self.withrVid): #si on peut mettre pause if not self.pause: #si la pause n'est pas active self.timer.stop() #mise en pause du timer self.pause = True #la pause est active else: #si la pause est active self.timer.start() #remise en route du timer self.pause = False #la pause n'est plus active else: #si la référence n'est pas faite self.makeBlankFirst() #faire la référence d'abord def stopAcquisition(self): #se produit en stoppant l'acquisition if self.blankDone: #si la référence est faite if self.start == True: #si une acquisition est en cours if self.withrVid: #pour l'option Record : global cam #récupère la variable semi-locale cam #Arrête et ferme la caméra cam.stop_recording() cam.close() self.actionRecord_video_with_detection.setCheckable( True) #option à nouveau modifiable self.actionRecord_video_with_detection.setChecked( True) #option cochée if self.withlVid: #pour l'option Live + record : self.thread3.stop( ) #arrête la preview (voir thread_detect_with_vid.py) self.actionLive_and_record_video_with_detection.setCheckable( True) #option à nouveau modifiable self.actionLive_and_record_video_with_detection.setChecked( True) #option cochée self.saveStats() #sauvegarde les stats self.timer.stop() #arrête le timer #fermeture des fichiers f.close() fn.close() os.chdir("/home/pi/Desktop/Résultats Capsula" ) #retour dans le dossier de travail #réinitialisation des états self.withrVid = False self.withlVid = False self.start = False self.stop = True mot.stopM() else: #si la référence n'est pas faite self.makeBlankFirst() #faire la référence d'abord def continuousDisplay(self): #mode d'affichage continu self.segmented = False def segmentedDisplay(self): #mode d'affichage segmenté global ptr, k, n n = ptr + 300 self.graphicsViewRealPlot.setXRange(n, n + 300) #mise à l'echelle X n += 300 k = 0 self.segmented = True #Onglet Calibration #Général def openDetectionConfiguration(self): file = QFileDialog.getOpenFileName() file = str(file)[2:-19] fodc = open(file, "r") detection_threshold = fodc.readline() length_threshold = fodc.readline() ratio_capsule = fodc.readline() sampling_period = fodc.readline() self.lineEditDetectionThreshold.setText(detection_threshold) self.lineEditLength.setText(length_threshold) self.lineEditMinimumSize.setText(ratio_capsule) self.lineEditSamplingPeriod.setText(sampling_period) fodc.close() os.chdir("/home/pi/Desktop/Résultats Capsula") def openPumpConfiguration(self): file = QFileDialog.getOpenFileName() file = str(file)[2:-19] fopc = open(file, "r") dutycycle = int(fopc.readline()) self.horizontalSliderDutyCycleP.setValue(dutycycle) fopc.close() os.chdir("/home/pi/Desktop/Résultats Capsula") def openMotorConfiguration(self): file = QFileDialog.getOpenFileName() file = str(file)[2:-19] fomc = open(file, "r") dutycycle = int(fomc.readline()) self.horizontalSliderDutyCycleM.setValue(dutycycle) fomc.close() os.chdir("/home/pi/Desktop/Résultats Capsula") def saveDetectionConfiguration(self): file = QFileDialog.getSaveFileName() if (str(file)[-23:-19] == ".txt"): fsdc = open(str(file)[2:-19], "w") else: fsdc = open(str(file)[2:-19] + ".txt", "w") detection_threshold = self.lineEditDetectionThreshold.text() length_threshold = self.lineEditLength.text() ratio_capsule = self.lineEditMinimumSize.text() sampling_period = self.lineEditSamplingPeriod.text() fsdc.write(detection_threshold + "\n") fsdc.write(length_threshold + "\n") fsdc.write(ratio_capsule + "\n") fsdc.write(sampling_period) fsdc.close() os.chdir("/home/pi/Desktop/Résultats Capsula") def savePumpConfiguration(self): file = QFileDialog.getSaveFileName() if (str(file)[-23:-19] == ".txt"): fspc = open(str(file)[2:-19], "w") else: fspc = open(str(file)[2:-19] + ".txt", "w") dutycycle = str(self.horizontalSliderDutyCycleP.value()) fspc.write(dutycycle) fspc.close() os.chdir("/home/pi/Desktop/Résultats Capsula") def saveMotorConfiguration(self): file = QFileDialog.getSaveFileName() if (str(file)[-23:-19] == ".txt"): fsmc = open(str(file)[2:-19], "w") else: fsmc = open(str(file)[2:-19] + ".txt", "w") dutycycle = str(self.horizontalSliderDutyCycleM.value()) fsmc.write(dutycycle) fsmc.close() os.chdir("/home/pi/Desktop/Résultats Capsula") def saveStats(self): #sauve des statistiques de l'acquisition global mini, maxi, fs #récupération de variables semi-locales #Ecriture dans le fichier stats et fermeture de celui ci fs.write("Nombres de capsules comptées :\t" + str(int(self.lcdNumberCapsuleCounter.value())) + "\n") fs.write("Signal maximal mesuré :\t" + str(round(maxi, 2)) + "V\n") fs.write("Signal minimal mesuré :\t" + str(round(mini, 2)) + "V\n") fs.write("Pas de temps :\t" + str(self.pasDeTemps)) fs.close() def closeEvent(self, event): #Quitte proprement la GUI self.timer.stop() #arrête le timer #réinitialise les GPIO GPIO.setmode(GPIO.BOARD) GPIO.setup(22, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(32, GPIO.OUT, initial=GPIO.LOW) GPIO.cleanup() self.close() #ferme la fenêtre
class Ui_MainWindow(QtWidgets.QMainWindow): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.setFixedSize(800, 618) MainWindow.setStyleSheet('background:#e8e8e8') #here starts widget setup, mostly just assigning locations and various properties self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.topDisplayDivider = QtWidgets.QFrame(self.centralwidget) self.topDisplayDivider.setGeometry(QtCore.QRect(0, 90, 801, 16)) self.topDisplayDivider.setFrameShape(QtWidgets.QFrame.HLine) self.topDisplayDivider.setFrameShadow(QtWidgets.QFrame.Sunken) self.topDisplayDivider.setObjectName("topDisplayDivider") self.menuDivider = QtWidgets.QFrame(self.centralwidget) self.menuDivider.setGeometry(QtCore.QRect(110, 100, 16, 501)) self.menuDivider.setFrameShape(QtWidgets.QFrame.VLine) self.menuDivider.setFrameShadow(QtWidgets.QFrame.Sunken) self.menuDivider.setObjectName("menuDivider") self.pushHistory = QtWidgets.QPushButton(self.centralwidget) self.pushHistory.setGeometry(QtCore.QRect(20, 140, 75, 23)) self.pushHistory.setObjectName("pushHistory") self.pushHistory.setStyleSheet("border: 1px solid grey;") self.pushAnalytics = QtWidgets.QPushButton(self.centralwidget) self.pushAnalytics.setGeometry(QtCore.QRect(20, 210, 75, 23)) self.pushAnalytics.setObjectName("pushAnalytics") self.pushExport = QtWidgets.QPushButton(self.centralwidget) self.pushExport.setGeometry(QtCore.QRect(20, 280, 75, 23)) self.pushExport.setObjectName("pushExport") self.pushOptions = QtWidgets.QPushButton(self.centralwidget) self.pushOptions.setGeometry(QtCore.QRect(20, 350, 75, 23)) self.pushOptions.setObjectName("pushOptions") self.pushLive = QtWidgets.QPushButton(self.centralwidget) self.pushLive.setGeometry(QtCore.QRect(20, 550, 75, 23)) self.pushLive.setObjectName("pushLive") self.pushGraph = QtWidgets.QPushButton(self.centralwidget) self.pushGraph.setGeometry(QtCore.QRect(200, 550, 75, 23)) self.pushGraph.setObjectName("pushGraph") self.pushGraph2 = QtWidgets.QPushButton(self.centralwidget) self.pushGraph2.setGeometry(QtCore.QRect(300, 550, 75, 23)) self.pushGraph2.setObjectName("pushGraph2") self.liveDisplay_1 = QtWidgets.QLabel(self.centralwidget) self.liveDisplay_1.setGeometry(QtCore.QRect(710, 20, 61, 61)) self.liveDisplay_1.setObjectName("liveDisplay_1") self.liveDisplay_1.setStyleSheet("font: 30pt Arial MS") self.liveDisplay_2 = QtWidgets.QLabel(self.centralwidget) self.liveDisplay_2.setGeometry(QtCore.QRect(570, 20, 61, 61)) self.liveDisplay_2.setObjectName("liveDisplay_2") self.liveDisplay_2.setStyleSheet("font: 30pt Arial MS") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(500, 20, 61, 61)) self.label.setText("") self.label.setPixmap(QtGui.QPixmap("heart.png")) self.label.setScaledContents(True) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(640, 20, 61, 61)) self.label_2.setText("") self.label_2.setPixmap(QtGui.QPixmap("o2.png")) self.label_2.setScaledContents(True) self.label_2.setObjectName("label_2") self.groupBox = QtWidgets.QGroupBox(self.centralwidget) self.groupBox.setGeometry(QtCore.QRect(140, 120, 631, 311)) self.groupBox.setObjectName("groupBox") self.label_3 = QtWidgets.QLabel(self.groupBox) self.label_3.setGeometry(QtCore.QRect(210, 110, 151, 31)) self.label_3.setObjectName("label_3") self.dateTimeEdit = QtWidgets.QDateEdit(self.centralwidget) self.dateTimeEdit.setGeometry(QtCore.QRect(190, 490, 194, 22)) self.dateTimeEdit.setObjectName("dateTimeEdit") self.dateTimeEdit.setDate(QDate.currentDate()) self.label_6 = QtWidgets.QLabel(self.centralwidget) self.label_6.setGeometry(QtCore.QRect(40, 20, 251, 41)) font = QtGui.QFont() font.setPointSize(19) self.label_6.setFont(font) self.label_6.setObjectName("label_6") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) #creating graphs self.graphWidgetLive = PlotWidget(self.centralwidget) self.graphWidgetLive.setGeometry(QtCore.QRect(40, 10, 400, 70)) self.graphWidgetLive.setObjectName("graphWidgetLive") self.graphWidgetLive.getPlotItem().hideAxis('bottom') self.graphWidgetLive.setMouseEnabled(x=False, y=False) self.graphWidgetLive.setYRange(0, 150, padding=0.2) self.graphWidgetLive.getPlotItem().hideAxis('bottom') self.graphWidgetMain = PlotWidget(self.centralwidget) self.graphWidgetMain.setGeometry(QtCore.QRect(150, 140, 600, 275)) self.graphWidgetMain.setObjectName("graphWidgetLive") self.graphWidgetMain.setMouseEnabled(x=True, y=False) self.graphWidgetMain.setYRange(50, 150, padding=0) self.graphWidgetMain.getPlotItem().hideAxis('bottom') self.graphWidgetLive.setBackground('w') pen = pg.mkPen(color=(255, 0, 0), width=2) pen2 = pg.mkPen(color=(0, 0, 255), width=2) time = [1, 2, 3, 4] heartRate = [90, 87, 88, 85] oxygenLevel = [100, 99, 99, 98] self.graphWidgetMain.setBackground('w') self.graphWidgetMain.plot(time, heartRate, pen=pen) self.graphWidgetMain.plot(time, oxygenLevel, pen=pen2) #these two values can be changed in options and are parameters for the windows notifications self.notifThresh = [120, 95] self.notifCooldown = 25 self.serialInput = False self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) #connecting buttons self.pushAnalytics.clicked.connect(self.show_Analysis) self.pushExport.clicked.connect(self.show_export) self.pushOptions.clicked.connect(self.show_popOptions) self.pushLive.setCheckable(True) self.pushLive.clicked.connect(self.show_graphLive) self.pushGraph.clicked.connect(self.fromFile) self.pushGraph2.clicked.connect(self.fromDate) def update_plot_data(self): #this is used to update the live graph by reading from serial or the debugging simulator self.timeLive = self.timeLive[1:] # Remove the first y element. self.timeLive.append(self.timeLive[-1] + 1) # Add a new value 1 higher than the last. if self.serialInput == True: serialData = serial_connection.getSerial() else: serialData = (singleGenerate(79, 3), singleGenerate(97, 1)) if serialData[0] != 0: self.liveHR = self.liveHR[1:] # Remove the first self.liveHR.append(serialData[0]) self.liveDisplay_2.setText(str(self.liveHR[99])) if serialData[1] != 0: self.liveO2 = self.liveO2[1:] # Remove the first self.liveO2.append(serialData[1]) self.liveDisplay_1.setText(str(self.liveO2[99])) if not (serialData[0] == 0 & serialData[1] == 0): datasystem.data_store(serialData[0], serialData[1]) a = datetime.datetime.now() b = self.startTime c = a - b print(c.total_seconds()) if c.total_seconds() > self.notifCooldown: if self.notifThresh[0] < serialData[0]: windowsalert.sendNotifH() self.startTime = datetime.datetime.now() if self.notifThresh[1] > serialData[1] & serialData[1] != 0: windowsalert.sendNotifO() self.startTime = datetime.datetime.now() self.data_line_1.setData(self.timeLive, self.liveHR) # Update the data. self.data_line_2.setData(self.timeLive, self.liveO2) # Update the data. def show_export(self): #used to call the zipping function in datasystem.py, and the file dialog options = QFileDialog.Options() | QFileDialog.DontUseNativeDialog fileName = QFileDialog.getSaveFileName(self, "Select an export location", "", "Zip Files (*.zip)", options=options) datasystem.data_zip(fileName[0] + '.zip') def show_graphLive(self): #connects to the button for live, and also controls if the graph/reading is enabled self.timeLive = list(range(100)) # 100 time points self.liveHR = [0] * 100 self.liveO2 = [0] * 100 self.startTime = datetime.datetime.now() - datetime.timedelta( seconds=self.notifCooldown) print(self.startTime) pen = pg.mkPen(color=(255, 0, 0), width=2) pen2 = pg.mkPen(color=(0, 0, 255), width=2) self.liveDisplay_2.setText('0') self.liveDisplay_1.setText('0') if self.pushLive.isChecked(): self.data_line_1 = self.graphWidgetLive.plot(self.timeLive, self.liveHR, pen=pen) self.data_line_2 = self.graphWidgetLive.plot(self.timeLive, self.liveO2, pen=pen2) self.timer = QtCore.QTimer() self.timer.setInterval(250) self.timer.timeout.connect(self.update_plot_data) self.timer.start() self.pushLive.setText('Stop') else: self.timer.stop() self.graphWidgetLive.clear() self.pushLive.setText('Start') def fromDate(self): #used to connect the date picker to the main graph x = self.dateTimeEdit.date().toPyDate() date = 'vitals' + str(x) directory = os.getcwd() foldername = directory + '\\vitalsmouse_userdata' self.importfile = foldername + '\\' + date + '.csv' self.show_graphMain() def fromFile(self): #used to connect the file dialog to the main graph options = QFileDialog.Options() | QFileDialog.DontUseNativeDialog fileName = QFileDialog.getOpenFileName(self, "Select a file to view", "", "CSV Files (*.csv)", options=options) self.importfile = fileName[0] self.show_graphMain() def show_graphMain(self): #loads the data from a file and displays it on the main graph print(self.importfile) self.graphWidgetMain.clear() maindata = datasystem.data_get(self.importfile) mainTime = maindata[0] mainHR = maindata[1] mainO2 = maindata[2] pen = pg.mkPen(color=(255, 0, 0), width=2) pen2 = pg.mkPen(color=(0, 0, 255), width=2) self.graphWidgetMain.setBackground('w') self.graphWidgetMain.plot(mainTime, mainHR, pen=pen) self.graphWidgetMain.plot(mainTime, mainO2, pen=pen2) def show_popOptions(self): #secondary window for options self.Options = QDialog() self.Options.resize(200, 250) self.input_label = QtWidgets.QLabel(self.Options) self.input_label.setGeometry(QtCore.QRect(10, 10, 61, 51)) self.input_label.setObjectName("input_label") self.inputBox = QtWidgets.QComboBox(self.Options) self.inputBox.setGeometry(QtCore.QRect(80, 30, 69, 22)) self.inputBox.setObjectName("inputBox") self.inputBox.addItem('Debug') self.inputBox.addItem('USB') self.notificationsBox = QtWidgets.QGroupBox(self.Options) self.notificationsBox.setGeometry(QtCore.QRect(0, 90, 211, 131)) self.notificationsBox.setObjectName("notificationsBox") self.lineEdit = QtWidgets.QLineEdit(self.notificationsBox) self.lineEdit.setGeometry(QtCore.QRect(130, 30, 61, 20)) self.lineEdit.setObjectName("lineEdit") self.hr_label = QtWidgets.QLabel(self.notificationsBox) self.hr_label.setGeometry(QtCore.QRect(6, 30, 111, 20)) self.hr_label.setObjectName("hr_label") self.lineEdit_2 = QtWidgets.QLineEdit(self.notificationsBox) self.lineEdit_2.setGeometry(QtCore.QRect(130, 60, 61, 20)) self.lineEdit_2.setObjectName("lineEdit_2") self.lineEdit_3 = QtWidgets.QLineEdit(self.notificationsBox) self.lineEdit_3.setGeometry(QtCore.QRect(130, 90, 61, 20)) self.lineEdit_3.setObjectName("lineEdit_3") self.o2_label = QtWidgets.QLabel(self.notificationsBox) self.o2_label.setGeometry(QtCore.QRect(10, 60, 111, 20)) self.o2_label.setObjectName("o2_label") self.cooldown_label = QtWidgets.QLabel(self.notificationsBox) self.cooldown_label.setGeometry(QtCore.QRect(10, 90, 111, 20)) self.cooldown_label.setObjectName("cooldown_label") self.input_label.setText("Input mode") self.notificationsBox.setTitle(("Notifications")) self.lineEdit.setText(("110")) self.hr_label.setText(("Heartrate threshold")) self.lineEdit_2.setText(("95")) self.lineEdit_3.setText(("20")) self.o2_label.setText(("Oxygen threshold")) self.cooldown_label.setText(("Cooldown(seconds)")) self.Options.setWindowTitle("Options") self.Options.exec_() h = self.inputBox.currentText() if h == 'USB': self.serialInput = True else: self.serialInput = False heartThresh = self.lineEdit.text() o2Thresh = self.lineEdit_2.text() cool = self.lineEdit_3.text() self.notifThresh = (int(heartThresh), int(o2Thresh)) self.notifCooldown = int(cool) def show_Analysis(self): #secondary window for analysis self.Analysis = QDialog() self.Analysis.resize(400, 400) self.dailyLine = QtWidgets.QLineEdit(self.Analysis) self.dailyLine.setGeometry(QtCore.QRect(210, 60, 113, 20)) self.dailyLine.setReadOnly(True) self.dailyLine.setObjectName("dailyLine") self.yearly_label = QtWidgets.QLabel(self.Analysis) self.yearly_label.setGeometry(QtCore.QRect(40, 140, 101, 16)) self.yearly_label.setObjectName("yearly_label") self.monthly_label = QtWidgets.QLabel(self.Analysis) self.monthly_label.setGeometry(QtCore.QRect(40, 100, 111, 16)) self.monthly_label.setObjectName("monthly_label") self.monthlyLine = QtWidgets.QLineEdit(self.Analysis) self.monthlyLine.setGeometry(QtCore.QRect(210, 100, 113, 20)) self.monthlyLine.setReadOnly(True) self.monthlyLine.setObjectName("monthlyLine") self.daily_label = QtWidgets.QLabel(self.Analysis) self.daily_label.setGeometry(QtCore.QRect(40, 60, 111, 16)) self.daily_label.setObjectName("daily_label") self.yearlyLine = QtWidgets.QLineEdit(self.Analysis) self.yearlyLine.setGeometry(QtCore.QRect(210, 140, 113, 20)) self.yearlyLine.setReadOnly(True) self.yearlyLine.setObjectName("yearlyLine") self.legend_label = QtWidgets.QLabel(self.Analysis) self.legend_label.setGeometry(QtCore.QRect(220, 20, 113, 20)) self.legend_label.setObjectName("legend_label") self.legend_label.setText("Heartrate, Oxygen") self.graphWidgetAnalysis = PlotWidget(self.Analysis) self.graphWidgetAnalysis.setGeometry(QtCore.QRect(50, 200, 300, 150)) self.graphWidgetAnalysis.setObjectName("graphWidgetLive") self.graphWidgetAnalysis.setMouseEnabled(x=False, y=False) self.graphWidgetAnalysis.setYRange(50, 150, padding=0) self.graphWidgetAnalysis.getPlotItem().hideAxis('bottom') analysis_data = datasystem.data_analysis() pen = pg.mkPen(color=(255, 0, 0), width=2) pen2 = pg.mkPen(color=(0, 0, 255), width=2) heartRate = analysis_data[3][0] oxygenLevel = analysis_data[3][1] length = len(heartRate) time = [int(z) for z in range(length)] self.graphWidgetAnalysis.setBackground('w') self.graphWidgetAnalysis.plot(time, heartRate, pen=pen) self.graphWidgetAnalysis.plot(time, oxygenLevel, pen=pen2) self.dailyLine.setText( str(round(analysis_data[0][0], 2)) + ', ' + str(round(analysis_data[0][1], 2))) self.monthlyLine.setText( str(round(analysis_data[1][0], 2)) + ', ' + str(round(analysis_data[1][1], 2))) self.yearlyLine.setText( str(round(analysis_data[2][0], 2)) + ', ' + str(round(analysis_data[2][1], 2))) self.yearly_label.setText("Yearly Average") self.monthly_label.setText("Monthly Average") self.daily_label.setText("Daily Average") self.Analysis.setWindowTitle("Analysis") self.Analysis.exec_() def retranslateUi(self, MainWindow): #this is a holdover from using pyuic5, not normally used like this _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushHistory.setText(_translate("MainWindow", "History")) self.pushAnalytics.setText(_translate("MainWindow", "Analytics")) self.pushExport.setText(_translate("MainWindow", "Export")) self.pushOptions.setText(_translate("MainWindow", "Options")) self.pushLive.setText(_translate("MainWindow", "Start")) self.pushGraph.setText(_translate("MainWindow", "From file")) self.pushGraph2.setText(_translate("MainWindow", "From date")) self.liveDisplay_1.setText("##") self.liveDisplay_2.setText("##") self.groupBox.setTitle(_translate("MainWindow", "History"))
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1200, 850) # Main window self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") MainWindow.setCentralWidget(self.centralwidget) # Plot widget self.plotWidget = PlotWidget(self.centralwidget) self.plotWidget.setObjectName("PlotWidget") # Trails view self.trailsScene = QGraphicsScene() self.trailsView = QGraphicsView(self.trailsScene, self.centralwidget) self.trailsView.setObjectName("trailsView") # Heatmap view self.heatmapScene = QGraphicsScene() self.heatmapView = QGraphicsView(self.heatmapScene, self.centralwidget) self.heatmapView.setObjectName("heatmapView") # OpenGL widget self.openGLWidget = OpenGLWidget() self.openGLWidget.setObjectName("openGLView") # Stacked widget, combining plot widget and graphics view self.stackedWidget = QStackedWidget(self.centralwidget) self.stackedWidget.setGeometry(QRect(10, 10, 800, 800)) self.stackedWidget.setObjectName("stackedWidget") self.stackedWidget.addWidget(self.plotWidget) self.stackedWidget.addWidget(self.trailsView) self.stackedWidget.addWidget(self.heatmapView) self.stackedWidget.addWidget(self.openGLWidget) # Perturbation title self.perturbationSlidersLabel = QLabel(self.centralwidget) self.perturbationSlidersLabel.setGeometry(QRect(960, 30, 170, 20)) font = QFont() font.setPointSize(14) self.perturbationSlidersLabel.setFont(font) self.perturbationSlidersLabel.setObjectName("perturbation_title") # Perturbation 1 self.horizontalSlider1 = QSlider(self.centralwidget) self.horizontalSlider1.setGeometry(QRect(920, 80, 270, 20)) self.horizontalSlider1.setMaximum(100) self.horizontalSlider1.setOrientation(Qt.Horizontal) self.horizontalSlider1.setInvertedAppearance(False) self.horizontalSlider1.setObjectName("horizontal1Slider") self.horizontalSlider1.valueChanged.connect(self.slider1Changed) self.checkBox1 = QCheckBox(self.centralwidget) self.checkBox1.setGeometry(QRect(830, 80, 90, 20)) self.checkBox1.setTristate(False) self.checkBox1.setObjectName("checkBox1") # Perturbation 2 self.horizontalSlider2 = QSlider(self.centralwidget) self.horizontalSlider2.setGeometry(QRect(920, 130, 270, 20)) self.horizontalSlider2.setMaximum(100) self.horizontalSlider2.setOrientation(Qt.Horizontal) self.horizontalSlider2.setInvertedAppearance(False) self.horizontalSlider2.setObjectName("horizontalSlider2") self.horizontalSlider2.valueChanged.connect(self.slider2Changed) self.checkBox2 = QCheckBox(self.centralwidget) self.checkBox2.setGeometry(QRect(830, 130, 90, 20)) self.checkBox2.setObjectName("checkBox2") # Perturbation 3 self.horizontalSlider3 = QSlider(self.centralwidget) self.horizontalSlider3.setGeometry(QRect(920, 180, 270, 20)) self.horizontalSlider3.setMaximum(100) self.horizontalSlider3.setOrientation(Qt.Horizontal) self.horizontalSlider3.setInvertedAppearance(False) self.horizontalSlider3.setObjectName("horizontalSlider3") self.horizontalSlider3.valueChanged.connect(self.slider3Changed) self.checkBox3 = QCheckBox(self.centralwidget) self.checkBox3.setGeometry(QRect(830, 180, 90, 20)) self.checkBox3.setObjectName("checkBox3") # Perturbation 4 self.horizontalSlider4 = QSlider(self.centralwidget) self.horizontalSlider4.setGeometry(QRect(920, 230, 270, 20)) self.horizontalSlider4.setMaximum(100) self.horizontalSlider4.setOrientation(Qt.Horizontal) self.horizontalSlider4.setInvertedAppearance(False) self.horizontalSlider4.setObjectName("horizontalSlider4") self.horizontalSlider4.valueChanged.connect(self.slider4Changed) self.checkBox4 = QCheckBox(self.centralwidget) self.checkBox4.setGeometry(QRect(830, 230, 90, 20)) self.checkBox4.setObjectName("checkBox4") # Random perturbation button self.perturbSelectedButton = QPushButton(self.centralwidget) self.perturbSelectedButton.setGeometry(QRect(830, 300, 150, 50)) self.perturbSelectedButton.setObjectName("perturbSelectedButton") self.perturbSelectedButton.setToolTip( "Randomly set all checked perturbations") self.perturbSelectedButton.clicked.connect(self.randChangeSelected) self.reset = QPushButton(self.centralwidget) self.reset.setGeometry(QRect(1000, 300, 110, 50)) self.reset.setObjectName("reset_button") self.reset.setToolTip("Set all checked perturbations back to 0") self.reset.clicked.connect(self.resetSelected) # Menubar items self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QRect(0, 0, 1285, 21)) self.menubar.setObjectName("menubar") self.menuFile = QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuViews = QMenu(self.menubar) self.menuViews.setObjectName("menuViews") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.viewsBasic = QAction(MainWindow) self.viewsBasic.setObjectName("viewsBasic") self.viewsBasic.triggered.connect(lambda: self.switchWidget(0)) self.viewsTrail = QAction(MainWindow) self.viewsTrail.setObjectName("viewsTrail") self.viewsTrail.triggered.connect(lambda: self.switchWidget(1)) self.viewsHeatmap = QAction(MainWindow) self.viewsHeatmap.setObjectName("viewsHeatmap") self.viewsHeatmap.triggered.connect(lambda: self.switchWidget(2)) self.viewsOpenGL = QAction(MainWindow) self.viewsOpenGL.setObjectName("viewsOpenGL") self.viewsOpenGL.triggered.connect(lambda: self.switchWidget(3)) self.fileReset = QAction(MainWindow) self.fileReset.setObjectName("fileReset") # self.fileReset.action.connect(self.reset) self.fileSave = QAction(MainWindow) self.fileSave.setObjectName("fileSave") self.menuFile.addAction(self.fileReset) self.menuFile.addAction(self.fileSave) self.menuViews.addAction(self.viewsBasic) self.menuViews.addAction(self.viewsTrail) self.menuViews.addAction(self.viewsHeatmap) self.menuViews.addAction(self.viewsOpenGL) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuViews.menuAction()) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.checkBox1.setText(_translate("MainWindow", "Add constant")) self.checkBox2.setText(_translate("MainWindow", "Dim. removal")) self.checkBox3.setText(_translate("MainWindow", "Perturbation3")) self.checkBox4.setText(_translate("MainWindow", "Perturbation4")) self.perturbSelectedButton.setText( _translate("MainWindow", "Randomize selected")) self.reset.setText(_translate("MainWindow", "Reset")) self.perturbationSlidersLabel.setText( _translate("MainWindow", "Perturbation sliders")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuViews.setTitle(_translate("MainWindow", "Views")) self.viewsBasic.setText(_translate("MainWindow", "Basic interface")) self.viewsBasic.setShortcut(_translate("MainWindow", "Ctrl+1")) self.viewsTrail.setText(_translate("MainWindow", "Trail interface")) self.viewsTrail.setShortcut(_translate("MainWindow", "Ctrl+2")) self.viewsHeatmap.setText( _translate("MainWindow", "Heat map interface")) self.viewsHeatmap.setShortcut(_translate("MainWindow", "Ctrl+3")) self.viewsOpenGL.setText(_translate("MainWindow", "OpenGL interface")) self.viewsOpenGL.setShortcut(_translate("MainWindow", "Ctrl+4")) self.fileReset.setText(_translate("MainWindow", "Reset")) self.fileReset.setShortcut(_translate("MainWindow", "Ctrl+R")) self.fileSave.setText(_translate("MainWindow", "Save")) self.fileSave.setShortcut(_translate("MainWindow", "Ctrl+S")) def switchWidget(self, index): self.stackedWidget.setCurrentIndex(index) print("Going to stacked widget index: " + str(index)) # TODO: only compute intermediateDatasets if not already done so if index == 1: self.statusbar.showMessage( "Computing and predicting intermediate datasets per increment..." ) self.computeIntermediateDatasets() self.statusbar.showMessage("Drawing trail map...") self.projectTrailMap() self.statusbar.showMessage("Trail map projected.") if index == 2: self.statusbar.showMessage( "Computing and predicting intermediate datasets per increment..." ) self.computeIntermediateDatasets() self.statusbar.showMessage("Drawing heat map...") self.projectHeatMap() self.statusbar.showMessage("Heat map projected.") if index == 3: self.statusbar.showMessage( "Computing and predicting intermediate datasets per increment..." ) self.computeIntermediateDatasets() self.statusbar.showMessage("Drawing trail map...") if self.predList: self.openGLWidget.paintTrailMapGL(self.predList, self.y_test, self.class_colors) else: print("No data to create trail map with.") self.statusbar.showMessage("No data to create trail map with.") def computeIntermediateDatasets(self): # If no checkbox is checked if not self.checkBox1.isChecked() and not self.checkBox2.isChecked() and \ not self.checkBox3.isChecked() and not self.checkBox4.isChecked(): self.statusbar.showMessage( "No perturbation is selected. Please choose one of them.") return print("Computing intermediate datasets") # Perturb using the checked perturbation if self.checkBox1.isChecked(): max_value = self.horizontalSlider1.value() self.dataset.interDataOfPerturb(1, max_value) if self.checkBox2.isChecked(): max_value = self.horizontalSlider2.value() self.dataset.interDataOfPerturb(2, max_value) # Predict every dataset and save to predList self.predList = [] for i in range(0, len(self.dataset.interDataset)): self.predList.append( self.model.predict(self.dataset.interDataset[i])) # Project a trail map using the data in predList def projectTrailMap(self): for j in range(len(self.predList[0])): pen = pg.mkPen(color=self.y_test[j], width=1) for i in range(len(self.predList) - 1): x1 = self.predList[i][j][0] y1 = self.predList[i][j][1] x2 = self.predList[i + 1][j][0] y2 = self.predList[i + 1][j][1] self.trailsScene.addLine(x1, y1, x2, y2, pen) # Fit trail map to screen # self.trailsScene.itemsBoundingRect() self.trailsView.fitInView(0, 0, 1, 1, Qt.KeepAspectRatio) def projectHeatMap(selfs): pass def replot(self): pred = self.model.predict(self.dataset.perturbed) items = pg.ScatterPlotItem(x=pred[:, 0], y=pred[:, 1], data=np.arange(len(self.dataset.perturbed)), pen='w', brush=self.brushes, size=10, hoverable=True, hoverPen=pg.mkPen(0, 0, 0, 255)) self.plotWidget.clear() self.plotWidget.addItem(items) # Disable range adjustments self.plotWidget.setRange(None, (0, 1), (0, 1)) self.plotWidget.setXRange(0, 1) def slider1Changed(self): new_value = self.horizontalSlider1.value() self.statusbar.showMessage( "Changed value of perturbation slider 1 to " + str(new_value)) self.dataset.addConstantNoise(new_value) self.replot() def slider2Changed(self): new_value = self.horizontalSlider2.value() self.statusbar.showMessage( "Changed value of perturbation slider 2 to " + str(new_value)) self.dataset.removeRandomDimensions(new_value) self.replot() def slider3Changed(self): new_value = self.horizontalSlider3.value() self.statusbar.showMessage( "Changed value of perturbation slider 3 to " + str(new_value)) def slider4Changed(self): new_value = self.horizontalSlider4.value() self.statusbar.showMessage( "Changed value of perturbation slider 4 to " + str(new_value)) def randChangeSelected(self): if self.checkBox1.isChecked(): self.horizontalSlider1.setValue( randint(1, self.horizontalSlider2.maximum())) if self.checkBox2.isChecked(): self.horizontalSlider2.setValue( randint(1, self.horizontalSlider2.maximum())) if self.checkBox3.isChecked(): self.horizontalSlider3.setValue( randint(1, self.horizontalSlider3.maximum())) if self.checkBox4.isChecked(): self.horizontalSlider4.setValue( randint(1, self.horizontalSlider4.maximum())) def resetSelected(self): if self.checkBox1.isChecked(): self.horizontalSlider1.setValue(0) if self.checkBox2.isChecked(): self.horizontalSlider2.setValue(0) if self.checkBox3.isChecked(): self.horizontalSlider3.setValue(0) if self.checkBox4.isChecked(): self.horizontalSlider4.setValue(0) def loadTestData(self, MainWindow): print("Loading dummy data...") x = np.random.normal(size=1000) y = np.random.normal(size=1000) brush = pg.mkBrush(50, 200, 50, 120) hoverBrush = pg.mkBrush(200, 50, 50, 200) items = pg.ScatterPlotItem(x=x, y=y, pen='w', brush=brush, size=15, hoverable=True, hoverBrush=hoverBrush) self.plotWidget.addItem(items) def loadData(self, MainWindow): print("Loading datasets...") X = np.load('data/X_mnist.npy') y = np.load('data/y_mnist.npy') label = "mnist-full" X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=10000, test_size=300, random_state=420, stratify=y) self.y_test = y_test # Class colors self.class_colors = [(0.890, 0.102, 0.110), (0.122, 0.471, 0.706), (0.698, 0.875, 0.541), (0.200, 0.627, 0.173), (0.984, 0.604, 0.600), (0.651, 0.808, 0.890), (0.992, 0.749, 0.435), (1.000, 0.498, 0.000), (0.792, 0.698, 0.839), (0.416, 0.239, 0.604), (1.000, 1.000, 0.600), (0.694, 0.349, 0.147)] self.dataset = Dataset(X_test) print("Loading NNP model...") self.model = keras.models.load_model("NNP_model_" + label) pred = self.model.predict(X_test) self.brushes = [] for label in y_test: color = self.class_colors[label] self.brushes.append( QBrush(QColor.fromRgbF(color[0], color[1], color[2]))) items = pg.ScatterPlotItem(x=pred[:, 0], y=pred[:, 1], data=np.arange(len(X_test)), pen='w', brush=self.brushes, size=10, hoverable=True, hoverPen=pg.mkPen(0, 0, 0, 255)) self.plotWidget.addItem(items)