Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #4
0
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)
Beispiel #5
0
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)
Beispiel #7
0
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()
Beispiel #8
0
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."))
Beispiel #9
0
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()
Beispiel #10
0
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
Beispiel #11
0
    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)
Beispiel #12
0
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)
Beispiel #13
0
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())])
Beispiel #17
0
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.
Beispiel #18
0
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()
Beispiel #19
0
    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)
Beispiel #20
0
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
Beispiel #21
0
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))
Beispiel #22
0
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()
Beispiel #23
0
        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)
Beispiel #24
0
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()
Beispiel #25
0
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()
Beispiel #26
0
 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
Beispiel #27
0
    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)
Beispiel #28
0
 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)
Beispiel #29
0
    def _plot_prediction(self, historical_dfs: list[pd.DataFrame],
                         model: RandomForest, prediction: ndarray,
                         target_date: datetime.date) -> None:
        """Opens a window with a plot of the historical target data as well as the prediction
        the model made."""
        hdf = historical_dfs[0]
        for frame in historical_dfs[1:]:
            hdf = hdf.combine_first(frame)
        window_end = target_date - \
            pd.DateOffset(days=model.window.target_shift)
        window_start = window_end - pd.DateOffset(days=30 - 1)
        hdf = pd.Series(
            hdf.loc[window_end:window_start][model.window.target_lbl])

        hdf_data = hdf.to_list()
        hdf_dates = hdf.index

        hdf_dates = [ts.to_pydatetime().timestamp() for ts in hdf_dates]

        b_axis = pg.DateAxisItem(orientation='bottom')
        b_axis.setLabel('Date')
        plot = PlotWidget(axisItems={'bottom': b_axis})

        target_time = datetime.combine(target_date, datetime.min.time())

        plot.addLegend()
        plot.plot(x=hdf_dates,
                  y=hdf_data,
                  name=f'Historical {model.window.target_lbl}')
        plot.plot(x=[target_time.timestamp()],
                  y=prediction,
                  pen=None,
                  symbol='o',
                  name=f'Predicted Value: {prediction[0]}')
        model_name = self._model.currentText()
        self._plot_window.setWindowTitle(f'{model_name} Prediction')
        self._plot_window.setCentralWidget(plot)
        self._plot_window.show()
Beispiel #30
0
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"))
Beispiel #31
0
    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()
Beispiel #32
0
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)
Beispiel #33
0
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)
Beispiel #34
0
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"))
Beispiel #35
0
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()
Beispiel #37
0
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 __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)
Beispiel #39
0
    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())
Beispiel #40
0
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
Beispiel #42
0
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_()
Beispiel #43
0
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
        )
    )
Beispiel #44
0
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'])
Beispiel #45
0
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
Beispiel #46
0
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
        )
    )    
Beispiel #47
0
    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()
Beispiel #48
0
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()
Beispiel #50
0
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)