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_YourSignalWindow(object): def __init__(self, data): self.data = data def setupUi(self, YourSignalWindow): YourSignalWindow.setObjectName("YourSignalWindow") YourSignalWindow.resize(888, 658) self.centralwidget = QtWidgets.QWidget(YourSignalWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.graphicsView = PlotWidget(self.centralwidget) self.graphicsView.setObjectName("graphicsView") self.gridLayout.addWidget(self.graphicsView, 0, 0, 1, 1) YourSignalWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(YourSignalWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 888, 25)) self.menubar.setObjectName("menubar") YourSignalWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(YourSignalWindow) self.statusbar.setObjectName("statusbar") YourSignalWindow.setStatusBar(self.statusbar) self.retranslateUi(YourSignalWindow) QtCore.QMetaObject.connectSlotsByName(YourSignalWindow) def retranslateUi(self, YourSignalWindow): _translate = QtCore.QCoreApplication.translate YourSignalWindow.setWindowTitle( _translate("YourSignalWindow", "YourSignalWindow")) self.DrawOriginalSiganal() def DrawOriginalSiganal(self): self.graphicsView.plot(self.data)
class ExampleApp(QtGui.QMainWindow): def __init__(self): super().__init__() pyqtgraph.setConfigOption('background', 'w') self.setupUi(self) def setupUi(self, MainWindow): MainWindow.setObjectName('MainWindow') MainWindow.resize(900, 900) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.graphicsView = PlotWidget(self.centralwidget) self.graphicsView.setGeometry(QtCore.QRect(200, 200, 500, 500)) self.graphicsView.setObjectName("graphicsView") MainWindow.setCentralWidget(self.centralwidget) def update(self): points = 100 X = np.arange(points) n = 0 dataLst = [] while n < 100: dataPoint = ser.readline() dataPoint = float(dataPoint) dataLst.append(dataPoint) n += 1 Y = dataLst penn = pyqtgraph.mkPen('k', width=3, style=QtCore.Qt.SolidLine) self.graphicsView.setYRange(0, 1200, padding=0) labelStyle = {'color': '#000', 'font-size': '20px'} self.graphicsView.setLabel('bottom', 'Number of Points', '', **labelStyle) self.graphicsView.setLabel('left', 'Voltage', '', **labelStyle) self.graphicsView.plot(X, Y, pen=penn, clear=True) QtCore.QTimer.singleShot(1, self.update)
class HistView(QWidget): def __init__(self, tracker: Tracker, parent=None): super().__init__(parent=parent) self.tracker = tracker params = ['x0', 'y0', 'sigma_x', 'sigma_y', 'A', 'theta'] self.buttons = {} self.cur_param: Optional[str] = None hlay = QHBoxLayout(self) layout = QVBoxLayout() hlay.addLayout(layout) self.setLayout(hlay) hlay.setContentsMargins(0, 0, 0, 0) for l in params: self.buttons[l] = QPushButton(l) self.buttons[l].clicked.connect(lambda x, l=l: self.show_param(l)) layout.addWidget(self.buttons[l]) layout.addStretch(1) self.plot_widget = PlotWidget(self) ax = DateAxisItem() self.plot_widget.plotItem.setAxisItems({'bottom': ax}) hlay.addWidget(self.plot_widget) def show_param(self, s: str): self.cur_param = s @Slot() def update_plot(self): if self.cur_param is None: return self.plot_widget.plotItem.clear() for c in self.tracker.cams: for i, p in enumerate(['x0', 'y0', 'sigma_x', 'sigma_y']): x, y = self.tracker.get_param_history(c.name, p) self.plot_widget.plot(x, y, pen=mkPen(i))
def __init__(self, parent=None): super(Form, self).__init__() self.tab = QTabWidget() # Add demo data for tab 1 x = np.random.normal(size=1000) y = np.random.normal(size=1000) plot1 = PlotWidget() plot1.plot(x, y, pen=None, symbol='o') self.tab.insertTab(0, plot1, "random") # Add demo data for tab 2 x = np.linspace(0, 6*np.pi, 1000) y = np.sin(x) plot2 = PlotWidget() plot2.plot(x, y) self.tab.insertTab(1, plot2, "sinus") self.main_window = QMainWindow() self.main_window.setCentralWidget(self.tab) self.main_window.show() # Force the window to stay on top self.setWindowFlags(Qt.WindowStaysOnTopHint)
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()
class Ui_MainWindow_Company_Scatter_Plot(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 650) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(10, 600, 850, 31)) font = QtGui.QFont() font.setPointSize(10) self.label.setFont(font) self.label.setObjectName("label") read_company_records() read_altered_company_records() alphabet_value = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] unaltered_employee_names = company_name_value_array altered_employee_names = altered_company_name_value_array self.graphWidget = PlotWidget(self.centralwidget) self.graphWidget.setGeometry(QtCore.QRect(0, 0, 785, 580)) self.graphWidget.setObjectName("graphWidget") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.graphWidget.setLabel('left', 'Number of occurrences of company names first letter values', color='red', size=30) self.graphWidget.setLabel('bottom', 'Company Names sorted by first letter in a companies name', color='red', size=30) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.graphWidget.addLegend() self.graphWidget.showGrid(x=True, y=True) self.graphWidget.setXRange(0, 26.5, padding=0) self.graphWidget.setYRange(0, 300, padding=0) try: self.plot(alphabet_value, unaltered_employee_names, "Original Company Names", 'r') self.plot(alphabet_value, altered_employee_names, "Altered Company Names", 'b') except Exception: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Error! Please close existing window.") msg.setInformativeText('You can only have one window open at a time. Please close the existing window to continue!') msg.setWindowTitle("Error") msg.exec_() pass def plot(self, x, y, plotname, color): pen = pg.mkPen(color=color) self.graphWidget.plot(x, y, name=plotname, pen=pen, symbol='+', symbolSize=10, symbolBrush=(color)) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Differential Privacy Engine")) self.label.setText(_translate("MainWindow", "NOTE: This graph displays the difference between company names if the Differential Privacy Engine includes the company name values."))
class 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()
class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() self.current_y = 0 #self.timer = QtCore.QTimer() #self.timer.timeout.connect(self.update_plot) #self.timer.setInterval(1000/FREQ) #self.timer.start() def initUI(self): self.setGeometry(300, 300, 1000, 1000) self.setWindowTitle('Icon') self.setWindowIcon(QtGui.QIcon('web.png')) self.plot = PlotWidget(self) self.plot.resize(900, 900) self.curves = [] for x, y in zip(chunkedx, chunkedy): print('plot', len(x), len(y)) self.curves.append(self.plot.plot(x, y)) print(self.curves[-1]) self.show() @timeme def update_plot(self): self.curves[-1].setData(small_x, ys[self.current_y]) self.current_y = (self.current_y + 1) % YS
def plot_mode(self, resultset): self.clear() for result in resultset: name = next(iter(result.keys())) plotwidget = PlotWidget( labels={'bottom': 'q (\u212B\u207B\u00B9)', 'left': 'I (a.u.)', 'top': 'd (nm)'}) def tickStrings(values, scale, spacing): return ['{:.3f}'.format(.2 * np.pi / i) if i != 0 else '\u221E' for i in values] plotwidget.plotItem.axes['top']['item'].tickStrings = tickStrings plotwidget.plot(*list(output.value for output in result.values()), name=name) self.addTab(plotwidget, name)
class MonitorWindow(QMainWindow): def __init__(self, experiment=None): super().__init__() self.experiment = experiment self.layout = QHBoxLayout() self.central_widget = QWidget() self.central_widget.setLayout(self.layout) self.plot_widget = PlotWidget() self.layout.addWidget(self.plot_widget) self.setCentralWidget(self.central_widget) self.plot = self.plot_widget.plot([0], [0]) self.start_button = QPushButton('Start') self.start_button.clicked.connect(self.experiment.start_monitor) self.stop_button = QPushButton('Stop') self.stop_button.clicked.connect(self.experiment.stop_monitor) self.layout.addWidget(self.start_button) self.layout.addWidget(self.stop_button) self.timer = QTimer() self.timer.timeout.connect(self.update_plot) self.timer.start(30) def update_plot(self): self.plot.setData(self.experiment.monitor_data)
class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() self.current_y = 0 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.update_plot) self.timer.setInterval(1000/FREQ) self.timer.start() def initUI(self): self.setGeometry(300, 300, 1000, 1000) self.setWindowTitle('Icon') self.setWindowIcon(QtGui.QIcon('web.png')) self.plot = PlotWidget(self, axisItems={'bottom': TimeAxisItem(orientation='bottom')}) self.plot.resize(900, 900) self.curve = self.plot.plot(x, ys[0]) #self.curve.attach(self.plot) self.show() def update_plot(self): self.curve.setData(x, ys[self.current_y]) self.current_y = (self.current_y + 1) % YS
class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() self.current_y = 0 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.update_plot) self.timer.setInterval(1000 / FREQ) self.timer.start() def initUI(self): self.setGeometry(300, 300, 1000, 1000) self.setWindowTitle('Icon') self.setWindowIcon(QtGui.QIcon('web.png')) self.plot = PlotWidget( self, axisItems={'bottom': TimeAxisItem(orientation='bottom')}) self.plot.resize(900, 900) self.curve = self.plot.plot(x, ys[0]) #self.curve.attach(self.plot) self.show() def update_plot(self): self.curve.setData(x, ys[self.current_y]) self.current_y = (self.current_y + 1) % YS
class PyQtGraphDataPlot(QWidget): _colors = [ Qt.red, Qt.blue, Qt.magenta, Qt.cyan, Qt.green, Qt.darkYellow, Qt.black, Qt.darkRed, Qt.gray, Qt.darkCyan ] def __init__(self, parent=None): super(PyQtGraphDataPlot, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.setBackground((255, 255, 255)) self._plot_widget.setXRange(0, 10, padding=0) self.legend = self._plot_widget.addLegend() vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._color_index = 0 self._curves = {} def add_curve(self, curve_id, curve_name, data_x, data_y): color = QColor(self._colors[self._color_index % len(self._colors)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot} self._update_legend() def remove_curve(self, curve_id): curve_id = str(curve_id) if curve_id in self._curves: self._plot_widget.removeItem(self._curves[curve_id]['plot']) del self._curves[curve_id] self._update_legend() def _update_legend(self): # TODO Figure this out pass @Slot(str, list, list) def update_values(self, curve_id, x, y): curve = self._curves[curve_id] curve['x'] = numpy.append(curve['x'], x) curve['y'] = numpy.append(curve['y'], y) def redraw(self): # Set axis bounds x_range, _ = self._plot_widget.viewRange() x_delta = x_range[1] - x_range[0] x_max = 0 for curve in self._curves.values(): if len(curve['x']) == 0: continue x_max = max(x_max, curve['x'][-1]) curve['plot'].setData(curve['x'], curve['y']) self._plot_widget.setXRange(x_max - x_delta, x_max, padding=0)
class UiVisualConsumos(GraphicsLayoutWidget): def __init__(self): super().__init__() self.threadpool = QThreadPool() self.cpuUsage = [] self.countTime = [] self.start_time = time() self.timer = QTimer() # --------------------------------------------------------------------------- self.plot_view = PlotWidget() self.plot_view.plotItem.setTitle("Processor percent usage") setConfigOptions(antialias=False) # --------------------------------------------------------------------------- self.hour = [] self.temperature = [] # --------------------------------------------------------------------------- self.plot_view.plot(self.hour, self.temperature, pen=mkPen(cosmetic=True, width=40.0, color='r')) self.plot_view.setLabel('left', "Processor usage", units='%') # --------------------------------------------------------------------------- self.main_layout = QVBoxLayout() self.main_layout.addWidget(self.plot_view) self.setLayout(self.main_layout) @Slot() def refresh(self, n): self.hour.append(n[0]) self.temperature.append(n[1]) self.plot_view.plot(self.hour, self.temperature, pen='r') @Slot() def init_logica(self, cpu_usage_callback): cpu_usage_callback.emit( [float(time() - self.start_time), float(psutil.cpu_percent())])
class ExampleApp(QtGui.QMainWindow): def __init__(self): super().__init__() pyqtgraph.setConfigOption('background', 'w') # self.setupUi(self) def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(350, 300) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") # the plot widget self.graphicsView = PlotWidget( self.centralwidget) # assign this PlotWidget to the graphicsView. self.graphicsView.setGeometry(QtCore.QRect(20, 20, 300, 300)) self.graphicsView.setObjectName("graphicsView") # MainWindow.setCentralWidget(self.centralwidget) def analogInput(self, channel): spi.max_speed_hz = 1350000 adc = spi.xfer2([1, (8 + channel) << 4, 0]) data = ((adc[1] & 3) << 8) + adc[2] return data def update(self): points = 100 #number of data points X = np.arange(points) n = 0 dataLst = [] while n < 100: dataPoint = self.analogInput(0) # Reading from CH0 #dataPoint=int(dataPoint) dataLst.append(dataPoint) n += 1 Y = dataLst penn = pyqtgraph.mkPen('k', width=3, style=QtCore.Qt.SolidLine) self.graphicsView.setYRange(0, 1200, padding=0) labelStyle = {'color': '#000', 'font-size': '20px'} self.graphicsView.setLabel('bottom', 'Number of Points', '', **labelStyle) self.graphicsView.setLabel('left', 'Voltage', '', **labelStyle) self.graphicsView.plot(X, Y, pen=penn, clear=True) QtCore.QTimer.singleShot( 1, self.update ) # 1 ms, QUICKLY repeat, recursively. Use this timer to invoke the 'update()' function recursively.
class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.setGeometry(300, 300, 400, 400) self.plot = PlotWidget(self, axisItems={'bottom': TimeAxisItem(orientation='bottom')}) self.plot.resize(300, 300) self.curve = self.plot.plot(np.linspace(0, 10, 100), np.random.random(100)) self.show()
def draw_right_part(self): rightPart = QtGui.QVBoxLayout() from pyqtgraph import PlotWidget pl = PlotWidget() self.plotU = pl.plot(pen=(255, 0, 0)) rightPart.addWidget(pl) self.menuLayout = QtGui.QGridLayout() temp = QtGui.QHBoxLayout() templabel = QtGui.QLabel(u' COM порт № ') self.text_COM_number = QtGui.QLineEdit() temp.addWidget(templabel) temp.addWidget(self.text_COM_number) self.button_setCOM = QtGui.QPushButton(u'Выбрать') self.button_setCOM.clicked.connect(self.button_setCOM_pressed) temp.addWidget(self.button_setCOM) temp.addStretch(1) #self.menuLayout.addWidget(self.button_setCOM, 0, 1)#, alignment=1) self.menuLayout.addLayout(temp,0,0) temp = QtGui.QHBoxLayout() self.button_hardware = QtGui.QPushButton(u'Старт платформы') self.button_hardware.clicked.connect(self.button_hardware_pressed) temp.addWidget(self.button_hardware) #self.menuLayout.addWidget(self.button_hardware, 1, 0)#, alignment=1) self.button_watch = QtGui.QPushButton(u'Начать просмотр') self.button_watch.clicked.connect(self.button_watch_pressed) temp.addWidget(self.button_watch) self.button_record = QtGui.QPushButton(u' Начать запись ') self.button_record.clicked.connect(self.button_record_pressed) temp.addWidget(self.button_record) temp.addStretch(1) self.menuLayout.addLayout(temp, 1,0)#Widget(self.button_watch, 1, 1)#, alignment=1) self.menuLayout.addLayout(self.build_parameters_menu(), 2, 0) temp = QtGui.QHBoxLayout() temp.insertSpacing(-1, 10) self.string_message = QtGui.QLineEdit() temp.addWidget(self.string_message) self.button_send_string = QtGui.QPushButton(u'Отправить строку') self.button_send_string.clicked.connect(self.button_send_string_pressed) temp.addWidget(self.button_send_string) temp.insertStretch(-1, 1) self.menuLayout.addLayout(temp, 3, 0)#, alignment=1) rightPart.addLayout(self.menuLayout) self.parts[1].setLayout(rightPart)
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 RealtimePlotWidget(QWidget): COLORS = [ Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray ] def __init__(self, parent=None): super(RealtimePlotWidget, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.enableAutoRange() self._plot_widget.showGrid(x=True, y=True, alpha=0.2) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._color_index = 0 self._curves = {} def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot} def remove_curve(self, curve_id): curve_id = str(curve_id) if curve_id in self._curves: self._plot_widget.removeItem(self._curves[curve_id]['plot']) del self._curves[curve_id] def set_x_range(self, left, right): self._plot_widget.setRange(xRange=(left, right)) def update_values(self, curve_id, x, y): curve = self._curves[curve_id] curve['x'] = numpy.append(curve['x'], x) curve['y'] = numpy.append(curve['y'], y) def redraw(self): for curve in self._curves.values(): if len(curve['x']): curve['plot'].setData(curve['x'], curve['y']) def lazy_redraw(self, period): timestamp = time.time() if not hasattr(self, '_prev_lazy_redraw'): self._prev_lazy_redraw = 0.0 if timestamp - self._prev_lazy_redraw > period: self._prev_lazy_redraw = timestamp self.redraw()
def __init__(self, name, *args): super().__init__() self.setObjectName(name + 'widget') self.setAutoFillBackground(True) self.setStyleSheet("background-color: rgb(60, 63, 65);") self.simulation_vars = {} layout = QGridLayout() layout.setObjectName(name + 'layout') for i, widget in enumerate(args): # make a label for the widget wlabel = QLabel(widget.string) wlabel.setObjectName(widget.key + '_label') wlabel.setStyleSheet('color: white') wlabel.setAlignment(Qt.AlignCenter) # Make a QDoubleSpinBox widget wbox = QDoubleSpinBox() wbox.setObjectName(widget.key) wbox.setStyleSheet('color: white') wbox.setRange(*widget.range) # SET RANGE BEFORE VALUE wbox.setValue(widget.value) wbox.setAlignment(Qt.AlignCenter) wbox.setAccelerated(True) # Add label (above) and spinbox (below) to layout layout.addWidget(wlabel, 0, i) layout.addWidget(wbox, 1, i) # Store the default simulation value self.simulation_vars[widget.key] = widget.value # update the view if this widget's value is changed # Using the lambda expression below allows extra information to # be passed to the self.update slot, allowing the delegator to # see who sent the signal, update the dictionary of model # inputs, call the model for a simulation result, and plot # it. See: # https://mfitzp.io/article/transmit-extra-data-with-signals-in-pyqt/ wbox.valueChanged.connect( lambda val, key=widget.key: self.parent().parent().updateView(key, val)) # Add pyqtgraph widget setConfigOption('background', (43, 43, 43)) setConfigOption('foreground', (187, 187, 187)) graphicsView = PlotWidget() layout.addWidget(graphicsView, 2, 0, 1, len(twosinglets_vars)) plots.append(graphicsView.plot()) # lets the graph span the entire width of the window, no matter how # many input widgets appear above self.setLayout(layout)
class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.setGeometry(300, 300, 400, 400) self.plot = PlotWidget( self, axisItems={'bottom': TimeAxisItem(orientation='bottom')}) self.plot.resize(300, 300) self.curve = self.plot.plot(np.linspace(0, 10, 100), np.random.random(100)) self.show()
class RealtimePlotWidget(QWidget): COLORS = [Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray] def __init__(self, parent=None): super(RealtimePlotWidget, self).__init__(parent) self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.enableAutoRange() self._plot_widget.showGrid(x=True, y=True, alpha=0.2) vbox = QVBoxLayout() vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._color_index = 0 self._curves = {} def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot} def remove_curve(self, curve_id): curve_id = str(curve_id) if curve_id in self._curves: self._plot_widget.removeItem(self._curves[curve_id]['plot']) del self._curves[curve_id] def set_x_range(self, left, right): self._plot_widget.setRange(xRange=(left, right)) def update_values(self, curve_id, x, y): curve = self._curves[curve_id] curve['x'] = numpy.append(curve['x'], x) curve['y'] = numpy.append(curve['y'], y) def redraw(self): for curve in self._curves.values(): if len(curve['x']): curve['plot'].setData(curve['x'], curve['y']) def lazy_redraw(self, period): timestamp = time.time() if not hasattr(self, '_prev_lazy_redraw'): self._prev_lazy_redraw = 0.0 if timestamp - self._prev_lazy_redraw > period: self._prev_lazy_redraw = timestamp self.redraw()
def __init__(self,channel,trace,units): QtGui.QDialog.__init__(self) layout = QtGui.QVBoxLayout() self.setLayout(layout) plot_widget = PlotWidget( title='%s trace' % channel, labels={'left':units} ) layout.addWidget(plot_widget) plot = plot_widget.plot(trace) self.plot = plot self.trace = trace
def on_pushButton_3_clicked(self): """ Slot documentation goes here. """ # answers = [] # for answer in db['question_'+str(self.index)].find(): # text = answer['content'].replace('\n', '') # if 5 < len(text) < 100: # answers.append(text) answers = [ answer['content'].replace('\n', '') for answer in db['question_' + str(self.index)].find() ] Line1 = InfiniteLine(pos=0, pen=(255, 0, 0), angle=0, movable=False) Line2 = InfiniteLine(pos=0.5, pen=(0, 0, 255), angle=0, movable=False) Line3 = InfiniteLine(pos=1, pen=(0, 255, 0), angle=0, movable=False) import sys start = perf_counter() data = LSTM.get_result(answers, vec_path=sys.path[0] + '/lstm/vec_lstm.pkl', model_path=sys.path[0] + '/lstm/lstmModel.pkl') end = perf_counter() print('情感分析总用时:' + str(end - start) + 's') tricks = [(0, '消极'), (0.5, '中立'), (1, '积极')] strAxis = AxisItem(orientation='left', maxTickLength=3) strAxis.setTicks([ tricks, ]) visitor_count_plot = PlotWidget(axisItems={'left': strAxis}, background=None) visitor_count_plot.plot(y=data, pen=None, symbol='o') visitor_count_plot.showAxis('bottom', False) visitor_count_plot.addItem(Line1) visitor_count_plot.addItem(Line2) visitor_count_plot.addItem(Line3) visitor_count_plot.setObjectName("tab") # visitor_count_plot.enableAutoRange('x', x_axis_scale) self._add_analysis_tab(visitor_count_plot, '情感分析') self.pushButton_3.setEnabled(False)
def update_graph(self, graph: pg.PlotWidget, x, y, y_name, x_Unit, y_Unit='V', color=(255, 255, 102)): """ Updates a graph :param graph: plotWidget :param x: x dataset :param y: y dataset :param y_name: name (MUST) :param color: default: 255, 255, 102 :return: """ sizex = len(x) sizey = len(y) np_x = np.asarray(x) np_y = np.asarray(y) if sizex == sizey: dataItems = graph.listDataItems() for i in dataItems: # console(i.name(), " ", y_name) if i is not None: if i.name() == y_name: graph.removeItem(i) cpen = mkPen(color=color, width=3) # npx, npy = get_mod_array(np_x, np_y, self.ui.corZeroBox.isChecked(), self.ui.formulaEdit.text()) graph.plot(np_x, np_y, pen=cpen, name=y_name) self.replot_saved_graphs() graph.setLabel('bottom', "Time scale", units=str(x_Unit)) graph.setLabel('left', "CH scale", units=str(y_Unit)) else: console("Inequality", y_name, " ; ", sizex, " ; ", sizey) self.append_html_paragraph( "Inequality: " + str(y_name) + " ; " + str(sizex) + " ; " + str(sizey), -1, True)
def _plot_prediction(self, historical_dfs: list[pd.DataFrame], model: RandomForest, prediction: ndarray, target_date: datetime.date) -> None: """Opens a window with a plot of the historical target data as well as the prediction the model made.""" hdf = historical_dfs[0] for frame in historical_dfs[1:]: hdf = hdf.combine_first(frame) window_end = target_date - \ pd.DateOffset(days=model.window.target_shift) window_start = window_end - pd.DateOffset(days=30 - 1) hdf = pd.Series( hdf.loc[window_end:window_start][model.window.target_lbl]) hdf_data = hdf.to_list() hdf_dates = hdf.index hdf_dates = [ts.to_pydatetime().timestamp() for ts in hdf_dates] b_axis = pg.DateAxisItem(orientation='bottom') b_axis.setLabel('Date') plot = PlotWidget(axisItems={'bottom': b_axis}) target_time = datetime.combine(target_date, datetime.min.time()) plot.addLegend() plot.plot(x=hdf_dates, y=hdf_data, name=f'Historical {model.window.target_lbl}') plot.plot(x=[target_time.timestamp()], y=prediction, pen=None, symbol='o', name=f'Predicted Value: {prediction[0]}') model_name = self._model.currentText() self._plot_window.setWindowTitle(f'{model_name} Prediction') self._plot_window.setCentralWidget(plot) self._plot_window.show()
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(751, 564) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.graphicsView = PlotWidget(self.centralwidget) self.graphicsView.setGeometry(QtCore.QRect(5, 11, 741, 391)) self.graphicsView.setObjectName("graphicsView") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(640, 420, 101, 21)) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(640, 440, 111, 16)) self.label_2.setObjectName("label_2") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(20, 500, 101, 31)) self.pushButton.setObjectName("pushButton") MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.graphicsView.plot(humx, humy, pen='g') self.graphicsView.plot(tempx, tempy, pen='r') #self.pushButton.clicked.connect() 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", "Green is Humidity")) self.label_2.setText(_translate("MainWindow", "Red is Temprature")) self.pushButton.setText(_translate("MainWindow", "Quit"))
def __init__(self, atri_plot: PlotWidget, vent_plot: PlotWidget, data_size: int): print("Graphs handler init") # noinspection PyArgumentList atri_plot.setRange(xRange=[-1, data_size], yRange=[-0.5, 5.5], padding=0) atri_plot.setLimits(xMin=-1, xMax=data_size, maxXRange=data_size + 1, yMin=-0.5, yMax=5.5) atri_plot.setMouseEnabled(x=True, y=False) atri_plot.enableAutoRange(x=False, y=True) atri_plot.setAutoVisible(x=False, y=True) atri_plot.showGrid(x=True, y=True) atri_plot.hideButtons() atri_plot.setMenuEnabled(False) atri_plot.setLabel('left', "Amplitude", units='V', **{'color': '#FFF', 'font-size': '10pt'}) atri_plot.setLabel('bottom', "Time", units='s', **{'color': '#FFF', 'font-size': '10pt'}) atri_plot.getAxis('bottom').setHeight(30) # noinspection PyArgumentList vent_plot.setRange(xRange=[-1, data_size], yRange=[-0.5, 5.5], padding=0) vent_plot.setLimits(xMin=-1, xMax=data_size, maxXRange=data_size + 1, yMin=-0.5, yMax=5.5) vent_plot.setMouseEnabled(x=True, y=False) vent_plot.enableAutoRange(x=False, y=True) vent_plot.setAutoVisible(x=False, y=True) vent_plot.showGrid(x=True, y=True) vent_plot.hideButtons() vent_plot.setMenuEnabled(False) vent_plot.setLabel('left', "Amplitude", units='V', **{'color': '#FFF', 'font-size': '10pt'}) vent_plot.setLabel('bottom', "Time", units='s', **{'color': '#FFF', 'font-size': '10pt'}) vent_plot.getAxis('bottom').setHeight(30) # Initialize graphs to 0 self._atri_data = np.zeros(data_size) self._vent_data = np.zeros(data_size) # Create new sense plots for the atrial and ventricular graphs, in blue self._atri_plot = atri_plot.plot(pen=(0, 229, 255)) self._vent_plot = vent_plot.plot(pen=(0, 229, 255)) self._plot_data()
class ExampleApp(QtGui.QMainWindow): def __init__(self): super().__init__() pyqtgraph.setConfigOption('background', 'w') self.setupUi(self) def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(900, 900) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName('centralwidget') # plot widget self.graphicsView = PlotWidget( self.centralwidget) # assign this plotwidget to the graphicsView self.graphicsView.setObjectName("graphicsView") MainWindow.setCentralWidget(self.centralwidget) def update(self): points = 100 x = np.array(points) n = 0 dataLst = [] while n < 200: dataPoint = ser.readline() dataPoint = int(dataPoint) dataLst.append(dataPoint) n += 1 y = dataLst penn = pyqtgraph.mkPen('k', width=3, style=QtCore.Qt.SolidLine) self.graphicsView.setYRange(0, 1200, padding=0) labelStyle = {'color': '#000', 'font-size': '20px'} self.graphicsView.setLabel('bottom', 'Number of Points', '', **labelStyle) self.graphicsView.plot(x, y, pen=penn, clear=True) QtCore.QTimer.singleShot(1, self.update)
class SimpleTestResultsDialog(QMainWindow): def __init__(self, parent=None, methods=None): super(SimpleTestResultsDialog, self).__init__(parent) self.setWindowTitle("Grismo - Wyniki dla prostego testu") self.setMinimumWidth(500) self.results_count = 0 self.all_results = [] self.methods = methods central = QWidget() self.setCentralWidget(central) result_dialog_layout = QVBoxLayout() central.setLayout(result_dialog_layout) self.results_table = QTableWidget() result_dialog_layout.addWidget(self.results_table) self.results_table.setRowCount(len(methods)) self.results_table.setColumnCount(3) self.results_table.setColumnWidth(2, 200) self.results_table.setHorizontalHeaderLabels(["Metoda", "Wynik", "Czas [s]"]) for i in range(len(methods)): self.results_table.setItem(i, 0, QTableWidgetItem(methods[i])) # plot box x_axis_dict = dict(enumerate(methods)) x_axis = AxisItem(orientation='bottom') x_axis.setTicks([x_axis_dict.items()]) self.results_plot = PlotWidget(axisItems={'bottom': x_axis}) self.results_plot.setBackground('w') self.results_plot.setTitle("Porównanie metod dla wskazanych grafów") self.results_plot.setLabel('left', 'Czas obliczeń [s]', color='k', size=10) self.results_plot.setLabel('bottom', 'Metody ', color='k', size=10) self.results_plot.setMaximumWidth(600) self.results_plot.showGrid(y=True) result_dialog_layout.addWidget(self.results_plot) # prepare plot data pen = mkPen(color='k', width=2) self.plot_data = self.results_plot.plot([], [], pen=pen, symbol='+', symbolSize=10, symbolBrush='k') def add_result(self, result): for i in range(len(result)): self.results_table.setItem(self.results_count, i, QTableWidgetItem(str(result[i]))) self.results_count = self.results_count + 1 self.all_results.append(result[-1]) self.plot_data.setData(range(len(self.all_results)), self.all_results)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23)) self.menubar.setObjectName("menubar") self.menufile = QtWidgets.QMenu(self.menubar) self.menufile.setObjectName("menufile") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionfileopen = QtWidgets.QAction(MainWindow) self.actionfileopen.setObjectName("actionfileopen") self.menufile.addAction(self.actionfileopen) self.menubar.addAction(self.menufile.menuAction()) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.plotWidget_ted = PlotWidget(self) self.plotWidget_ted.setGeometry(QtCore.QRect(5, 5, 800, 600)) self.data1 = np.random.normal(size=300) self.curve2 = self.plotWidget_ted.plot(self.data1, name="mode2") self.ptr1 = 0 self.timer = pq.QtCore.QTimer() self.timer.timeout.connect(self.update_data) self.timer.start(50) def update_data(self): self.data1[:-1] = self.data1[1:] self.data1[-1] = np.random.normal() self.curve2.setData(self.data1) self.ptr1 += 1 self.curve2.setPos(self.ptr1, 0) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.menufile.setTitle(_translate("MainWindow", "file"))
def create_graph_plot(gui, graph: PlotWidget, x: tuple, y: tuple, plotName: str, color: str): """ Creates a graph plot with parameters provided. :param gui: Graphical user interface in which to set up graphs. :param graph: Graph function will plot on. :param x: X values of graph. :param y: Y values of graph. :param plotName: Name of graph. :param color: Color graph will be drawn in. """ pen = mkPen(color=color) plot = graph.plot(x, y, name=plotName, pen=pen, autoDownsample=True, downsampleMethod='subsample') plot.curve.scene().sigMouseMoved.connect( lambda point: onMouseMoved(gui=gui, point=point, graph=graph)) return plot
class Canvas2Dupgraded(PlotWidget, AnimatedWidget): def __init__(self, parent=None, data_dict=None): super(Canvas2Dupgraded, self).__init__() self.shareData(**data_dict) self.plotWidget = PlotWidget(self) self._i = self.current_state self.title = self.options['column'] self.graph_data = self.plot_data[self.title].tolist() self.internal_iterations = len(self.graph_data) self.createPlotCanvas() def createPlotCanvas(self): self.null_data = np.array([i for i in range(self.internal_iterations)]) self.plotWidget.setTitle(self.title) self.plotWidget.setGeometry(0, 0, self.geom[0] - 60, self.geom[1] - 60) self.plotWidget.setXRange(0, self.internal_iterations) self.plotWidget.setYRange(np.min(self.graph_data), np.max(self.graph_data), padding=0.1) self.plotWidget.enableAutoRange('xy', False) self.plotData = self.plotWidget.plot( self.graph_data[:self._i], pen=pg.mkPen(color=self.options['color'][0], width=self.options['marker_size']), name="data1", clear=True) def on_resize_geometry_reset(self, geom): """ when another widget is promoted, this window must resize too this means resetting the graph unfortunately """ self.plotWidget.setGeometry(0, 0, geom[0] - 60, geom[1] - 60) def set_i(self, value, trigger=False, record=False): self._i = value self._i %= self.internal_iterations self.plotData.setData(self.null_data[:self._i], self.graph_data[:self._i]) pg.QtGui.QApplication.processEvents()
def __init__(self, time_series, topographies, filters, channel_names, fs, scores, scores_name='Mutual info', marks=None, *args): super(ScoredComponentsTable, self).__init__(*args) # attributes self.row_items_max_height = 125 self.time_series = time_series self.marks = marks self.channel_names = channel_names self.fs = fs # set size and names self.columns = ['Selection', scores_name, 'Topography', 'Time series (push to switch mode)'] self.setColumnCount(len(self.columns)) self.setRowCount(time_series.shape[1]) self.setHorizontalHeaderLabels(self.columns) # columns widgets self.checkboxes = [] self.topographies_items = [] self.plot_items = [] self.scores = [] _previous_plot_link = None for ind in range(self.rowCount()): # checkboxes checkbox = QtWidgets.QCheckBox() self.checkboxes.append(checkbox) self.setCellWidget(ind, self.columns.index('Selection'), checkbox) # topographies and filters topo_filter = TopoFilterCavas(self, self.channel_names, topographies[:, ind], filters[:, ind], self.row_items_max_height) self.topographies_items.append(topo_filter) self.setCellWidget(ind, self.columns.index('Topography'), topo_filter) # plots plot_widget = PlotWidget(enableMenu=False) if _previous_plot_link is not None: plot_widget.setXLink(_previous_plot_link) # plot_widget.setYLink(_previous_plot_link) _previous_plot_link = plot_widget plot_widget.plot(y=self.time_series[:, ind]) if self.marks is not None: plot_widget.plot(y=self.marks*np.max(self.time_series[:, ind]), pen=(1,3)) plot_widget.plot(y=-self.marks * np.max(self.time_series[:, ind]), pen=(1, 3)) plot_widget.plot(x=np.arange(self.time_series.shape[0]) / fs) plot_widget.setMaximumHeight(self.row_items_max_height) plot_widget.plotItem.getViewBox().state['wheelScaleFactor'] = 0 self.plot_items.append(plot_widget) self.setCellWidget(ind, 3, plot_widget) # scores score_widget = BarLabelWidget(scores[ind], max(scores), min(scores)) self.scores.append(score_widget) self.setCellWidget(ind, self.columns.index(scores_name), score_widget) # formatting self.current_row = None self.horizontalHeader().setStretchLastSection(True) self.resizeColumnsToContents() self.resizeRowsToContents() # clickable 3 column header self.horizontalHeader().sectionClicked.connect(self.handle_header_click) self.is_spectrum_mode = False # reorder self.order = np.argsort(scores) self.reorder() # checkbox signals for checkbox in self.checkboxes: checkbox.stateChanged.connect(self.checkboxes_state_changed) # selection context menu header = self.horizontalHeader() header.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) header.customContextMenuRequested.connect(self.handle_header_menu) # ctrl+a short cut QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_A), self).activated.connect(self.ctrl_plus_a_event) # checkbox cell clicked self.cellClicked.connect(self.cell_was_clicked)
def init_gui(self): layout = QtGui.QVBoxLayout() self.setLayout(layout) plot_widget = PlotWidget() layout.addWidget(plot_widget) fragments = [] for type, entry in self.formula: if type is CHANNEL_TYPE: fragments.append("(%s)" % entry) elif type is OPERATION_TYPE: fragments.append({value: key for key, value in operations.items()}[entry]) elif type is NUMBER_TYPE: fragments.append(str(entry)) formula_label = QtGui.QLabel("\t".join(fragments)) layout.addWidget(formula_label) controls_layout = QtGui.QHBoxLayout() layout.addLayout(controls_layout) controls_layout.addWidget(QtGui.QLabel("moving average")) moving_average_spin = QtGui.QSpinBox() moving_average_spin.setSuffix("samples") moving_average_spin.setRange(1, MAX_AVERAGE) controls_layout.addWidget(moving_average_spin) controls_layout.addStretch() controls_layout.addWidget(QtGui.QLabel("shots averaging")) shots_spin = QtGui.QSpinBox() shots_spin.setSuffix("shots") shots_spin.setRange(1, MAX_SHOTS) controls_layout.addWidget(shots_spin) controls_layout.addStretch() run_check = QtGui.QCheckBox("run") controls_layout.addWidget(run_check) plot = plot_widget.plot() client = yield connectAsync() vm = client.voltmeter self.trace = np.zeros(HISTORY + MAX_AVERAGE) def on_moving_average_changed(_): update_plot() moving_average_spin.valueChanged.connect(on_moving_average_changed) def update_plot(): samples = moving_average_spin.value() plot.setData(moving_average(self.trace[: HISTORY + samples - 1], samples)) @inlineCallbacks def on_run(): if run_check.isChecked(): sample = yield get_sample() self.trace = np.roll(self.trace, 1) self.trace[0] = sample update_plot() on_run() run_check.clicked.connect(on_run) @inlineCallbacks def get_sample(): deferreds = {} shots = shots_spin.value() channels = tuple(set([entry for type, entry in self.formula if type is CHANNEL_TYPE])) packet = vm.packet() voltages = {channel: 0.0 for channel in channels} for channel in channels: packet.get_sample(channel) for shot in range(shots): response = yield packet.send() if len(channels) is 1: voltages[channels[0]] += response.get_sample / shots elif len(channels) > 1: for channel, voltage in zip(channels, response.get_sample): voltages[channel] += voltage / shots stack = [] for type, entry in self.formula: if type is OPERATION_TYPE: v1 = stack.pop() v2 = stack.pop() stack.append(entry(v2, v1)) else: if type is CHANNEL_TYPE: stack.append(voltages[entry]) else: stack.append(entry) returnValue(stack.pop())
class BusMonitorWidget(QGroupBox): DEFAULT_PLOT_X_RANGE = 120 BUS_LOAD_PLOT_MAX_SAMPLES = 5000 def __init__(self, parent, node, iface_name): super(BusMonitorWidget, self).__init__(parent) self.setTitle('CAN bus activity (%s)' % iface_name.split(os.path.sep)[-1]) self._node = node self._hook_handle = self._node.can_driver.add_io_hook(self._frame_hook) self._columns = [ BasicTable.Column('Dir', lambda e: (e[0].upper()), searchable=False), BasicTable.Column('Local Time', TimestampRenderer(), searchable=False), BasicTable.Column('CAN ID', lambda e: (('%0*X' % (8 if e[1].extended else 3, e[1].id)).rjust(8), colorize_can_id(e[1]))), BasicTable.Column('Data Hex', lambda e: (' '.join(['%02X' % x for x in e[1].data]).ljust(3 * e[1].MAX_DATA_LENGTH), colorize_transfer_id(e))), BasicTable.Column('Data ASCII', lambda e: (''.join([(chr(x) if 32 <= x <= 126 else '.') for x in e[1].data]), colorize_transfer_id(e))), BasicTable.Column('Src', lambda e: render_node_id_with_color(e[1], 'src')), BasicTable.Column('Dst', lambda e: render_node_id_with_color(e[1], 'dst')), BasicTable.Column('Data Type', lambda e: render_data_type_with_color(e[1]), resize_mode=QHeaderView.Stretch), ] self._log_widget = RealtimeLogWidget(self, columns=self._columns, font=get_monospace_font(), post_redraw_hook=self._redraw_hook) self._log_widget.on_selection_changed = self._update_measurement_display def flip_row_mark(row, col): if col == 0: item = self._log_widget.table.item(row, col) if item.icon().isNull(): item.setIcon(get_icon('circle')) flash(self, 'Row %d was marked, click again to unmark', row, duration=3) else: item.setIcon(QIcon()) self._log_widget.table.cellPressed.connect(flip_row_mark) self._stat_update_timer = QTimer(self) self._stat_update_timer.setSingleShot(False) self._stat_update_timer.timeout.connect(self._update_stat) self._stat_update_timer.start(500) self._traffic_stat = TrafficStatCounter() self._stat_frames_tx = QLabel('N/A', self) self._stat_frames_rx = QLabel('N/A', self) self._stat_traffic = QLabel('N/A', self) self._load_plot = PlotWidget(background=(0, 0, 0)) self._load_plot.setRange(xRange=(0, self.DEFAULT_PLOT_X_RANGE), padding=0) self._load_plot.setMaximumHeight(150) self._load_plot.setMinimumHeight(100) self._load_plot.setMinimumWidth(100) self._load_plot.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self._load_plot.showGrid(x=True, y=True, alpha=0.4) self._load_plot.setToolTip('Frames per second') self._load_plot.getPlotItem().getViewBox().setMouseEnabled(x=True, y=False) self._load_plot.enableAutoRange() self._bus_load_plot = self._load_plot.plot(name='Frames per second', pen=mkPen(QColor(Qt.lightGray), width=1)) self._bus_load_samples = [], [] self._started_at_mono = time.monotonic() layout = QVBoxLayout(self) layout.addWidget(self._log_widget, 1) stat_vars_layout = QGridLayout(self) stat_layout_next_row = 0 def add_stat_row(label, value): nonlocal stat_layout_next_row stat_vars_layout.addWidget(QLabel(label, self), stat_layout_next_row, 0) stat_vars_layout.addWidget(value, stat_layout_next_row, 1) value.setMinimumWidth(75) stat_layout_next_row += 1 add_stat_row('Frames transmitted:', self._stat_frames_tx) add_stat_row('Frames received:', self._stat_frames_rx) add_stat_row('Frames per second:', self._stat_traffic) stat_vars_layout.setRowStretch(stat_layout_next_row, 1) stat_layout = QHBoxLayout(self) stat_layout.addLayout(stat_vars_layout) stat_layout.addWidget(self._load_plot, 1) layout.addLayout(stat_layout, 0) self.setLayout(layout) def close(self): self._hook_handle.remove() def _update_stat(self): bus_load, ts_mono = self._traffic_stat.get_frames_per_second() self._stat_traffic.setText(str(int(bus_load + 0.5))) if len(self._bus_load_samples[0]) >= self.BUS_LOAD_PLOT_MAX_SAMPLES: self._bus_load_samples[0].pop(0) self._bus_load_samples[1].pop(0) self._bus_load_samples[1].append(bus_load) self._bus_load_samples[0].append(ts_mono - self._started_at_mono) self._bus_load_plot.setData(*self._bus_load_samples) (xmin, xmax), _ = self._load_plot.viewRange() diff = xmax - xmin xmax = self._bus_load_samples[0][-1] xmin = self._bus_load_samples[0][-1] - diff self._load_plot.setRange(xRange=(xmin, xmax), padding=0) def _redraw_hook(self): self._stat_frames_tx.setText(str(self._traffic_stat.tx)) self._stat_frames_rx.setText(str(self._traffic_stat.rx)) def _frame_hook(self, direction, frame): self._traffic_stat.add_frame(direction, frame) self._log_widget.add_item_async((direction, frame)) def _update_measurement_display(self, selected_rows_cols): if not selected_rows_cols: return min_row = min([row for row, _ in selected_rows_cols]) max_row = max([row for row, _ in selected_rows_cols]) def get_row_ts(row): return TimestampRenderer.parse_timestamp(self._log_widget.table.item(row, 1).text()) def get_load_str(num_frames, dt): if dt >= 1e-6: return 'average load %.1f FPS' % (num_frames / dt) return 'average load is unknown' if min_row == max_row: num_frames = min_row first_ts = get_row_ts(0) current_ts = get_row_ts(min_row) dt = current_ts - first_ts flash(self, '%d frames from beginning, %.3f sec since first frame, %s', num_frames, dt, get_load_str(num_frames, dt)) else: num_frames = max_row - min_row + 1 first_ts = get_row_ts(min_row) last_ts = get_row_ts(max_row) dt = last_ts - first_ts flash(self, '%d frames, timedelta %.6f sec, %s', num_frames, dt, get_load_str(num_frames, dt))
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
def test(): ## BOILERPLATE ## import sys from PySide import QtGui, QtCore from math import sin if QtCore.QCoreApplication.instance() is None: app = QtGui.QApplication(sys.argv) import qt4reactor qt4reactor.install() ## BOILERPLATE ## #create the widget name even if you're not using it so that onStepped doesn't error listScanInputWidget = None def log(x): print x #configure a layout for the plot widget & controls to go side by side on widget = QtGui.QWidget() widget.show() layout = QtGui.QHBoxLayout() widget.setLayout(layout) # create a plot and associated widget from pyqtgraph import PlotWidget plotWidget = PlotWidget() plot = plotWidget.plot() layout.addWidget(plotWidget) #configure a control panel layout controlPanel = QtGui.QWidget() cpLayout = QtGui.QVBoxLayout() controlPanel.setLayout(cpLayout) #create a scanToggleObject scanToggle = ScanToggleObject() ''' #create a list scan input & widget listScanInput = ListScanInput(lambda(x):x,None) listScanInputWidget = ListScanInputWidget(listScanInput) cpLayout.addWidget(listScanInputWidget) scanToggle.toggled.connect( compose( listScanInputWidget.setDisabled, scanToggle.isToggled ) ) scanToggle.toggled.connect(partial(log,listScanInputWidget.listScanInput.positions)) scanToggle.setInput(listScanInput.next) ''' #create an interval scan input & widget intScanInput = IntervalScanInput(lambda(x):x,0,1000,10) scanToggle.setInput(intScanInput.next) intScanInputWidget = IntervalScanInputWidget(intScanInput,DEFAULTS) cpLayout.addWidget(intScanInputWidget) scanToggle.toggled.connect( compose( intScanInputWidget.setDisabled, scanToggle.isToggled ) ) #create scan output, for now a sine wave, this is where voltmeter would go def output(): result = sin(float(output.i)/output.res) output.i+=1 return result output.i = 0 output.res = 10 scanToggle.setOutput(output) # create a scan toggle x, y = [], [] def onActivationRequested(x,y): while x: x.pop() while y: y.pop() scanToggle.toggle() # not performing any setup, so go ahead and connect activation requests to toggle scanToggle.activationRequested.connect( partial( onActivationRequested, x, y ) ) # create a toggle widget from qtutils.toggle import ToggleWidget cpLayout.addWidget(ToggleWidget(scanToggle)) # handle the stepped signal from ab.abbase import sleep @inlineCallbacks def onStepped(data): input, output = data x.append(input) y.append(output) plot.setData(x,y) yield sleep(.05) scanToggle.completeStep() if listScanInputWidget is not None: listScanInputWidget.updateQueue() scanToggle.stepped.connect(onStepped) #for debug purposes, connect to toggle signal scanToggle.toggled.connect(partial(log,'toggled')) scanToggle.toggleRequested.connect(partial(log,'toggleRequested')) #add the control panel to the window and execute layout.addWidget(controlPanel) app.exec_()
def SmartScanGUI(): # oh god i'm so sorry. don't listen to him; he's never sorry. class self: x,y,err = [], [], [] refData = {} #configure a layout for the plot widget & controls to go side by side on widget = QtGui.QWidget() container.append(widget) widget.show() layout = QtGui.QHBoxLayout() widget.setLayout(layout) # create a plot and associated widget plotWidget = PlotWidget() plot = plotWidget.plot() layout.addWidget(plotWidget,1) # configure a control panel layout cpLayout = QtGui.QVBoxLayout() layout.addLayout(cpLayout) # configure the output widget outputPane = ComboWidget() cpLayout.addWidget(LabelWidget('output',outputPane)) ############################################################# VOLTMETER OUTPUT ########################################################### # add volt meter to scan output vmProtocol = yield getProtocol( (VM_DEBUG_SERVER_CONFIG if DEBUG else VM_SERVER_CONFIG)['url'] ) vmClient = VoltMeterClient(vmProtocol) vmWidget = VoltMeterOutputWidget(vmClient) outputPane.addTab(vmWidget,'voltmeter') ############################################################# BEGIN INPUTS ########################################################### # configure the input widget inputPane = ComboWidget() inputPane.setTabPosition(inputPane.West) cpLayout.addWidget(LabelWidget('input',inputPane),1) inputPane.addTab( ManualInputWidget(widget), 'manual' ) inputPane.addTab( ManualScanInputWidget(widget), 'manual scan' ) # 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) ############################################################# STEPPER MOTOR INPUTS ########################################################### if INPUTS_TOGGLE[SM_BOOL]: # add stepper motors to scan input smProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) smClients = { smID:ChunkedStepperMotorClient(smProtocol,smID) for smID in (KDP,BBO,PDL,LID,POL) } for smID,smClient in smClients.items(): thisInputWidget = CenterInputWidget( smClient.setPosition, smClient.cancel, -99999, 99999, 0, 0, 0, 1000, 0, 10, smClient.getPosition ) inputPane.addTab( thisInputWidget, { KDP:'kdp', BBO:'bbo', PDL:'pdl', LID:'lid', POL:'pol' }[smID] ) ''' ############################################################# WAVELENGTH SERVER INPUT ########################################################### if INPUTS_TOGGLE[WL_BOOL]: # add wavelength client to scan input wlProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) wlClient = WavelengthClient(wlProtocol) wlInputWidget = CenterInputWidget( wlClient.setWavelength, wlClient.cancelWavelengthSet, 24100.0, 25000.0, 2, 24200.0, 0.01, 100.0, 2, .2, wlClient.getWavelength ) inputPane.addTab( wlInputWidget, 'surf' ) ############################################################# POLARIZER SERVER INPUT ########################################################### if INPUTS_TOGGLE[POL_BOOL]: # add wavelength client to scan input polProtocol = yield getProtocol( TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER ) polClient = PolarizerClient(polProtocol) polInputWidget = CenterInputWidget( polClient.setAngle, #agent to progress the scan polClient.cancelAngleSet, #agent to abort the scan -720.0, #minimum value of scan bounds 720.0, #maximum value of scan bounds 2, #precision (number of zeroes after decimal) on bounds 90.0, #initial value for scan bounds 0.01, #minimum value of step size 180.0, #maximum value of scan bounds 2, #precision (number of zeroes after decimal) on step size 5.0, #initial value for step size polClient.getAngle #agent to read position for scan ) inputPane.addTab( polInputWidget, 'polServ' ) ''' ############################################################# DDG INPUTS ########################################################### if INPUTS_TOGGLE[DDG_BOOL]: # add delay generator to scan input dgProtocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER ) dgClient = DelayGeneratorClient(dgProtocol) delays = yield dgClient.getDelays() for dgID in delays.keys(): def setter(dgID): @inlineCallbacks def _setter(delay): yield dgClient.setPartnerDelay(dgID,delay) returnValue(delay) return _setter def getter(dgID): @inlineCallbacks def _getter(): delays = yield dgClient.getDelays() returnValue(delays[dgID]) return _getter def cancel(dgID): def _cancel(): pass return _cancel dgCombo = CenterInputWidget( setter(dgID), cancel(dgID), 1, 50000000, 0, 3896550.0, 0, 1000000, 1, 100, getter(dgID) ) inputPane.addTab( dgCombo, dgID ) ############################################################# END INPUTS ########################################################### ############################################################# SCANNING ########################################################### #create a scan toggle scanToggle = CancelScanToggleObject() scanPane = QtGui.QVBoxLayout() scanPane.addWidget(ToggleWidget(scanToggle)) repeatSpinBox = QtGui.QSpinBox() repeatSpinBox.setRange(1,10000) repeatSpinBox.setValue(1) scanPane.addWidget(LabelWidget('repeat',repeatSpinBox)) cpLayout.addWidget(LabelWidget('scan',scanPane)) def onActivationRequested(): # empty data for l in (self.x,self.y,self.err): while l: l.pop() # get current selected scan output, scan input scanOutput = outputPane.getOutput() scanInput = inputPane.getInput() scanToggle.setOutput(scanOutput.next) scanToggle.setInput(scanInput.next) # on stop request, send cancel signal to scan input and output def cancel(): scanInput.cancel() scanOutput.cancel() scanToggle.setCancel(cancel) # set autoscale on x & y axes when a new scan is started plotWidget.enableAutoRange() # start scan scanToggle.toggle() scanToggle.activationRequested.connect(onActivationRequested) ############################################################# PLOTTING ########################################################### 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) ) ) # plot on step completion def updatePlot(): plotWidget.clear() for name, refData in self.refData.iteritems(): xYPlot( plotWidget, refData['data'][0], refData['data'][1], yerr=refData['data'][2], color=refData['color'], name=name ) if len(self.x) >= 1: xYPlot(plotWidget,self.x,self.y,yerr=self.err) def onStepped(data): # unpack scan step data position, output = data # unpack output as mean and error mean, err = output # update plot data self.x.append(position) self.y.append(mean) self.err.append(err) # update plot updatePlot() # ready for next step! scanToggle.completeStep() scanToggle.stepped.connect(onStepped) ############################################################# LOAD FUNCTIONS ########################################################### # set up reference data capabilities refLayout = QtGui.QHBoxLayout() def onLoadClicked(): date = datetime.datetime.now().strftime("%Y-%m-%d") time = datetime.datetime.now().strftime("%H%M") dir = os.path.join( POOHDATAPATH, date ) refFileName = QtGui.QFileDialog.getOpenFileName( widget, 'select file', dir, "CSV Files (*.csv)" ) refData = np.loadtxt(open(refFileName[0],"rb"),delimiter=",") name = refFileName[0].rpartition('/')[2] color = QtGui.QColorDialog.getColor() self.refData[name] = { 'color': color, 'data': [refData[:,0], refData[:,1], refData[:,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 ) ) # set up data saving capabilities saveLayout = QtGui.QVBoxLayout() ############################################################# SAVE FUNCTIONS ########################################################### def onSaveClicked(): dataArray = np.asarray( [self.x,self.y,self.err], dtype=np.dtype(np.float32) ) date = datetime.datetime.now().strftime("%Y-%m-%d") time = datetime.datetime.now().strftime("%H%M") dir = os.path.join( POOHDATAPATH, date ) if not os.path.exists(dir): os.makedirs(dir) path = QtGui.QFileDialog.getExistingDirectory( widget, 'select filename', dir ) if not path: return desc, valid = QtGui.QInputDialog.getText( widget, 'enter file description', 'description' ) filename = '%s_%s.csv' % (time,desc) if valid else '%s.csv' % time np.savetxt( os.path.join( path, filename ), dataArray.transpose(), delimiter=',' ) saveButton = QtGui.QPushButton('save') saveButton.clicked.connect(onSaveClicked) saveLayout.addWidget(SqueezeRow(saveButton)) cpLayout.addWidget( LabelWidget( 'save', saveLayout ) )
class RealtimePlotWidget(QWidget): AUTO_RANGE_FRACTION = 0.99 COLORS = [Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray] def __init__(self, display_measurements, parent): super(RealtimePlotWidget, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self._plot_widget = PlotWidget() self._plot_widget.setBackground((0, 0, 0)) self._legend = self._plot_widget.addLegend() self._plot_widget.showButtons() self._plot_widget.showGrid(x=True, y=True, alpha=0.3) vbox = QVBoxLayout(self) vbox.addWidget(self._plot_widget) self.setLayout(vbox) self._last_update_ts = 0 self._reset_required = False self._update_timer = QTimer(self) self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._update) self._update_timer.start(200) self._color_index = 0 self._curves = {} # Crosshair def _render_measurements(cur, ref): text = 'time %.6f sec, y %.6f' % cur if ref is None: return text dt = cur[0] - ref[0] dy = cur[1] - ref[1] if abs(dt) > 1e-12: freq = '%.6f' % abs(1 / dt) else: freq = 'inf' display_measurements(text + ';' + ' ' * 4 + 'dt %.6f sec, freq %s Hz, dy %.6f' % (dt, freq, dy)) display_measurements('Hover to sample Time/Y, click to set new reference') add_crosshair(self._plot_widget, _render_measurements) # Final reset self.reset() def _trigger_auto_reset_if_needed(self): ts = time.monotonic() dt = ts - self._last_update_ts self._last_update_ts = ts if dt > 2: self._reset_required = True def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]): color = QColor(self.COLORS[self._color_index % len(self.COLORS)]) self._color_index += 1 pen = mkPen(color, width=1) plot = self._plot_widget.plot(name=curve_name, pen=pen) data_x = numpy.array(data_x) data_y = numpy.array(data_y) self._curves[curve_id] = {'data': (data_x, data_y), 'plot': plot} self._trigger_auto_reset_if_needed() def update_values(self, curve_id, x, y): curve = self._curves[curve_id] old_x, old_y = curve['data'] curve['data'] = numpy.append(old_x, x), numpy.append(old_y, y) self._trigger_auto_reset_if_needed() def reset(self): for curve in self._curves.keys(): self._plot_widget.removeItem(self._curves[curve]['plot']) self._curves = {} self._color_index = 0 self._plot_widget.enableAutoRange(enable=self.AUTO_RANGE_FRACTION, x=self.AUTO_RANGE_FRACTION, y=self.AUTO_RANGE_FRACTION) self._legend.scene().removeItem(self._legend) self._legend = self._plot_widget.addLegend() def _update(self): if self._reset_required: self.reset() self._reset_required = False for curve in self._curves.values(): if len(curve['data'][0]): curve['plot'].setData(*curve['data'])
class CamViewer(Display): # Emitted when the user changes the value. roi_x_signal = Signal(str) roi_y_signal = Signal(str) roi_w_signal = Signal(str) roi_h_signal = Signal(str) def __init__(self, parent=None, args=None): super(CamViewer, self).__init__(parent=parent, args=args) # Set up the list of cameras, and all the PVs test_dict = { "image": "ca://MTEST:Image", "max_width": "ca://MTEST:ImageWidth", "max_height": "ca://MTEST:ImageWidth", "roi_x": None, "roi_y": None, "roi_width": None, "roi_height": None } # self.cameras = { "VCC": vcc_dict, "C-Iris": c_iris_dict, "Test": test_dict } self.cameras = {"Testing IOC Image": test_dict } self._channels = [] self.imageChannel = None # Populate the camera combo box self.ui.cameraComboBox.clear() for camera in self.cameras: self.ui.cameraComboBox.addItem(camera) # When the camera combo box changes, disconnect from PVs, re-initialize, then reconnect. self.ui.cameraComboBox.activated[str].connect(self.cameraChanged) # Set up the color map combo box. self.ui.colorMapComboBox.clear() for key, map_name in cmap_names.items(): self.ui.colorMapComboBox.addItem(map_name, userData=key) self.ui.imageView.colorMap = self.ui.colorMapComboBox.currentData() self.ui.colorMapComboBox.activated[str].connect(self.colorMapChanged) # Set up the color map limit sliders and line edits. # self._color_map_limit_sliders_need_config = True self.ui.colorMapMinSlider.valueChanged.connect(self.setColorMapMin) self.ui.colorMapMaxSlider.valueChanged.connect(self.setColorMapMax) self.ui.colorMapMinLineEdit.returnPressed.connect(self.colorMapMinLineEditChanged) self.ui.colorMapMaxLineEdit.returnPressed.connect(self.colorMapMaxLineEditChanged) # Set up the stuff for single-shot and average modes. self.ui.singleShotRadioButton.setChecked(True) self._average_mode_enabled = False self.ui.singleShotRadioButton.clicked.connect(self.enableSingleShotMode) self.ui.averageRadioButton.clicked.connect(self.enableAverageMode) self.ui.numShotsLineEdit.returnPressed.connect(self.numAverageChanged) # Add a plot for vertical lineouts self.yLineoutPlot = PlotWidget() self.yLineoutPlot.setMaximumWidth(80) self.yLineoutPlot.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) self.yLineoutPlot.getPlotItem().invertY() self.yLineoutPlot.hideAxis('bottom') # self.yLineoutPlot.setYLink(self.ui.imageView.getView()) self.ui.imageGridLayout.addWidget(self.yLineoutPlot, 0, 0) self.yLineoutPlot.hide() # We do some mangling of the .ui file here and move the imageView over a cell, kind of ugly. self.ui.imageGridLayout.removeWidget(self.ui.imageView) self.ui.imageGridLayout.addWidget(self.ui.imageView, 0, 1) # Add a plot for the horizontal lineouts self.xLineoutPlot = PlotWidget() self.xLineoutPlot.setMaximumHeight(80) self.xLineoutPlot.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self.xLineoutPlot.hideAxis('left') # self.xLineoutPlot.setXLink(self.ui.imageView.getView()) self.ui.imageGridLayout.addWidget(self.xLineoutPlot, 1, 1) self.xLineoutPlot.hide() # Update the lineout plot ranges when the image gets panned or zoomed self.ui.imageView.getView().sigRangeChanged.connect(self.updateLineoutRange) # Instantiate markers. self.marker_dict = {1:{}, 2:{}, 3:{}, 4:{}} marker_size = QPointF(20., 20.) self.marker_dict[1]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((100, 100, 255), width=5)) self.marker_dict[1]['button'] = self.ui.marker1Button self.marker_dict[1]['xlineedit'] = self.ui.marker1XPosLineEdit self.marker_dict[1]['ylineedit'] = self.ui.marker1YPosLineEdit self.marker_dict[2]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((255, 100, 100), width=5)) self.marker_dict[2]['button'] = self.ui.marker2Button self.marker_dict[2]['xlineedit'] = self.ui.marker2XPosLineEdit self.marker_dict[2]['ylineedit'] = self.ui.marker2YPosLineEdit self.marker_dict[3]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((60, 255, 60), width=5)) self.marker_dict[3]['button'] = self.ui.marker3Button self.marker_dict[3]['xlineedit'] = self.ui.marker3XPosLineEdit self.marker_dict[3]['ylineedit'] = self.ui.marker3YPosLineEdit self.marker_dict[4]['marker'] = ImageMarker((0, 0), size=marker_size, pen=mkPen((255, 60, 255), width=5)) self.marker_dict[4]['button'] = self.ui.marker4Button self.marker_dict[4]['xlineedit'] = self.ui.marker4XPosLineEdit self.marker_dict[4]['ylineedit'] = self.ui.marker4YPosLineEdit # Disable auto-ranging the image (it feels strange when the zoom changes as you move markers around.) self.ui.imageView.getView().disableAutoRange() for d in self.marker_dict: marker = self.marker_dict[d]['marker'] marker.setZValue(20) marker.hide() marker.sigRegionChanged.connect(self.markerMoved) self.ui.imageView.getView().addItem(marker) self.marker_dict[d]['button'].toggled.connect(self.enableMarker) curvepen = QPen(marker.pen) curvepen.setWidth(1) self.marker_dict[d]['xcurve'] = self.xLineoutPlot.plot(pen=curvepen) self.marker_dict[d]['ycurve'] = self.yLineoutPlot.plot(pen=curvepen) self.marker_dict[d]['xlineedit'].returnPressed.connect(self.markerPositionLineEditChanged) self.marker_dict[d]['ylineedit'].returnPressed.connect(self.markerPositionLineEditChanged) # Set up zoom buttons self.ui.zoomInButton.clicked.connect(self.zoomIn) self.ui.zoomOutButton.clicked.connect(self.zoomOut) self.ui.zoomToActualSizeButton.clicked.connect(self.zoomToActualSize) # Set up ROI buttons self.ui.setROIButton.clicked.connect(self.setROI) self.ui.resetROIButton.clicked.connect(self.resetROI) self.destroyed.connect(functools.partial(widget_destroyed, self.channels)) @Slot() def zoomIn(self): self.ui.imageView.getView().scaleBy((0.5, 0.5)) @Slot() def zoomOut(self): self.ui.imageView.getView().scaleBy((2.0, 2.0)) @Slot() def zoomToActualSize(self): if len(self.image_data) == 0: return self.ui.imageView.getView().setRange(xRange=(0, self.image_data.shape[0]), yRange=(0, self.image_data.shape[1]), padding=0.0) def disable_all_markers(self): for d in self.marker_dict: self.marker_dict[d]['button'].setChecked(False) self.marker_dict[d]['marker'].setPos((0, 0)) @Slot(bool) def enableMarker(self, checked): any_markers_visible = False for d in self.marker_dict: marker = self.marker_dict[d]['marker'] button = self.marker_dict[d]['button'] any_markers_visible = any_markers_visible or button.isChecked() marker.setVisible(button.isChecked()) self.markerMoved(d) self.marker_dict[d]['xcurve'].setVisible(button.isChecked()) self.marker_dict[d]['ycurve'].setVisible(button.isChecked()) self.marker_dict[d]['xlineedit'].setEnabled(button.isChecked()) self.marker_dict[d]['ylineedit'].setEnabled(button.isChecked()) if any_markers_visible: self.xLineoutPlot.show() self.yLineoutPlot.show() else: self.xLineoutPlot.hide() self.yLineoutPlot.hide() @Slot() def markerPositionLineEditChanged(self): for d in self.marker_dict: marker = self.marker_dict[d]['marker'] x_line_edit = self.marker_dict[d]['xlineedit'] y_line_edit = self.marker_dict[d]['ylineedit'] try: new_x = int(x_line_edit.text()) new_y = int(y_line_edit.text()) if new_x <= marker.maxBounds.width() and new_y <= marker.maxBounds.height(): marker.setPos((new_x, new_y)) except: pass coords = marker.getPixelCoords() x_line_edit.setText(str(coords[0])) y_line_edit.setText(str(coords[1])) @Slot(object) def markerMoved(self, marker): self.updateLineouts() for marker_index in self.marker_dict: marker = self.marker_dict[marker_index]['marker'] x_line_edit = self.marker_dict[marker_index]['xlineedit'] y_line_edit = self.marker_dict[marker_index]['ylineedit'] coords = marker.getPixelCoords() x_line_edit.setText(str(coords[0])) y_line_edit.setText(str(coords[1])) @Slot(object, object) def updateLineoutRange(self, view, new_ranges): self.ui.xLineoutPlot.setRange(xRange=new_ranges[0], padding=0.0) self.ui.yLineoutPlot.setRange(yRange=new_ranges[1], padding=0.0) def updateLineouts(self): for marker_index in self.marker_dict: marker = self.marker_dict[marker_index]['marker'] xcurve = self.marker_dict[marker_index]['xcurve'] ycurve = self.marker_dict[marker_index]['ycurve'] if marker.isVisible(): result, coords = marker.getArrayRegion(self.image_data, self.ui.imageView.getImageItem()) xcurve.setData(y=result[0], x=np.arange(len(result[0]))) ycurve.setData(y=np.arange(len(result[1])), x=result[1]) @Slot() def enableSingleShotMode(self): self._average_mode_enabled = False self._average_buffer = np.ndarray(0) @Slot() def enableAverageMode(self): self._average_mode_enabled = True @Slot(str) def cameraChanged(self, new_camera): new_camera = str(new_camera) if self.imageChannel == self.cameras[new_camera]["image"]: return close_widget_connections(self) self.disable_all_markers() self.initializeCamera(new_camera) def initializeCamera(self, new_camera): new_camera = str(new_camera) self._color_map_limit_sliders_need_config = True self.times = np.zeros(10) self.old_timestamp = 0 self.image_width = 0 # current width (width of ROI) self.image_max_width = 0 # full width. Only used to reset ROI to full. self.image_max_height = 0 # full height. Only used to reset ROI to full. self.image_data = np.zeros(0) self._average_counter = 0 self._average_buffer = np.ndarray(0) self._needs_auto_range = True self.imageChannel = self.cameras[new_camera]["image"] self.widthChannel = self.cameras[new_camera]["roi_width"] or self.cameras[new_camera]["max_width"] self.maxWidthChannel = self.cameras[new_camera]["max_width"] self.maxHeightChannel = self.cameras[new_camera]["max_height"] self.roiXChannel = self.cameras[new_camera]["roi_x"] self.roiYChannel = self.cameras[new_camera]["roi_y"] self.roiWidthChannel = self.cameras[new_camera]["roi_width"] self.roiHeightChannel = self.cameras[new_camera]["roi_height"] self._channels = [PyDMChannel(address=self.imageChannel, connection_slot=self.connectionStateChanged, value_slot=self.receiveImageWaveform, severity_slot=self.alarmSeverityChanged), PyDMChannel(address=self.widthChannel, value_slot=self.receiveImageWidth), PyDMChannel(address=self.maxWidthChannel, value_slot=self.receiveMaxWidth), PyDMChannel(address=self.maxHeightChannel, value_slot=self.receiveMaxHeight)] if self.roiXChannel and self.roiYChannel and self.roiWidthChannel and self.roiHeightChannel: self._channels.extend([PyDMChannel(address=self.roiXChannel, value_slot=self.receiveRoiX, value_signal=self.roi_x_signal, write_access_slot=self.roiWriteAccessChanged), PyDMChannel(address=self.roiYChannel, value_slot=self.receiveRoiY, value_signal=self.roi_y_signal), PyDMChannel(address=self.roiWidthChannel, value_slot=self.receiveRoiWidth, value_signal=self.roi_w_signal), PyDMChannel(address=self.roiHeightChannel, value_slot=self.receiveRoiHeight, value_signal=self.roi_h_signal)]) self.ui.roiXLineEdit.setEnabled(True) self.ui.roiYLineEdit.setEnabled(True) self.ui.roiWLineEdit.setEnabled(True) self.ui.roiHLineEdit.setEnabled(True) else: self.ui.roiXLineEdit.clear() self.ui.roiXLineEdit.setEnabled(False) self.ui.roiYLineEdit.clear() self.ui.roiYLineEdit.setEnabled(False) self.ui.roiWLineEdit.clear() self.ui.roiWLineEdit.setEnabled(False) self.ui.roiHLineEdit.clear() self.ui.roiHLineEdit.setEnabled(False) establish_widget_connections(self) @Slot() def setROI(self): self.roi_x_signal.emit(self.ui.roiXLineEdit.text()) self.roi_y_signal.emit(self.ui.roiYLineEdit.text()) self.roi_w_signal.emit(self.ui.roiWLineEdit.text()) self.roi_h_signal.emit(self.ui.roiHLineEdit.text()) @Slot() def resetROI(self): self.roi_x_signal.emit(str(0)) self.roi_y_signal.emit(str(0)) self.roi_w_signal.emit(str(self.image_max_width)) self.roi_h_signal.emit(str(self.image_max_height)) @Slot(str) def colorMapChanged(self, _): self.ui.imageView.colorMap = self.ui.colorMapComboBox.currentData() def configureColorMapLimitSliders(self, max_int): self.ui.colorMapMinSlider.setMaximum(max_int) self.ui.colorMapMaxSlider.setMaximum(max_int) self.ui.colorMapMaxSlider.setValue(max_int) self.ui.colorMapMinSlider.setValue(0) self.setColorMapMin(0) self.setColorMapMax(max_int) self._color_map_limit_sliders_need_config = False @Slot() def colorMapMinLineEditChanged(self): try: new_min = int(self.ui.colorMapMinLineEdit.text()) except: self.ui.colorMapMinLineEdit.setText(str(self.ui.colorMapMinSlider.value())) return if new_min < 0: new_min = 0 if new_min > self.ui.colorMapMinSlider.maximum(): new_min = self.ui.colorMapMinSlider.maximum() self.ui.colorMapMinSlider.setValue(new_min) @Slot(int) def setColorMapMin(self, new_min): if new_min > self.ui.colorMapMaxSlider.value(): self.ui.colorMapMaxSlider.setValue(new_min) self.ui.colorMapMaxLineEdit.setText(str(new_min)) self.ui.colorMapMinLineEdit.setText(str(new_min)) self.ui.imageView.setColorMapLimits(new_min, self.ui.colorMapMaxSlider.value()) @Slot() def colorMapMaxLineEditChanged(self): try: new_max = int(self.ui.colorMapMaxLineEdit.text()) except: self.ui.colorMapMaxLineEdit.setText(str(self.ui.colorMapMaxSlider.value())) return if new_max < 0: new_max = 0 if new_max > self.ui.colorMapMaxSlider.maximum(): new_max = self.ui.colorMapMaxSlider.maximum() self.ui.colorMapMaxSlider.setValue(new_max) @Slot(int) def setColorMapMax(self, new_max): if new_max < self.ui.colorMapMinSlider.value(): self.ui.colorMapMinSlider.setValue(new_max) self.ui.colorMapMinLineEdit.setText(str(new_max)) self.ui.colorMapMaxLineEdit.setText(str(new_max)) self.ui.imageView.setColorMapLimits(self.ui.colorMapMinSlider.value(), new_max) def createAverageBuffer(self, size, type, initial_val=[]): num_shots = 1 try: num_shots = int(self.ui.numShotsLineEdit.text()) except: self.ui.numShotsLineEdit.setText(str(num_shots)) if num_shots < 1: num_shots = 1 self.ui.numShotsLineEdit.setText(str(num_shots)) if num_shots > 200: num_shots = 200 self.ui.numShotsLineEdit.setText(str(num_shots)) if len(initial_val) > 0: return np.full((num_shots, size), initial_val, dtype=type) else: return np.zeros(shape=(num_shots, size), dtype=type) @Slot() def numAverageChanged(self): self._average_buffer = np.zeros(0) @Slot(np.ndarray) def receiveImageWaveform(self, new_waveform): if not self.image_width: return # Calculate the average rate new_timestamp = time.time() if not (self.old_timestamp == 0): delta = new_timestamp - self.old_timestamp self.times = np.roll(self.times, 1) self.times[0] = delta avg_delta = np.mean(self.times) self.ui.dataRateLabel.setText("{:.1f} Hz".format((1.0 / avg_delta))) self.ui.displayRateLabel.setText("{:.1f} Hz".format((1.0 / avg_delta))) self.old_timestamp = new_timestamp # If this is the first image, set up the color map slider limits if self._color_map_limit_sliders_need_config: max_int = np.iinfo(new_waveform.dtype).max self.configureColorMapLimitSliders(max_int) # If we are in average mode, add this image to the circular averaging buffer, otherwise just display it. if self._average_mode_enabled: if len(self._average_buffer) == 0: self._average_buffer = self.createAverageBuffer(len(new_waveform), new_waveform.dtype, new_waveform) self._average_counter = 0 self._average_counter = (self._average_counter + 1) % len(self._average_buffer) # self._average_buffer = np.roll(self._average_buffer, 1, axis=0) self._average_buffer[self._average_counter] = new_waveform mean = np.mean(self._average_buffer, axis=0).astype(new_waveform.dtype) self.image_data = mean.reshape((int(self.image_width), -1), order='F') else: self.image_data = new_waveform.reshape((int(self.image_width), -1), order='F') self.setMarkerBounds() self.updateLineouts() self.ui.imageView.image_value_changed(self.image_data) self.calculateStats() if self._needs_auto_range: self.ui.imageView.getView().autoRange(padding=0.0) current_range = self.ui.imageView.getView().viewRange() self._needs_auto_range = False def calculateStats(self): # Full image stats mean = np.mean(self.image_data) std = np.std(self.image_data) width = self.image_data.shape[0] height = self.image_data.shape[1] min_val = np.min(self.image_data) max_val = np.max(self.image_data) self.ui.imageStatsLabel.setText("Mean: {0:.2f}, Std: {1:.2f}, Min: {2}, Max: {3}, Width: {4}, Height: {5}".format(mean, std, min_val, max_val, width, height)) # Current view stats current_range = self.ui.imageView.getView().viewRange() view_x_min = int(max(0, current_range[0][0])) view_x_max = int(min(self.image_data.shape[0], current_range[0][1])) view_y_min = int(max(0, current_range[1][0])) view_y_max = int(min(self.image_data.shape[1], current_range[1][1])) view_slice = self.image_data[view_x_min:view_x_max, view_y_min:view_y_max] mean = np.mean(view_slice) std = np.std(view_slice) width = view_slice.shape[0] height = view_slice.shape[1] min_val = np.min(view_slice) max_val = np.max(view_slice) self.ui.viewStatsLabel.setText("Mean: {0:.2f}, Std: {1:.2f}, Min: {2}, Max: {3}, Width: {4}, Height: {5}".format(mean, std, min_val, max_val, width, height)) def setMarkerBounds(self): for marker_index in self.marker_dict: marker = self.marker_dict[marker_index]['marker'] marker.maxBounds = QRectF(0, 0, self.image_data.shape[0] + marker.size()[0] - 1, self.image_data.shape[1] + marker.size()[1] - 1) @Slot(int) def receiveImageWidth(self, new_width): self.image_width = new_width self.ui.imageView.image_width_changed(self.image_width) @Slot(int) def receiveMaxWidth(self, new_max_width): self.image_max_width = new_max_width @Slot(int) def receiveMaxHeight(self, new_max_height): self.image_max_height = new_max_height @Slot(int) def receiveRoiX(self, new_roi_x): self.ui.roiXLineEdit.setText(str(new_roi_x)) @Slot(int) def receiveRoiY(self, new_roi_y): self.ui.roiYLineEdit.setText(str(new_roi_y)) @Slot(int) def receiveRoiWidth(self, new_roi_w): self.ui.roiWLineEdit.setText(str(new_roi_w)) @Slot(int) def receiveRoiHeight(self, new_roi_h): self.ui.roiHLineEdit.setText(str(new_roi_h)) # -2 to +2, -2 is LOLO, -1 is LOW, 0 is OK, etc. @Slot(int) def alarmStatusChanged(self, new_alarm_state): pass # 0 = NO_ALARM, 1 = MINOR, 2 = MAJOR, 3 = INVALID @Slot(int) def alarmSeverityChanged(self, new_alarm_severity): pass @Slot(bool) def roiWriteAccessChanged(self, can_write_roi): self.ui.setROIButton.setEnabled(can_write_roi) self.ui.resetROIButton.setEnabled(can_write_roi) self.ui.roiXLineEdit.setReadOnly(not can_write_roi) self.ui.roiYLineEdit.setReadOnly(not can_write_roi) self.ui.roiWLineEdit.setReadOnly(not can_write_roi) self.ui.roiHLineEdit.setReadOnly(not can_write_roi) # false = disconnected, true = connected @Slot(bool) def connectionStateChanged(self, connected): if connected: self.ui.imageView.redraw_timer.start() else: self.ui.imageView.redraw_timer.stop() self.ui.connectedLabel.setText({True: "Yes", False: "No"}[connected]) def ui_filename(self): return 'camviewer.ui' def channels(self): return self._channels
def SmartScanGUI(): # oh god i'm so sorry class self: x,y,err = [], [], [] #configure a layout for the plot widget & controls to go side by side on widget = QtGui.QWidget() container.append(widget) widget.show() layout = QtGui.QHBoxLayout() widget.setLayout(layout) # create a plot and associated widget plotWidget = PlotWidget() plot = plotWidget.plot() layout.addWidget(plotWidget,1) # configure a control panel layout cpLayout = QtGui.QVBoxLayout() layout.addLayout(cpLayout) # configure the output widget outputWidget = ComboWidget() cpLayout.addWidget(LabelWidget('output',outputWidget)) # add volt meter to scan output vmProtocol = yield getProtocol( (VM_DEBUG_SERVER_CONFIG if DEBUG else VM_SERVER_CONFIG)['url'] ) vmClient = VoltMeterClient(vmProtocol) vmWidget = VoltMeterOutputWidget(vmClient) outputWidget.addTab(vmWidget,'voltmeter') # configure the input widget inputWidget = ComboWidget() inputWidget.setTabPosition(inputWidget.West) cpLayout.addWidget(LabelWidget('input',inputWidget),1) inputWidget.addTab( ManualInputWidget(widget), 'manual' ) inputWidget.addTab( ManualScanInputWidget(widget), 'manual scan' ) # 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) if INPUTS_TOGGLE[SM_BOOL]: # add stepper motors to scan input smProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) smClients = { smID:ChunkedStepperMotorClient(smProtocol,smID) for smID in (KDP,BBO,PDL) } for smID,smClient in smClients.items(): combo_input_widget = ComboWidget() combo_input_widget.addTab( CenterInputWidget( smClient.setPosition, smClient.cancel, -99999, 99999, 0, 0, 0, 1000, 0, 10, smClient.getPosition ), 'interval' ) combo_input_widget.addTab( ListInputWidget( smClient.setPosition, smClient.cancel ), 'list' ) inputWidget.addTab( combo_input_widget, { KDP:'kdp', BBO:'bbo', PDL:'pdl' }[smID] ) if INPUTS_TOGGLE[WL_BOOL]: # add wavelength client to scan input wlProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) wlClient = WavelengthClient(wlProtocol) wlInputWidget = ComboWidget() wlInputWidget.addTab( CenterInputWidget( wlClient.setWavelength, wlClient.cancelWavelengthSet, 24100.0, 25000.0, 2, 24200.0, 0.01, 100.0, 2, .2, wlClient.getWavelength ), 'interval' ) wlInputWidget.addTab( ListInputWidget( wlClient.setWavelength, wlClient.cancelWavelengthSet ), 'list' ) inputWidget.addTab( wlInputWidget, 'surf' ) if INPUTS_TOGGLE[DDG_BOOL]: # add delay generator to scan input dgProtocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER ) dgClient = DelayGeneratorClient(dgProtocol) delays = yield dgClient.getDelays() for dgID in delays.keys(): def setter(dgID): @inlineCallbacks def _setter(delay): yield dgClient.setPartnerDelay(dgID,delay) returnValue(delay) return _setter def getter(dgID): @inlineCallbacks def _getter(): delays = yield dgClient.getDelays() returnValue(delays[dgID]) return _getter def cancel(dgID): def _cancel(): pass return _cancel dgCombo = ComboWidget() dgCombo.addTab( CenterInputWidget( setter(dgID), cancel(dgID), 1, 50000000, 0, 3896550.0, 0, 1000000, 1, 100, getter(dgID) ), 'interval' ) dgCombo.addTab( ListInputWidget( setter(dgID), cancel(dgID) ), 'list' ) inputWidget.addTab( dgCombo, dgID ) #create a scan toggle scanToggle = SmartScanToggleObject() cpLayout.addWidget( LabelWidget( 'scan',ToggleWidget(scanToggle) ) ) def onActivationRequested(): # empty data for l in (self.x,self.y,self.err): while l: l.pop() # get current selected scan output, scan input scanOutput = outputWidget.getOutput() scanInput = inputWidget.getInput() scanToggle.setOutput(scanOutput.next) scanToggle.setInput(scanInput.next) # on stop request, send cancel signal to scan input and output def cancel(): scanInput.cancel() scanOutput.cancel() scanToggle.setCancel(cancel) # start scan scanToggle.toggle() scanToggle.activationRequested.connect(onActivationRequested) # plot on step completion def onStepped(data): # unpack scan step data position, output = data # unpack output as mean and error mean, err = output # update plot data self.x.append(position) self.y.append(mean) self.err.append(err) # update plot plotWidget.clear() plotWidget.plot(self.x,self.y) plotWidget.addItem( ErrorBarItem( x=np.asarray(self.x), y=np.asarray(self.y), top=np.asarray(self.err), bottom=np.asarray(self.err), beam=.05 ) ) # ready for next step! scanToggle.completeStep() scanToggle.stepped.connect(onStepped) # set up data saving capabilities (ask bobby re: this) saveLayout = QtGui.QVBoxLayout() def onSaveClicked(): dataArray = np.asarray( [self.x,self.y,self.err], dtype=np.dtype(np.float32) ) date = datetime.datetime.now().strftime("%Y-%m-%d") time = datetime.datetime.now().strftime("%H%M") dir = os.path.join( POOHDATAPATH, date ) if not os.path.exists(dir): os.makedirs(dir) path = QtGui.QFileDialog.getExistingDirectory( widget, 'select filename', dir ) if not path: return desc, valid = QtGui.QInputDialog.getText( widget, 'enter file description', 'description' ) filename = '%s_%s.csv' % (time,desc) if valid else '%s.csv' % time np.savetxt( os.path.join( path, filename ), dataArray.transpose(), delimiter=',' ) saveCSVButton = QtGui.QPushButton('save (csv)') saveCSVButton.clicked.connect(onSaveClicked) saveLayout.addWidget(SqueezeRow(saveCSVButton)) cpLayout.addWidget( LabelWidget( 'save', saveLayout ) )
def init_widget(self): layout = QtGui.QHBoxLayout() self.setLayout(layout) plot_layout = QtGui.QHBoxLayout() layout.addLayout(plot_layout) plots = {} traces = {} for plot in PLOTS: plot_dict = PLOTS_DICT[plot] plot_widget = PlotWidget( title=plot_dict[TITLE], labels={ 'bottom':'time (samples)', 'left':plot_dict[LABEL] } ) plot_traces = plot_dict[TRACES] if len(plot_traces) > 1: plot_widget.addLegend() trace_index = 0 colors = ('F33','3F3','33F') for trace_key, trace_d in plot_traces.items(): trace = [0] * HISTORY kwargs = { LINE:{ 'pen':{'color':colors[trace_index]} }, SCATTER:{ 'pen':None, 'symbol':'o', 'symbolSize':3, 'symbolBrush':colors[trace_index] } }[trace_d[TRACE_TYPE]] kwargs['name'] = trace_d[TRACE_NAME] plot = plot_widget.plot( trace, **kwargs ) plots[trace_key] = plot traces[trace_key] = trace trace_index += 1 plot_layout.addWidget(plot_widget) client = yield connectAsync() sh_server = client.sample_heater controls_layout = QtGui.QVBoxLayout() layout.addLayout(controls_layout) temperature_setpoint_layout = QtGui.QHBoxLayout() controls_layout.addWidget( LabelWidget( 'temperature setpoint', temperature_setpoint_layout ) ) temperature_setpoint_label = QtGui.QLabel() temperature_setpoint_layout.addWidget(temperature_setpoint_label) temperature_setpoint_layout.addStretch() temperature_setpoint_spin = QtGui.QSpinBox() temperature_setpoint_spin.setRange(MIN_TEMPERATURE,MAX_TEMPERATURE) temperature_setpoint_spin.setPrefix('temp') temperature_setpoint_spin.setSuffix('C') temperature_setpoint_layout.addWidget(temperature_setpoint_spin) temperature_setpoint_button = QtGui.QPushButton('set') temperature_setpoint_layout.addWidget(temperature_setpoint_button) def set_temperature_setpoint(): catch_labrad_error( self, sh_server.set_temperature_setpoint(temperature_setpoint_spin.value()) ) temperature_setpoint_button.clicked.connect(set_temperature_setpoint) def update_temperature_setpoint(temperature_setpoint): self.temperature_setpoint = temperature_setpoint temperature_setpoint_label.setText('temp setpoint: %d' % self.temperature_setpoint) sh_server.on_temperature_setpoint_changed.connect( lambda c, temperature_setpoint: update_temperature_setpoint(temperature_setpoint) ) temperature_setpoint = yield sh_server.get_temperature_setpoint() update_temperature_setpoint(temperature_setpoint) def update_label(label,state): label.setText('status: ' + str(state)) for name, signal, getter, setter, option_1, option_2 in ( ( 'heating state', sh_server.on_heating_state_changed, sh_server.get_heating_state, sh_server.set_heating_state, 'heating', 'cooling' ), ( 'feedback state', sh_server.on_feedback_state_changed, sh_server.get_feedback_state, sh_server.set_feedback_state, True, False ), ( 'temperature limit state', sh_server.on_temperature_limit_state_changed, sh_server.get_temperature_limit_state, None, None, None ), ( 'emission current limit state', sh_server.on_emission_current_limit_state_changed, sh_server.get_emission_current_limit_state, None, None, None ), ( 'thermocouple state', sh_server.on_thermocouple_state_changed, sh_server.get_thermocouple_state, None, None, None ), ): layout = QtGui.QHBoxLayout() controls_layout.addWidget( LabelWidget( name, layout ) ) label = QtGui.QLabel() layout.addWidget(label) layout.addStretch() state = yield getter() update_label(label,state) def get_slot(label): def slot(c,state): update_label(label,state) return slot signal.connect(get_slot(label)) if setter is None: continue def cb(setter,option): catch_labrad_error( self, setter(option) ) for option in (option_1,option_2): button = QtGui.QPushButton(str(option)) layout.addWidget(button) button.clicked.connect(partial(cb,setter,option)) for lockable_setting in ( sh_server.set_feedback_state, sh_server.set_heating_state, sh_server.set_temperature_setpoint ): controls_layout.addWidget(LockWidget(sh_server,lockable_setting.ID,lockable_setting.name)) def update_plot(plot,sample): t = traces[plot] t.insert(0,sample) t.pop() plots[plot].setData(t) @inlineCallbacks def loop(): packet = sh_server.packet() packet.get_filament_control() packet.get_emission_current() packet.get_temperature() packet.get_rate() packet.get_rate_setpoint() result = yield packet.send() filament_control = result.get_filament_control update_plot(FILAMENT_TRACE,filament_control) temperature = result.get_temperature update_plot(TEMPERATURE_TRACE,temperature) emission_current = result.get_emission_current update_plot(EMISSION_TRACE,emission_current) rate = result.get_rate update_plot(RATE_TRACE,rate) rate_setpoint = result.get_rate_setpoint update_plot(RATE_SETPOINT_TRACE,rate_setpoint) temperature_setpoint = self.temperature_setpoint update_plot(TEMPERATURE_SETPOINT_TRACE,temperature_setpoint) rate_average = np.average(traces[RATE_TRACE][:RUNNING_AVERAGE]) update_plot(RATE_AVERAGE,rate_average) loop() loop()
class 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 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 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)