Example #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)
Example #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'")
Example #3
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()
Example #4
0
    def clear_graphics(graphics_view: PlotWidget):
        """
        static method for clearing content in all graphics

        Parameters
        ----------
        graphics_view   : PlotWidget
                          graphics view to place chart

        """
        Assertor.assert_data_types([graphics_view], [PlotWidget])
        graphics_view.clear()
Example #5
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()
Example #6
0
    def clear_graphics(graphics_view: PlotWidget, table_view: QTableView):
        """
        static method for clearing content in all graphics

        Parameters
        ----------
        graphics_view   : PlotWidget
                          graphics view to place chart
        table_view      : QTableView
                          table view to link graphics_view

        """
        Assertor.assert_data_types([graphics_view, table_view],
                                   [PlotWidget, QTableView])
        table_view.setModel(None)
        table_view.clearSpans()
        graphics_view.clear()
Example #7
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
Example #8
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))
Example #9
0
class VNAWidget(QWidget):
    settings = None
    def __init__(self):
        super(VNAWidget, self).__init__()
        self.setWindowTitle("VNA Window")
        layout = QVBoxLayout(self)

        self.plot_layout = QHBoxLayout()
        layout.addLayout(self.plot_layout)
        self.mag_plot = PlotWidget()
        self.mag_plot.addLegend()
        self.plot_layout.addWidget(self.mag_plot)

        self.message_box = QPlainTextEdit()
        layout.addWidget(self.message_box)

        self.form_layout = QFormLayout()
        layout.addLayout(self.form_layout)

        self.dataset_edit = QLineEdit("TestSample")
        save_file_button = QPushButton("HDF5 File")
        self.save_file_edit = QLineEdit("C:\\_Data\\test.h5")
        # self.form_layout.addRow("VNA Address", self.address_combo_box)
        self.form_layout.addRow(save_file_button, self.save_file_edit)
        dataset_button = QPushButton("Dataset")
        self.form_layout.addRow(dataset_button, self.dataset_edit)

        self.button_layout = QHBoxLayout()
        layout.addLayout(self.button_layout)
        grab_trace_button = QPushButton("Grab Trace")
        save_button = QPushButton("Save")
        self.button_layout.addWidget(grab_trace_button)
        self.button_layout.addWidget(save_button)

        self.freqs = None
        self.mags = None
        self.phases = None
        self.vna = None
        self.current_vna_addr = None
        self.vna_params = None

        save_file_button.clicked.connect(self.change_save_file)
        dataset_button.clicked.connect(self.change_dataset)
        grab_trace_button.clicked.connect(self.grab_trace)
        save_button.clicked.connect(self.save_trace)

    def get_vna(self):
        return instruments['VNA']

    def grab_trace(self):
        vna = self.get_vna()
        self.freqs = vna.do_get_xaxis()
        self.mags, self.phases = vna.do_get_data()
        self.replot()
        self.vna_params =  vna.get_parameter_values(query=True)
        self.message("VNA Params")
        self.message("----------")
        for k, v in self.vna_params.items():
            self.message(k, ":", v)
        self.message("")

    def replot(self):
        self.mag_plot.clear()
        self.mag_plot.plotItem.legend.setParent(None)
        self.mag_plot.addLegend()
        if self.freqs is None:
            return
        self.mag_plot.plot(self.freqs, self.mags, pen='g', name='Data')

    def message(self, *objs):
        self.message_box.appendPlainText(" ".join([str(o) for o in objs]))

    def change_save_file(self):
        filename = QFileDialog.getSaveFileName(
            self, "Save File", self.save_file_edit.text(),
            "HDF5 files (*.h5 *.hdf5)", options=QFileDialog.DontConfirmOverwrite
        )
        self.save_file_edit.setText(filename)

    def change_dataset(self):
        dialog = QDialog()
        layout = QVBoxLayout(dialog)
        model = H5File(h5py.File(str(self.save_file_edit.text())))
        tree_view = H5View()
        tree_view.setModel(model)
        tree_view.setSelectionMode(QAbstractItemView.SingleSelection)
        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(dialog.accept)
        button_box.rejected.connect(dialog.reject)
        layout.addWidget(tree_view)
        layout.addWidget(button_box)
        if dialog.exec_():
            #self.dataset_edit.setText(tree_view.selected_path()[1:])
            dsname = model.itemFromIndex(tree_view.selectedIndexes()[0]).fullname[1:]
            self.dataset_edit.setText(dsname)


    def get_h5group(self):
        filename = str(self.save_file_edit.text())
        h5file = datasrv.get_file(filename)
        path = str(self.dataset_edit.text())
        return h5helpers.resolve_path(h5file, path)

    def save_trace_csv(self):
        default_name = time.strftime("trace_%Y%m%d_%H%M%S.dat")
        save_path = str(self.save_path_edit.text())
        default_filename = os.path.join(save_path, default_name)
        filename = str(QFileDialog.getSaveFileName(self, "Save Trace", default_filename))
        data = numpy.array([self.freqs, self.mags, self.phases]).transpose()
        numpy.savetxt(filename, data)

    def save_trace(self):
        group = self.get_h5group()
        if 'freqs' in group:
            reply = QMessageBox.question(self, "", "Dataset exists in file, Overwrite?", QMessageBox.Yes | QMessageBox.No)
            if reply == QMessageBox.No:
                return

        group['freqs'] = self.freqs
        group['mags'] = self.mags
        group['phases'] = self.phases
        h5helpers.set_scale(group, 'freqs', 'mags')
        h5helpers.set_scale(group, 'freqs', 'phases')
        h5helpers.update_attrs(group, self.vna_params)
        self.message("Saved in file %s" % group.get_fullname())
Example #10
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)
class Ui_Dialog(object):
    def __init__(self) :
        self.c = 1
        self.dx = 0.1
        self.n = 1
    
    def setupUi(self, Dialog):
        Dialog.setObjectName("Equation de transport")
        Dialog.resize(996, 388)
        Dialog.setWindowIcon(QtGui.QIcon(r'D:\Cours\Aero2\GP\Transport\Numerix.jpg'))
        Dialog.setFixedSize(996,388)
        font = QtGui.QFont()
        font.setFamily("CMU Bright")
        font.setPointSize(10)
        Dialog.setFont(font)
        self.frame = QtWidgets.QFrame(Dialog)
        self.frame.setGeometry(QtCore.QRect(20, 10, 361, 81))
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.label = QtWidgets.QLabel(self.frame)
        self.label.setGeometry(QtCore.QRect(10, 10, 181, 16))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.frame)
        self.label_2.setGeometry(QtCore.QRect(200, 10, 161, 16))
        self.label_2.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.label_2.setMouseTracking(False)
        self.label_2.setObjectName("label_2")
        self.L = QtWidgets.QLineEdit(self.frame)
        self.L.setGeometry(QtCore.QRect(10, 40, 113, 22))
        self.L.setObjectName("L")
        self.tmax = QtWidgets.QLineEdit(self.frame)
        self.tmax.setGeometry(QtCore.QRect(200, 40, 113, 22))
        self.tmax.setObjectName("tmax")
        self.frame_2 = QtWidgets.QFrame(Dialog)
        self.frame_2.setGeometry(QtCore.QRect(20, 110, 361, 221))
        font = QtGui.QFont()
        font.setFamily("CMU Serif")
        font.setPointSize(10)
        self.frame_2.setFont(font)
        self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.label_3 = QtWidgets.QLabel(self.frame_2)
        self.label_3.setGeometry(QtCore.QRect(10, 10, 171, 16))
        self.label_3.setObjectName("label_3")
        self.CI = QtWidgets.QComboBox(self.frame_2)
        self.CI.setGeometry(QtCore.QRect(10, 50, 91, 22))
        font = QtGui.QFont()
        font.setFamily("CMU Serif")
        font.setPointSize(10)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.CI.setFont(font)
        self.CI.setStyleSheet("")
        self.CI.setObjectName("CI")
        self.CI.addItem("sin(x)")
        self.CI.addItem("exp(-x^2)")
        self.CI.addItem("0")
        self.label_4 = QtWidgets.QLabel(self.frame_2)
        self.label_4.setGeometry(QtCore.QRect(180, 10, 201, 16))
        self.label_4.setObjectName("label_4")
        self.frame_3 = QtWidgets.QFrame(self.frame_2)
        self.frame_3.setGeometry(QtCore.QRect(170, 0, 191, 181))
        self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_3.setObjectName("frame_3")
        self.label_5 = QtWidgets.QLabel(self.frame_3)
        self.label_5.setGeometry(QtCore.QRect(20, 40, 71, 16))
        self.label_5.setObjectName("label_5")
        self.Cl_0 = QtWidgets.QComboBox(self.frame_3)
        self.Cl_0.setGeometry(QtCore.QRect(20, 70, 90, 22))
        self.Cl_0.setObjectName("Cl_0")
        self.Cl_0.addItem("0")
        self.Cl_0.addItem("sin(t)")
        self.label_6 = QtWidgets.QLabel(self.frame_3)
        self.label_6.setGeometry(QtCore.QRect(20, 110, 71, 16))
        self.label_6.setObjectName("label_6")
        self.Cl_L = QtWidgets.QComboBox(self.frame_3)
        self.Cl_L.setGeometry(QtCore.QRect(20, 140, 90, 22))
        self.Cl_L.setObjectName("Cl_L")
        self.Cl_L.addItem("0")
        self.Cl_L.addItem("sin(t)")
        self.Cl_L.addItem("Aucune")
        self.label_7 = QtWidgets.QLabel(self.frame_2)
        self.label_7.setGeometry(QtCore.QRect(10, 100, 151, 16))
        self.label_7.setObjectName("label_7")
        self.Vitesse = QtWidgets.QLineEdit(self.frame_2)
        self.Vitesse.setGeometry(QtCore.QRect(10, 140, 113, 22))
        self.Vitesse.setObjectName("Vitesse")
        self.Animation = QtWidgets.QCheckBox(Dialog)
        self.Animation.setGeometry(QtCore.QRect(30, 340, 101, 20))
        self.Animation.setObjectName("Animation")
        self.Plot_btn = QtWidgets.QPushButton(Dialog)
        self.Plot_btn.setGeometry(QtCore.QRect(220, 340, 93, 28))
        self.Plot_btn.setObjectName("Plot_btn")
        self.Graph = PlotWidget(Dialog)
        self.Graph.setGeometry(QtCore.QRect(389, 9, 591, 361))
        self.Graph.setObjectName("Graph")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
        Dialog.setTabOrder(self.CI, self.Vitesse)
        Dialog.setTabOrder(self.Vitesse,self.Cl_0)
        Dialog.setTabOrder(self.Cl_0, self.Cl_L)
        Dialog.setTabOrder(self.Cl_L, self.Animation)
        Dialog.setTabOrder(self.Animation, self.Plot_btn)
        
        setConfigOptions(antialias=True)
        
        self.Plot_btn.clicked.connect(self.plotter)
        self.Graph.setBackground('w')
        self.Graph.setLabel('left','y(x,tmax)')
        self.Graph.setLabel('bottom','x')
        
        
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.animplotter)
    
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Equation de transport"))
        self.label.setText(_translate("Dialog", "Longueur de l\'espace :"))
        self.label_2.setText(_translate("Dialog", "Temps maximum :"))
        self.label_3.setText(_translate("Dialog", "Conditions initiales :"))
        self.CI.setItemText(0, _translate("Dialog", "sin(x)"))
        self.CI.setItemText(1, _translate("Dialog", "exp(-x^2)"))
        self.CI.setItemText(2, _translate("Dialog", "0"))
        self.label_4.setText(_translate("Dialog", "Conditions aux limites :"))
        self.label_5.setText(_translate("Dialog", "En x = 0 :"))
        self.Cl_0.setItemText(0, _translate("Dialog", "0"))
        self.Cl_0.setItemText(1, _translate("Dialog", "sin(t)"))
        self.label_6.setText(_translate("Dialog", "En x = L :"))
        self.Cl_L.setItemText(0, _translate("Dialog", "0"))
        self.Cl_L.setItemText(1, _translate("Dialog", "sin(t)"))
        self.Animation.setText(_translate("Dialog", "Animation"))
        self.Plot_btn.setText(_translate("Dialog", "Plot !"))
        self.label_6.setText(_translate("Dialog", "En x = L :"))
        self.Cl_L.setItemText(0, _translate("Dialog", "0"))
        self.Cl_L.setItemText(1, _translate("Dialog", "sin(t)"))
        self.Cl_L.setItemText(2, _translate("Dialog", "Aucune"))
        self.Animation.setText(_translate("Dialog", "Animation"))
        self.Plot_btn.setText(_translate("Dialog", "Plot !"))
        self.label_7.setText(_translate("Dialog", "Vitesse de l\'onde :"))
    
    def solve(self) :
        
        self.C = self.c*self.dt/self.dx
        self.Fi = init = self.Finit()
        self.sol = []
        self.solutions = [0 for t in self.T]
        
        for t in range(len(self.T)) :
            for x in range(len(self.Fi)) :
                self.sol.append(
                    init[x] - self.C*(init[x] - init[x-1])
                    )
            
            if self.Cl_0.currentText() == 'sin(t)' :
                self.sol[0] = np.sin(self.T[t]*self.c)
            elif self.Cl_0.currentText() == '0' :
                self.sol[0] = 0
            
            if self.Cl_L.currentText() == 'sin(t)' :
                self.sol[-1] = np.sin(self.T[t])
            elif self.Cl_L.currentText() == '0' :
                self.sol[-1] = 0
            
            init = self.sol
            self.sol = []
            self.solutions[t] = init
            
        self.sol = init
        return self.sol
    
    def plotter(self) :
        
        self.c = float(self.Vitesse.text())
        self.tmaxv = float(self.tmax.text())
        self.dt = self.dx/self.c
        
        self.Graph.clear()
        
        self.X = np.arange(0,float(self.L.text()),self.dx).tolist()
        self.T = np.arange(0,self.tmaxv,self.dt).tolist()
        
        Solution = self.solve()
        self.Graph.setXRange(0,float(self.L.text()))
        self.Graph.setYRange(min(Solution)-self.dx,1.1)
        
        self.timer.setInterval(self.tmaxv/len(self.T)*10**3)
        #self.timer.setInterval(50)
        
        if self.Animation.isChecked() :
            self.n = 1
            self.my_line = self.Graph.plot(self.X,self.Finit(),name ='t=0', pen = mkPen(color = 'k') )
            self.timer.start()
        else :
            self.Graph.plot(self.X,self.Finit(),name ='t=0', pen = mkPen(color = 'b') )
            self.Graph.plot(self.X,Solution,name ='t=tmax', pen = mkPen(color = 'k') )
        
    def Finit(self) :
        X = np.arange(0,float(self.L.text()),self.dx)
        if self.CI.currentText() == 'exp(-x^2)' :
            return np.exp(-(X-float(self.L.text())/2)**2)
        elif self.CI.currentText() == 'sin(x)' :
            return np.sin(X)
        elif self.CI.currentText() == '0' :
            return [0 for x in X]
    
    def animplotter(self) :
        try :
            self.my_line.setData(self.X,self.solutions[self.n])
            self.n += 1
        except :
            self.timer.stop()
Example #12
0
class RTBSA(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.help_menu = self.menuBar().addMenu("&Help")
        self.file_menu = self.menuBar().addMenu("&File")
        self.status_text = QLabel()
        self.plot = PlotWidget(alpha=0.75)
        self.ui = Ui_RTBSA()
        self.ui.setupUi(self)
        self.setWindowTitle('Real Time BSA')
        self.loadStyleSheet()
        self.setUpGraph()

        self.bsapvs = [
            'GDET:FEE1:241:ENRC', 'GDET:FEE1:242:ENRC', 'GDET:FEE1:361:ENRC',
            'GDET:FEE1:362:ENRC'
        ]

        self.populateBSAPVs()
        self.connectGuiFunctions()

        # Initial number of points
        self.numPoints = 2800

        # Initial number of standard deviations
        self.stdDevstoKeep = 3.0

        # 20ms polling time
        self.updateTime = 50

        # Set initial polynomial fit to 2
        self.fitOrder = 2

        self.disableInputs()
        self.abort = True

        # Used to update plot
        self.timer = QTimer(self)

        # self.ratePV = PV('IOC:IN20:EV01:RG01_ACTRATE')
        self.ratePV = PV("EVNT:SYS0:1:LCLSBEAMRATE")

        self.menuBar().setStyleSheet(
            'QWidget{background-color:grey;color:purple}')
        self.create_menu()
        self.create_status_bar()

        # The PV names
        self.devices = {"A": "", "B": ""}

        self.pvObjects = {"A": None, "B": None}

        # The raw, unsynchronized, unfiltered buffers
        self.rawBuffers = {"A": empty(2800), "B": empty(2800)}

        # The times when each buffer finished its last data acquisition
        self.timeStamps = {"A": None, "B": None}

        self.synchronizedBuffers = {"A": empty(2800), "B": empty(2800)}

        # Versions of data buffers A and B that are filtered by standard
        # deviation. Didn't want to edit those buffers directly so that we could
        # unfilter or refilter with a different number more efficiently
        self.filteredBuffers = {"A": empty(2800), "B": empty(2800)}

        # Text objects that appear on the plot
        self.text = {"avg": None, "std": None, "slope": None, "corr": None}

        # All things plot related!
        self.plotAttributes = {
            "curve": None,
            "fit": None,
            "parab": None,
            "frequencies": None
        }

        # Used for the kill swtich
        self.counter = {"A": 0, "B": 0}

        # Used to implement scrolling for time plots
        self.currIdx = {"A": 0, "B": 0}

    def getRate(self):
        # return rtbsaUtils.rateDict[self.ratePV.value]
        return self.ratePV.value

    def disableInputs(self):
        self.ui.fitOrder.setDisabled(True)
        self.ui.searchInputA.setDisabled(True)
        self.ui.searchInputB.setDisabled(True)
        self.ui.labelFitOrder.setDisabled(True)
        self.ui.bsaListA.setDisabled(True)
        self.ui.bsaListB.setDisabled(True)
        self.statusBar().showMessage('Hi there!  I missed you!')
        self.ui.checkBoxPolyFit.setChecked(False)

    def populateBSAPVs(self):
        # Generate list of BSA PVS
        try:
            BSAPVs = check_output(
                ['eget', '-ts', 'ds', '-a',
                 'tag=LCLS.BSA.rootnames']).splitlines()[1:-1]
            self.bsapvs.extend(BSAPVs)

        # Backup for eget error
        except CalledProcessError:
            print("Unable to pull most recent PV list")
            # bsaPVs is pulled from the Constants file
            self.bsapvs.extend(rtbsaUtils.bsaPVs)

        # TODO un-hardcode machine and add common SPEAR PV's
        except OSError:
            print "Other machines coming soon to an RTBSA near you!"
            pass

        for pv in self.bsapvs:
            self.ui.bsaListA.addItem(pv)
            self.ui.bsaListB.addItem(pv)

    def connectGuiFunctions(self):
        # enter 1 is the text input box for device A, and 2 is for B
        QObject.connect(self.ui.searchInputA,
                        SIGNAL("textChanged(const QString&)"), self.searchA)
        QObject.connect(self.ui.searchInputB,
                        SIGNAL("textChanged(const QString&)"), self.searchB)

        # Changes the text in the input box to match the selection from the list
        self.ui.bsaListA.itemClicked.connect(self.setEnterA)
        self.ui.bsaListB.itemClicked.connect(self.setEnterB)

        # Dropdown menu for device A (add common BSA PV's)
        self.ui.dropdownA.addItems(rtbsaUtils.commonlist)

        # Make bunch length default selection
        index = rtbsaUtils.commonlist.index("BLEN:LI24:886:BIMAX")
        self.ui.dropdownA.setCurrentIndex(index)

        self.ui.dropdownA.activated.connect(self.inputActivated)

        # Dropdown menu for device B
        self.ui.dropdownB.addItems(rtbsaUtils.commonlist)
        self.ui.dropdownB.activated.connect(self.inputActivated)

        # All the checkboxes in the Settings section
        self.ui.checkBoxAvsT.clicked.connect(self.AvsTClick)
        self.ui.checkBoxBvsA.clicked.connect(self.AvsBClick)
        self.ui.checkBoxFFT.clicked.connect(self.AFFTClick)
        self.ui.checkBoxShowAve.clicked.connect(self.avg_click)
        self.ui.checkBoxShowStdDev.clicked.connect(self.std_click)
        self.ui.checkBoxCorrCoeff.clicked.connect(self.corr_click)
        self.ui.checkBoxPolyFit.clicked.connect(self.parab_click)
        self.ui.checkBoxLinFit.clicked.connect(self.line_click)
        self.ui.checkBoxShowGrid.clicked.connect(self.showGrid)

        # All the buttons in the Controls section
        self.ui.startButton.clicked.connect(self.initializePlot)
        self.ui.stopButton.clicked.connect(self.stop)
        self.ui.lclsLogButton.clicked.connect(self.logbook)
        self.ui.mccLogButton.clicked.connect(self.MCCLog)

        # fitedit is the text input box for "Order"
        self.ui.fitOrder.returnPressed.connect(self.fitOrderActivated)

        # The radio buttons that enable the dropdown menus
        self.ui.dropdownButtonA.clicked.connect(self.common_1_click)
        self.ui.dropdownButtonB.clicked.connect(self.common_2_click)

        # The radio buttons that enable the search bars
        self.ui.searchButtonA.clicked.connect(self.enter_1_click)
        self.ui.searchButtonB.clicked.connect(self.enter_2_click)

        # Pressing enter in the text input boxes for points and std dev triggers
        # updating the plot
        self.ui.numPoints.returnPressed.connect(self.points_entered)
        self.ui.numStdDevs.returnPressed.connect(self.stdDevEntered)

        # Triggers a redrawing upon pressing enter in the search bar.
        # Proper usage should be using the search bar to search, and selecting
        # from the results in the list. If it's not in the list, it's an invalid
        # PV with no reason to attempt plotting
        self.ui.searchInputA.returnPressed.connect(self.inputActivated)
        self.ui.searchInputB.returnPressed.connect(self.inputActivated)

    def showGrid(self):
        self.plot.showGrid(self.ui.checkBoxShowGrid.isChecked(),
                           self.ui.checkBoxShowGrid.isChecked())

    def setUpGraph(self):
        layout = QGridLayout()
        self.ui.widgetPlot.setLayout(layout)
        layout.addWidget(self.plot, 0, 0)
        self.plot.showGrid(1, 1)

    def loadStyleSheet(self):
        currDir = path.abspath(path.dirname(__file__))
        cssFile = path.join(currDir, "style.css")
        try:
            with open(cssFile, "r") as f:
                self.setStyleSheet(f.read())
        except IOError:
            print("Error loading style sheet")
            pass

    def create_status_bar(self):
        palette = QPalette()
        palette.setColor(palette.Foreground, Qt.magenta)
        self.statusBar().addWidget(self.status_text, 1)
        self.statusBar().setPalette(palette)

    # Effectively an autocomplete
    def search(self, enter, widget):
        widget.clear()
        query = str(enter.text())
        for pv in self.bsapvs:
            if query.lower() in pv.lower():
                widget.addItem(pv)

    def searchA(self):
        self.search(self.ui.searchInputA, self.ui.bsaListA)

    def searchB(self):
        self.search(self.ui.searchInputB, self.ui.bsaListB)

    def setEnter(self, widget, enter, search, enter_rb):
        selection = widget.currentItem()
        enter.textChanged.disconnect()
        enter.setText(selection.text())
        QObject.connect(enter, SIGNAL("textChanged(const QString&)"), search)

        if not self.abort and enter_rb.isChecked():
            self.stop()
            self.timer.singleShot(250, self.initializePlot)

    def setEnterA(self):
        self.setEnter(self.ui.bsaListA, self.ui.searchInputA, self.searchA,
                      self.ui.searchButtonA)

    def setEnterB(self):
        self.setEnter(self.ui.bsaListB, self.ui.searchInputB, self.searchB,
                      self.ui.searchButtonB)

    def correctInput(self, errorMessage, acceptableTxt, textBox):
        self.statusBar().showMessage(errorMessage, 6000)
        textBox.setText(acceptableTxt)

    def correctNumpoints(self, errorMessage, acceptableValue):
        self.correctInput(errorMessage, str(acceptableValue),
                          self.ui.numPoints)
        self.numPoints = acceptableValue

    def correctStdDevs(self, errorMessage, acceptableValue):
        self.correctInput(errorMessage, str(acceptableValue),
                          self.ui.numStdDevs)
        self.stdDevstoKeep = acceptableValue

    def stdDevEntered(self):
        try:
            self.stdDevstoKeep = float(self.ui.numStdDevs.text())
            if self.stdDevstoKeep <= 0:
                raise ValueError
        except ValueError:
            self.correctStdDevs('Enter a float > 0', 3.0)
            return

    def points_entered(self):
        try:
            self.numPoints = int(self.ui.numPoints.text())
        except ValueError:
            self.correctNumpoints('Enter an integer, 1 to 2800', 120)
            return

        if self.numPoints > 2800:
            self.correctNumpoints('Max # points is 2800', 2800)
            return

        if self.numPoints < 1:
            self.correctNumpoints('Min # points is 1', 1)
            return

        self.reinitialize_plot()

    ############################################################################
    # Where the magic happens (well, where it starts to happen). This
    # initializes the BSA plotting and then starts a timer to update the plot.
    ############################################################################
    def initializePlot(self):
        plotTypeIsValid = (self.ui.checkBoxAvsT.isChecked()
                           or self.ui.checkBoxBvsA.isChecked()
                           or self.ui.checkBoxFFT.isChecked())

        if not plotTypeIsValid:
            self.statusBar().showMessage(
                'Pick a Plot Type (PV vs. time '
                'or B vs A)', 10000)
            return

        self.ui.startButton.setDisabled(True)
        self.abort = False

        self.cleanPlot()
        self.pvObjects["A"], self.pvObjects["B"] = None, None

        # Plot history buffer for one PV
        if self.ui.checkBoxAvsT.isChecked():
            if self.populateDevices(self.ui.dropdownButtonA, self.ui.dropdownA,
                                    self.ui.searchButtonA,
                                    self.ui.searchInputA, "A"):
                self.genPlotAndSetTimer(self.genTimePlotA,
                                        self.updateTimePlotA)

        # Plot for 2 PVs
        elif self.ui.checkBoxBvsA.isChecked():
            if self.updateValsFromInput():
                self.genPlotAndSetTimer(self.genPlotAB, self.updatePlotAB)

        # Plot power spectrum
        else:
            if self.populateDevices(self.ui.dropdownButtonA, self.ui.dropdownA,
                                    self.ui.searchButtonA,
                                    self.ui.searchInputA, "A"):
                self.genPlotAndSetTimer(self.InitializeFFTPlot,
                                        self.updatePlotFFT)

    def populateDevices(self, common_rb, common, enter_rb, enter, device):

        if common_rb.isChecked():
            self.devices[device] = str(common.currentText())

        elif enter_rb.isChecked():
            pv = str(enter.text()).strip()

            # Checks that it's non empty and that it's a BSA pv
            if pv and pv in self.bsapvs:
                self.devices[device] = pv
            else:
                self.printStatus('Device ' + device + ' invalid. Aborting.')
                self.ui.startButton.setEnabled(True)
                return False

        return True

    def printStatus(self, message, printToXterm=True):
        if printToXterm:
            print message

        self.statusBar().showMessage(message)

    def updateValsFromInput(self):

        if not self.populateDevices(self.ui.dropdownButtonA, self.ui.dropdownA,
                                    self.ui.searchButtonA,
                                    self.ui.searchInputA, "A"):
            return False

        if not self.populateDevices(self.ui.dropdownButtonB, self.ui.dropdownB,
                                    self.ui.searchButtonB,
                                    self.ui.searchInputB, "B"):
            return False

        self.printStatus("Initializing/Synchronizing " + self.devices["A"] +
                         " vs. " + self.devices["B"] + " buffers...")

        self.initializeBuffers()

        return True

    def initializeBuffers(self):
        # Initial population of our buffers using the HSTBR PV's in our
        # callback functions
        self.clearAndUpdateCallbacks("HSTBR", resetTime=True)

        while ((not self.timeStamps["A"] or not self.timeStamps["B"])
               and not self.abort):
            QApplication.processEvents()

        self.adjustSynchronizedBuffers(True)

        # Switch to BR PVs to avoid pulling an entire history buffer on every
        # update.
        self.clearAndUpdateCallbacks("BR", resetRawBuffer=True)

    def clearAndUpdateCallbacks(self,
                                suffix,
                                resetTime=False,
                                resetRawBuffer=False):
        self.clearAndUpdateCallback("A", suffix, self.callbackA,
                                    self.devices["A"], resetTime,
                                    resetRawBuffer)
        self.clearAndUpdateCallback("B", suffix, self.callbackB,
                                    self.devices["B"], resetTime,
                                    resetRawBuffer)

    # noinspection PyTypeChecker
    def clearAndUpdateCallback(self,
                               device,
                               suffix,
                               callback,
                               pvName,
                               resetTime=False,
                               resetRawBuffer=False):
        self.clearPV(device)

        # Without the time parameter, we wouldn't get the timestamp
        self.pvObjects[device] = PV(pvName + suffix, form='time')

        if resetTime:
            self.timeStamps[device] = None

        # Make sure that the initial raw buffer is synchronized and pad with
        # nans if it's less than 2800 points long
        if resetRawBuffer:
            nanArray = empty(2800 - self.synchronizedBuffers[device].size)
            nanArray[:] = nan
            self.rawBuffers[device] = \
                concatenate([self.synchronizedBuffers[device], nanArray])

        self.pvObjects[device].add_callback(callback)

    # Callback function for Device A
    # noinspection PyUnusedLocal
    def callbackA(self, pvname=None, value=None, timestamp=None, **kw):
        self.updateTimeAndBuffer("A", pvname, timestamp, value)

    # Callback function for Device B
    # noinspection PyUnusedLocal
    def callbackB(self, pvname=None, value=None, timestamp=None, **kw):
        self.updateTimeAndBuffer("B", pvname, timestamp, value)

    ############################################################################
    # This is where the data is actually acquired and saved to the buffers.
    # Callbacks are effectively listeners that listen for change, so we
    # basically put a callback on the PVs of interest (devices A and/or B) so
    # that every time the value of that PV changes, we get that new value and
    # append it to our raw data buffer for that device.
    # Initialization of the buffer is slightly different in that the listener is
    # put on the history buffer of that PV (denoted by the HSTBR suffix), so
    # that we just immediately write the previous 2800 points to our raw buffer
    ############################################################################
    def updateTimeAndBuffer(self, device, pvname, timestamp, value):
        def padRawBufferWithNans(start, end):
            rtbsaUtils.padWithNans(self.rawBuffers[device], start, end)

        if "HSTBR" in pvname:
            self.timeStamps[device] = timestamp

            # value is the buffer because we're monitoring the HSTBR PV
            self.rawBuffers[device] = value

            # Reset the counter every time we reinitialize the plot
            self.counter[device] = 0

        else:
            if not self.timeStamps[device]:
                return

            rate = self.getRate()
            if rate < 1:
                return

            scalingFactor = 1.0 / rate
            elapsedPulses = round(
                (timestamp - self.timeStamps[device]) / scalingFactor)

            currIdx = int((timestamp / scalingFactor) % self.numPoints)

            if elapsedPulses <= 0:
                return

            # Pad the buffer with nans for missed pulses
            elif elapsedPulses > 1:

                # noinspection PyTypeChecker
                lastIdx = int(
                    (self.timeStamps[device] / scalingFactor) % self.numPoints)

                # Take care of wrap around
                if currIdx < lastIdx:
                    padRawBufferWithNans(lastIdx + 1, self.numPoints)
                    padRawBufferWithNans(0, currIdx)

                else:
                    padRawBufferWithNans(lastIdx + 1, currIdx)

            # Directly index into the raw buffer using the timestamp
            self.rawBuffers[device][currIdx] = value

            self.counter[device] += elapsedPulses
            self.timeStamps[device] = timestamp
            self.currIdx[device] = currIdx

    def clearPV(self, device):
        pv = self.pvObjects[device]
        if pv:
            pv.clear_callbacks()
            pv.disconnect()

    def adjustSynchronizedBuffers(self, syncByTime=False):
        numBadShots = self.populateSynchronizedBuffers(syncByTime)
        blength = 2800 - numBadShots

        # Make sure the buffer size doesn't exceed the desired number of points
        if self.numPoints < blength:
            self.synchronizedBuffers["A"] = \
                self.synchronizedBuffers["A"][:self.numPoints]

            self.synchronizedBuffers["B"] = \
                self.synchronizedBuffers["B"][:self.numPoints]

    # A spin loop that waits until the beam rate is at least 1Hz
    def waitForRate(self):

        start_time = time()
        gotStuckAndNeedToUpdateMessage = False

        # self.rate is a PV, such that .value is shorthand for .getval
        while self.ratePV.value < 1:
            # while self.ratePV.value < 2:
            #     # noinspection PyArgumentList
            QApplication.processEvents()
            #
            if time() - start_time > 0.5:
                gotStuckAndNeedToUpdateMessage = True
                self.printStatus("Waiting for beam rate to be at least 1Hz...",
                                 False)

        if gotStuckAndNeedToUpdateMessage:
            self.printStatus("Running", False)

        # return rtbsaUtils.rateDict[self.ratePV.value]
        return self.ratePV.value

    ############################################################################
    # Time 1 is when Device A started acquiring data, and Time 2 is when Device
    # B started acquiring data. Since they're not guaranteed to start
    # acquisition at the same time, one data buffer might be ahead of the other,
    # meaning that the intersection of the two buffers would not include the
    # first n elements of one and the last n elements of the other. See the
    # diagram below, where the dotted line represents the time axis (one buffer
    # is contained  by square brackets [], the other by curly braces {}, and the
    # times where each starts and ends is indicated right underneath).
    #
    #
    #          [           {                            ]           }
    # <----------------------------------------------------------------------> t
    #       t1_start    t2_start                     t1_end      t2_end
    #
    #
    # Note that both buffers are of the same size (2800) so that:
    # (t1_end - t1_start) = (t2_end - t2_start)
    #
    # From the diagram, we see that only the time between t2_start and t1_end
    # contains data from both buffers (t1_start to t2_start only contains data
    # from buffer 1, and t1_end to t2_end only contains data from buffer 2).
    # Using that, we can chop the beginning of buffer 1 and the end of buffer 2
    # so that we're only left with the overlapping region.
    #
    # In order to figure out how many points we need to chop from each buffer
    # (it's the same number for both since they're both the same size), we
    # multiply the time delta by the beam rate (yay dimensional analysis!):
    # seconds * (shots/second) = (number of shots)
    #
    # That whole rigmarole only applies to the initial population of the buffers
    # (where we're pulling the entire history buffer at once using the HSTBR
    # suffix). From then on, we're indexing into the raw buffers using the
    # pulse ID modulo 2800, so they're inherently synchronized
    ############################################################################
    def populateSynchronizedBuffers(self, syncByTime):
        def padSyncBufferWithNans(device, startIdx, endIdx):
            lag = endIdx - startIdx

            if lag > 20:
                print("Reinitializing buffers due to " + str(lag) +
                      " shot lag for device " + device)
                self.initializeBuffers()

            else:
                rtbsaUtils.padWithNans(self.synchronizedBuffers[device],
                                       startIdx + 1, endIdx + 1)

        def checkIndices(device, startIdx, endIdx):
            # Check for index wraparound
            if endIdx < startIdx:
                padSyncBufferWithNans(device, startIdx, self.numPoints - 1)
                padSyncBufferWithNans(device, 0, endIdx)

            else:
                padSyncBufferWithNans(device, startIdx, endIdx)

        if syncByTime:
            numBadShots = int(
                round((self.timeStamps["B"] - self.timeStamps["A"]) *
                      self.getRate()))

            startA, endA = rtbsaUtils.getIndices(numBadShots, 1)
            startB, endB = rtbsaUtils.getIndices(numBadShots, -1)

            self.synchronizedBuffers["A"] = self.rawBuffers["A"][startA:endA]
            self.synchronizedBuffers["B"] = self.rawBuffers["B"][startB:endB]

            return abs(numBadShots)

        else:

            self.synchronizedBuffers["A"] = self.rawBuffers["A"]
            self.synchronizedBuffers["B"] = self.rawBuffers["B"]

            # The timestamps and indices get updated by the callbacks, so we
            # store the values at the time of buffer-copying
            timeStampA = self.timeStamps["A"]
            timeStampB = self.timeStamps["B"]

            currIdxA = self.currIdx["A"]
            currIdxB = self.currIdx["B"]

            diff = timeStampA - timeStampB

            if diff > 0:
                checkIndices("A", currIdxB, currIdxA)

            elif diff < 0:
                checkIndices("B", currIdxA, currIdxB)

            return 0

    def genPlotAndSetTimer(self, genPlot, updateMethod):
        if self.abort:
            return

        try:
            genPlot()
        except UnboundLocalError:
            self.printStatus('No Data, Aborting Plotting Algorithm')
            return

        self.timer = QTimer(self)

        # Run updateMethod every updatetime milliseconds
        self.timer.singleShot(self.updateTime, updateMethod)

        self.printStatus('Running')

    # noinspection PyTypeChecker
    def genTimePlotA(self):
        newData = self.initializeData()

        if not newData.size:
            self.printStatus('Invalid PV? Unable to get data. Aborting.')
            self.ui.startButton.setEnabled(True)
            return

        data = newData[:self.numPoints]

        self.plotAttributes["curve"] = PlotCurveItem(data, pen=1)
        self.plot.addItem(self.plotAttributes["curve"])

        self.plotFit(arange(self.numPoints), data, self.devices["A"])

    ############################################################################
    # This is the main plotting function for "Plot A vs Time" that gets called
    # every self.updateTime seconds
    # noinspection PyTypeChecker
    ############################################################################
    def updateTimePlotA(self):

        if not self.checkPlotStatus():
            return

        xData, yData = self.filterTimePlotBuffer()

        if yData.size:
            self.plotAttributes["curve"].setData(yData)
            if self.ui.checkBoxAutoscale.isChecked():
                mx = max(yData)
                mn = min(yData)
                if mx - mn > .00001:
                    self.plot.setYRange(mn, mx)
                    self.plot.setXRange(0, len(yData))

            if self.ui.checkBoxShowAve.isChecked():
                rtbsaUtils.setPosAndText(self.text["avg"], mean(yData), 0,
                                         min(yData), 'AVG: ')

            if self.ui.checkBoxShowStdDev.isChecked():
                rtbsaUtils.setPosAndText(self.text["std"],
                                         std(yData), self.numPoints / 4,
                                         min(yData), 'STD: ')

            if self.ui.checkBoxCorrCoeff.isChecked():
                self.text["corr"].setText('')

            if self.ui.checkBoxLinFit.isChecked():
                self.text["slope"].setPos(self.numPoints / 2, min(yData))
                self.getLinearFit(xData, yData, True)

            elif self.ui.checkBoxPolyFit.isChecked():
                self.text["slope"].setPos(self.numPoints / 2, min(yData))
                self.getPolynomialFit(xData, yData, True)

        self.timer.singleShot(self.updateTime, self.updateTimePlotA)

    def checkPlotStatus(self):
        QApplication.processEvents()

        if self.abort:
            return False

        self.waitForRate()

        # kill switch to stop backgrounded, forgetten GUIs. Somewhere in the
        # ballpark of 20 minutes assuming 120Hz
        if self.counter["A"] > 150000:
            self.stop()
            self.printStatus("Stopping due to inactivity")

        return True

    def filterTimePlotBuffer(self):
        currIdx = self.currIdx["A"]
        choppedBuffer = self.rawBuffers["A"][:self.numPoints]

        # All this nonsense to make it scroll :P Thanks to Ben for the
        # inspiration!
        if currIdx > 0:
            choppedBuffer = concatenate(
                [choppedBuffer[currIdx:], choppedBuffer[:currIdx]])

        xData, yData = rtbsaUtils.filterBuffers(choppedBuffer,
                                                lambda x: ~isnan(x),
                                                arange(self.numPoints),
                                                choppedBuffer)

        if self.devices["A"] == "BLEN:LI24:886:BIMAX":
            xData, yData = rtbsaUtils.filterBuffers(
                yData, lambda x: x < rtbsaUtils.IPK_LIMIT, xData, yData)

        if self.ui.checkBoxStdDev.isChecked():
            stdDevFilterFunc = self.StdDevFilterFunc(mean(yData), std(yData))
            xData, yData = rtbsaUtils.filterBuffers(yData, stdDevFilterFunc,
                                                    xData, yData)
        return xData, yData

    def getLinearFit(self, xData, yData, updateExistingPlot):
        # noinspection PyTupleAssignmentBalance
        m, b = polyfit(xData, yData, 1)
        fitData = polyval([m, b], xData)

        self.text["slope"].setText('Slope: ' + str("{:.3e}".format(m)))

        if updateExistingPlot:
            self.plotAttributes["fit"].setData(xData, fitData)
        else:
            # noinspection PyTypeChecker
            self.plotAttributes["fit"] = PlotCurveItem(xData,
                                                       fitData,
                                                       'g-',
                                                       linewidth=1)

    def getPolynomialFit(self, xData, yData, updateExistingPlot):
        co = polyfit(xData, yData, self.fitOrder)
        pol = poly1d(co)
        xDataSorted = sorted(xData)
        fit = pol(xDataSorted)

        if updateExistingPlot:
            self.plotAttributes["parab"].setData(xDataSorted, fit)
        else:
            # noinspection PyTypeChecker
            self.plotAttributes["parab"] = PlotCurveItem(xDataSorted,
                                                         fit,
                                                         pen=3,
                                                         size=2)

        if self.fitOrder == 2:
            self.text["slope"].setText('Peak: ' + str(-co[1] / (2 * co[0])))

        elif self.fitOrder == 3:
            self.text["slope"].setText(
                str("{:.2e}".format(co[0])) + 'x^3' +
                str("+{:.2e}".format(co[1])) + 'x^2' +
                str("+{:.2e}".format(co[2])) + 'x' +
                str("+{:.2e}".format(co[3])))

    def genPlotAB(self):
        if self.ui.checkBoxStdDev.isChecked():
            self.plotCurveAndFit(self.filteredBuffers["A"],
                                 self.filteredBuffers["B"])
        else:
            self.plotCurveAndFit(self.synchronizedBuffers["A"],
                                 self.synchronizedBuffers["B"])

    def plotCurveAndFit(self, xData, yData):
        # noinspection PyTypeChecker
        self.plotAttributes["curve"] = ScatterPlotItem(xData,
                                                       yData,
                                                       pen=1,
                                                       symbol='x',
                                                       size=5)
        self.plot.addItem(self.plotAttributes["curve"])
        self.plotFit(xData, yData,
                     self.devices["B"] + ' vs. ' + self.devices["A"])

    def plotFit(self, xData, yData, title):
        self.plot.addItem(self.plotAttributes["curve"])
        self.plot.setTitle(title)

        # Fit line
        if self.ui.checkBoxLinFit.isChecked():
            self.getLinearFit(xData, yData, False)
            self.plot.addItem(self.plotAttributes["fit"])

        # Fit polynomial
        elif self.ui.checkBoxPolyFit.isChecked():
            self.ui.fitOrder.setDisabled(False)
            try:
                self.getPolynomialFit(xData, yData, False)
                self.plot.addItem(self.plotAttributes["parab"])
            except linalg.linalg.LinAlgError:
                print "Error getting polynomial fit"

    ############################################################################
    # This is the main plotting function for "Plot B vs A" that gets called
    # every self.updateTime milliseconds
    ############################################################################
    def updatePlotAB(self):
        if not self.checkPlotStatus():
            return

        QApplication.processEvents()

        self.adjustSynchronizedBuffers()
        self.filterNans()
        self.filterPeakCurrent()

        if self.ui.checkBoxStdDev.isChecked():
            self.filterStdDev()
            self.updateLabelsAndFit(self.filteredBuffers["A"],
                                    self.filteredBuffers["B"])
        else:
            self.updateLabelsAndFit(self.synchronizedBuffers["A"],
                                    self.synchronizedBuffers["B"])

        self.timer.singleShot(self.updateTime, self.updatePlotAB)

    def filterNans(self):
        def filterFunc(x):
            return ~isnan(x)

        self.filterData(self.synchronizedBuffers["A"], filterFunc, True)
        self.filterData(self.synchronizedBuffers["B"], filterFunc, True)

    # Need to filter out errant indices from both buffers to keep them
    # synchronized
    def filterData(self, dataBuffer, filterFunc, changeOriginal):
        bufferA, bufferB = rtbsaUtils.filterBuffers(
            dataBuffer, filterFunc, self.synchronizedBuffers["A"],
            self.synchronizedBuffers["B"])

        if changeOriginal:
            self.synchronizedBuffers["A"] = bufferA
            self.synchronizedBuffers["B"] = bufferB
        else:
            self.filteredBuffers["A"] = bufferA
            self.filteredBuffers["B"] = bufferB

    # This PV gets insane values, apparently
    def filterPeakCurrent(self):
        def filterFunc(x):
            return x < rtbsaUtils.IPK_LIMIT

        if self.devices["A"] == "BLEN:LI24:886:BIMAX":
            self.filterData(self.synchronizedBuffers["A"], filterFunc, True)
        if self.devices["B"] == "BLEN:LI24:886:BIMAX":
            self.filterData(self.synchronizedBuffers["B"], filterFunc, True)

    def filterStdDev(self):

        bufferA = self.synchronizedBuffers["A"]
        bufferB = self.synchronizedBuffers["B"]

        self.filterData(bufferA,
                        self.StdDevFilterFunc(mean(bufferA), std(bufferA)),
                        False)

        self.filterData(bufferB,
                        self.StdDevFilterFunc(mean(bufferB), std(bufferB)),
                        False)

    def StdDevFilterFunc(self, average, stdDev):
        return lambda x: abs(x - average) < self.stdDevstoKeep * stdDev

    # noinspection PyTypeChecker
    def updateLabelsAndFit(self, bufferA, bufferB):
        self.plotAttributes["curve"].setData(bufferA, bufferB)

        try:
            if self.ui.checkBoxAutoscale.isChecked():
                self.setPlotRanges(bufferA, bufferB)

            minBufferA = nanmin(bufferA)
            minBufferB = nanmin(bufferB)
            maxBufferA = nanmax(bufferA)
            maxBufferB = nanmax(bufferB)

            if self.ui.checkBoxShowAve.isChecked():
                rtbsaUtils.setPosAndText(self.text["avg"], nanmean(bufferB),
                                         minBufferA, minBufferB, 'AVG: ')

            if self.ui.checkBoxShowStdDev.isChecked():
                xPos = (minBufferA + (minBufferA + maxBufferA) / 2) / 2

                rtbsaUtils.setPosAndText(self.text["std"], nanstd(bufferB),
                                         xPos, minBufferB, 'STD: ')

            if self.ui.checkBoxCorrCoeff.isChecked():
                correlation = corrcoef(bufferA, bufferB)
                rtbsaUtils.setPosAndText(self.text["corr"],
                                         correlation.item(1), minBufferA,
                                         maxBufferB, "Corr. Coefficient: ")

            if self.ui.checkBoxLinFit.isChecked():
                self.text["slope"].setPos((minBufferA + maxBufferA) / 2,
                                          minBufferB)
                self.getLinearFit(bufferA, bufferB, True)

            elif self.ui.checkBoxPolyFit.isChecked():
                self.text["slope"].setPos((minBufferA + maxBufferA) / 2,
                                          minBufferB)
                self.getPolynomialFit(bufferA, bufferB, True)

        except ValueError:
            print "Error updating plot range"

    def setPlotRanges(self, bufferA, bufferB):
        mx = nanmax(bufferB)
        mn = nanmin(bufferB)

        if mn != mx:
            self.plot.setYRange(mn, mx)

        mx = nanmax(bufferA)
        mn = nanmin(bufferA)

        if mn != mx:
            self.plot.setXRange(mn, mx)

    def InitializeFFTPlot(self):
        self.genPlotFFT(self.initializeData(), False)

    # TODO I have no idea what's happening here
    def genPlotFFT(self, newdata, updateExistingPlot):

        if not newdata.size:
            return None

        newdata = newdata[:self.numPoints]

        nans, x = isnan(newdata), lambda z: z.nonzero()[0]
        # interpolate nans
        newdata[nans] = interp(x(nans), x(~nans), newdata[~nans])
        # remove DC component
        newdata = newdata - mean(newdata)

        newdata = concatenate([newdata, zeros(self.numPoints * 2)])

        ps = abs(fft.fft(newdata)) / newdata.size

        self.waitForRate()
        frequencies = fft.fftfreq(newdata.size, 1.0 / self.getRate())
        keep = (frequencies >= 0)
        ps = ps[keep]
        frequencies = frequencies[keep]
        idx = argsort(frequencies)

        if updateExistingPlot:
            self.plotAttributes["curve"].setData(x=frequencies[idx], y=ps[idx])
        else:
            # noinspection PyTypeChecker
            self.plotAttributes["curve"] = PlotCurveItem(x=frequencies[idx],
                                                         y=ps[idx],
                                                         pen=1)

        self.plot.addItem(self.plotAttributes["curve"])
        self.plot.setTitle(self.devices["A"])
        self.plotAttributes["frequencies"] = frequencies

        return ps

    # noinspection PyTypeChecker
    def cleanPlot(self):
        self.plot.clear()

        self.text["avg"] = TextItem('', color=(200, 200, 250), anchor=(0, 1))
        self.text["std"] = TextItem('', color=(200, 200, 250), anchor=(0, 1))
        self.text["slope"] = TextItem('', color=(200, 200, 250), anchor=(0, 1))
        self.text["corr"] = TextItem('', color=(200, 200, 250), anchor=(0, 1))

        plotLabels = [
            self.text["avg"], self.text["std"], self.text["slope"],
            self.text["corr"]
        ]

        for plotLabel in plotLabels:
            self.plot.addItem(plotLabel)

    def initializeData(self):
        self.printStatus("Initializing " + self.devices["A"] + " buffer...",
                         True)

        if self.ui.dropdownButtonA.isChecked():
            self.devices["A"] = str(self.ui.dropdownA.currentText())

        elif self.ui.searchButtonA.isChecked():
            pv = str(self.ui.searchInputA.text()).strip()
            if pv and pv in self.bsapvs:
                self.devices["A"] = pv
            else:
                return None
        else:
            return None

        # Initializing our data by putting a callback on the history buffer PV
        self.clearAndUpdateCallback("A", "HSTBR", self.callbackA,
                                    self.devices["A"], True)

        while (not self.timeStamps["A"]) and not self.abort:
            QApplication.processEvents()

        # Removing that callback and manually appending new values to our local
        # data buffer using the usual PV
        # TODO ask Ahmed what the BR is for
        self.clearAndUpdateCallback("A", "BR", self.callbackA,
                                    self.devices["A"])

        # This was populated in the callback function
        return self.rawBuffers["A"]

    ############################################################################
    # This is the main plotting function for "Plot A FFT" that gets called
    # every self.updateTime seconds
    ############################################################################
    def updatePlotFFT(self):
        if not self.checkPlotStatus():
            return

        ps = self.genPlotFFT(self.rawBuffers["A"], True)

        if self.ui.checkBoxAutoscale.isChecked():
            mx = max(ps)
            mn = min(ps)
            if mx - mn > .00001:
                frequencies = self.plotAttributes["frequencies"]
                self.plot.setYRange(mn, mx)
                # noinspection PyTypeChecker
                self.plot.setXRange(min(frequencies), max(frequencies))

        self.timer.singleShot(self.updateTime, self.updatePlotFFT)

    def AvsTClick(self):
        if not self.ui.checkBoxAvsT.isChecked():
            pass
        else:
            self.ui.checkBoxBvsA.setChecked(False)
            self.ui.checkBoxFFT.setChecked(False)
            self.AvsBClick()

    def AvsBClick(self):
        if not self.ui.checkBoxBvsA.isChecked():
            self.ui.groupBoxB.setDisabled(True)
            self.ui.searchButtonB.setChecked(False)
            self.ui.searchButtonB.setDisabled(True)
            self.ui.searchInputB.setDisabled(True)
            self.ui.dropdownB.setDisabled(True)
            self.ui.dropdownButtonB.setChecked(False)
            self.ui.dropdownButtonB.setDisabled(True)
        else:
            self.ui.checkBoxAvsT.setChecked(False)
            self.ui.checkBoxFFT.setChecked(False)
            self.AvsTClick()
            self.ui.groupBoxB.setDisabled(False)
            self.ui.bsaListB.setDisabled(True)
            self.ui.searchButtonB.setDisabled(False)
            self.ui.searchInputB.setDisabled(True)
            self.ui.dropdownButtonB.setDisabled(False)
            self.ui.dropdownButtonB.setChecked(True)
            self.ui.dropdownB.setDisabled(False)

        self.stop()
        self.timer.singleShot(250, self.initializePlot)

    def AFFTClick(self):
        if not self.ui.checkBoxFFT.isChecked():
            pass
        else:
            self.ui.checkBoxBvsA.setChecked(False)
            self.ui.checkBoxAvsT.setChecked(False)
            self.AvsBClick()

    def avg_click(self):
        if not self.ui.checkBoxShowAve.isChecked():
            self.text["avg"].setText('')

    def std_click(self):
        if not self.ui.checkBoxShowStdDev.isChecked():
            self.text["std"].setText('')

    def corr_click(self):
        if not self.ui.checkBoxCorrCoeff.isChecked():
            self.text["corr"].setText('')

    def enter_1_click(self):
        if self.ui.searchButtonA.isChecked():
            self.ui.searchInputA.setDisabled(False)
            self.ui.bsaListA.setDisabled(False)
            self.ui.dropdownButtonA.setChecked(False)
            self.ui.dropdownA.setDisabled(True)
        else:
            self.ui.searchInputA.setDisabled(True)

    def enter_2_click(self):
        if self.ui.searchButtonB.isChecked():
            self.ui.searchInputB.setDisabled(False)
            self.ui.bsaListB.setDisabled(False)
            self.ui.dropdownButtonB.setChecked(False)
            self.ui.dropdownB.setDisabled(True)
        else:
            self.ui.searchInputB.setDisabled(True)

    def common_1_click(self):
        if self.ui.dropdownButtonA.isChecked():
            self.ui.dropdownA.setEnabled(True)
            self.ui.searchButtonA.setChecked(False)
            self.ui.searchInputA.setDisabled(True)
            self.ui.bsaListA.setDisabled(True)
        else:
            self.ui.dropdownA.setEnabled(False)
        self.inputActivated()

    def inputActivated(self):
        if not self.abort:
            self.stop()
            self.timer.singleShot(250, self.initializePlot)

    def common_2_click(self):
        if self.ui.dropdownButtonB.isChecked():
            self.ui.dropdownB.setEnabled(True)
            self.ui.searchButtonB.setChecked(False)
            self.ui.searchInputB.setDisabled(True)
            self.ui.bsaListB.setDisabled(True)
        else:
            self.ui.dropdownB.setEnabled(False)
        self.inputActivated()

    def line_click(self):
        self.ui.checkBoxPolyFit.setChecked(False)
        self.ui.fitOrder.setDisabled(True)
        self.ui.labelFitOrder.setDisabled(True)
        self.reinitialize_plot()

    def fitOrderActivated(self):
        try:
            self.fitOrder = int(self.ui.fitOrder.text())
        except ValueError:
            self.statusBar().showMessage('Enter an integer, 1-10', 6000)
            return

        if self.fitOrder > 10 or self.fitOrder < 1:
            self.statusBar().showMessage(
                'Really?  That is going to be useful' +
                ' to you?  The (already ridiculous)' +
                ' range is 1-10.  Hope you win a ' + 'nobel prize jackass.',
                6000)
            self.ui.fitOrder.setText('2')
            self.fitOrder = 2

        if self.fitOrder != 2:
            try:
                self.text["slope"].setText('')
            except AttributeError:
                pass

    def parab_click(self):
        self.ui.checkBoxLinFit.setChecked(False)

        if not self.ui.checkBoxPolyFit.isChecked():
            self.ui.fitOrder.setDisabled(True)
            self.ui.labelFitOrder.setDisabled(True)
        else:
            self.ui.fitOrder.setEnabled(True)
            self.ui.labelFitOrder.setEnabled(True)

        self.reinitialize_plot()

    # This is a mess, but it works (used if user changes number points,
    # fit type etc.)
    def reinitialize_plot(self):
        self.cleanPlot()

        # Setup for single PV plotting
        if self.ui.checkBoxAvsT.isChecked():
            self.genTimePlotA()

        elif self.ui.checkBoxBvsA.isChecked():
            self.genPlotAB()
        else:
            self.genPlotFFT(self.synchronizedBuffers["A"], False)

    def logbook(self):
        rtbsaUtils.logbook('Python Real-Time BSA', 'BSA Data',
                           str(self.numPoints) + ' points', self.plot.plotItem)
        self.statusBar().showMessage('Sent to LCLS Physics Logbook!', 10000)

    def MCCLog(self):
        rtbsaUtils.MCCLog('/tmp/RTBSA.png', '/tmp/RTBSA.ps',
                          self.plot.plotItem)

    def clearCallbacks(self, device):
        if self.pvObjects[device]:
            self.pvObjects[device].clear_callbacks()
            self.pvObjects[device].disconnect()

    def stop(self):
        self.clearCallbacks("A")

        if self.pvObjects["B"]:
            self.clearCallbacks("B")

        self.abort = True
        self.statusBar().showMessage('Stopped')
        self.ui.startButton.setDisabled(False)
        QApplication.processEvents()

    def create_menu(self):

        load_file_action = self.create_action("&Save plot",
                                              shortcut="Ctrl+S",
                                              slot=self.save_plot,
                                              tip="Save the plot")

        quit_action = self.create_action("&Quit",
                                         slot=self.close,
                                         shortcut="Ctrl+Q",
                                         tip="Close the application")

        rtbsaUtils.add_actions(self.file_menu,
                               (load_file_action, None, quit_action))

        about_action = self.create_action("&About",
                                          shortcut='F1',
                                          slot=self.on_about,
                                          tip='About')

        rtbsaUtils.add_actions(self.help_menu, (about_action, ))

    def create_action(self,
                      text,
                      slot=None,
                      shortcut=None,
                      icon=None,
                      tip=None,
                      checkable=False,
                      signal="triggered()"):

        action = QAction(text, self)

        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action

    def save_plot(self):
        file_choices = "PNG (*.png)|*.png"
        # noinspection PyTypeChecker,PyCallByClass
        filePath = unicode(
            QFileDialog.getSaveFileName(self, 'Save file', '', file_choices))
        if filePath:
            self.ui.widgetPlot.canvas.print_figure(filePath, dpi=100)
            self.statusBar().showMessage('Saved to %s' % filePath, 2000)

    def on_about(self):
        msg = (
            "Can you read this?  If so, congratulations. You are a magical, " +
            "marvelous troll.")
        # noinspection PyCallByClass
        QMessageBox.about(self, "About", msg.strip())
class SpectrometerWidget(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setLayout(QtGui.QHBoxLayout())
        self.resize(700, 500)
        self.wave = []
        self.spec = []
        self.time = None

        @inlineCallbacks
        def onInit():
            # connect to server
            ipAddress = TEST_SPECTROMETER_SERVER if DEBUG else SPECTROMETER_SERVER
            protocol = yield getProtocol(ipAddress)

            # create a client
            self.client = SpectrometerClient(protocol)
            self.wave = yield self.client.getWavelengths()
            self.numberToAverage = 1
            self.numberAcquired = 0
            self.darkSpectrum = np.zeros(NUM_PIXELS)
            self.specProcessed = np.zeros(NUM_PIXELS)
            self.gettingDark = False

            # set up overall layout: 1 large panel (plot) to left of 1 narrow /
            # panel (controls) all above 1 skinny panel (timestamp)
            fullLayout = QtGui.QVBoxLayout()
            self.layout().addLayout(fullLayout)

            topHalfLayout = QtGui.QHBoxLayout()
            fullLayout.addLayout(topHalfLayout)

            # define the plot
            self.plotWidget = PlotWidget()
            self.plot = self.plotWidget.plot()
            topHalfLayout.addWidget(self.plotWidget, 1)

            # define the controls panel
            cpLayout = QtGui.QVBoxLayout()
            topHalfLayout.addLayout(cpLayout)

            # define the capture controls (to go on controls panel)
            capLayout = QtGui.QVBoxLayout()

            def updatePlot(x, y):
                x = np.asarray(x)
                y = np.asarray(y)
                self.plotWidget.clear()
                self.plotWidget.plot(x, y, pen=mkPen("w", width=1))
                self.plotWidget.addItem(self.cursorVert)
                self.plotWidget.addItem(self.cursorHori)
                vertLabel.setText(str(round(self.cursorVert.pos()[0], 2)))
                horiLabel.setText(str(round(self.cursorHori.pos()[1], 2)))

            def avgSpec():
                oldAvgSpec = self.specProcessed
                addThis = self.spec - self.darkSpectrum
                self.numberAcquired += 1
                if self.numberAcquired < self.numberToAverage:
                    scale = self.numberAcquired
                else:
                    scale = self.numberToAverage
                newAvg = ((scale - 1) * oldAvgSpec + addThis) / scale
                self.specProcessed = newAvg

            @inlineCallbacks
            def capture():
                self.spec = yield self.client.getSpectrum()
                self.spec = np.asarray(self.spec)
                self.time = yield self.client.getLastTime()
                yield avgSpec()
                updatePlot(self.wave, self.specProcessed)
                self.timestamp.setText("last update: " + str(self.time))

            @inlineCallbacks
            def forcePress():
                self.numberAcquired = 0
                yield capture()

            forceButton = QtGui.QPushButton("force")
            forceButton.clicked.connect(forcePress)
            capLayout.addWidget(forceButton)

            autoRunLayout = QtGui.QHBoxLayout()

            self.freeRunCall = LoopingCall(capture)
            self.freeRunStatus = False

            def freeRun():
                if self.freeRunStatus:
                    freeButton.setText("start auto")
                    forceButton.setEnabled(True)
                    self.freeRunCall.stop()
                    self.freeRunStatus = False
                    self.numberAcquired = 0
                    return
                if not self.freeRunStatus:
                    freeButton.setText("stop auto")
                    forceButton.setEnabled(False)
                    self.freeRunCall.start(autoRateSpin.value(), now=True)
                    self.freeRunStatus = True

            freeButton = QtGui.QPushButton("start auto")
            freeButton.clicked.connect(freeRun)
            autoRunLayout.addWidget(freeButton)

            def updateAutoRate():
                if self.freeRunStatus:
                    self.freeRunCall.stop()
                    self.freeRunCall.start(autoRateSpin.value(), now=True)

            autoRateSpin = QtGui.QDoubleSpinBox()
            autoRateSpin.setRange(0.1, 10000.0)
            autoRateSpin.setValue(0.5)
            autoRateSpin.setSuffix("s")
            autoRateSpin.setSingleStep(0.1)
            autoRateSpin.valueChanged.connect(updateAutoRate)
            autoRunLayout.addWidget(autoRateSpin)

            capLayout.addLayout(autoRunLayout)

            cpLayout.addWidget(LabelWidget("capture", capLayout))

            # define the cursor/analysis controls
            curLayout = QtGui.QVBoxLayout()
            cpLayout.addWidget(LabelWidget("analysis", curLayout))

            self.cursorVert = InfiniteLine(
                pos=self.wave[NUM_PIXELS / 2], angle=90, pen=mkPen("g", width=0.5), movable=True
            )
            self.cursorHori = InfiniteLine(pos=0, angle=0, pen=mkPen("g", width=0.5), movable=True)
            self.plotWidget.addItem(self.cursorVert)
            self.plotWidget.addItem(self.cursorHori)

            vertLayout = QtGui.QHBoxLayout()
            vertName = QtGui.QLabel()
            vertName.setText("wavelength: ")
            vertLayout.addWidget(vertName)
            vertLabel = QtGui.QLabel()
            vertLabel.setText(str(round(self.cursorVert.pos()[0], 2)))
            vertLayout.addWidget(vertLabel)
            curLayout.addLayout(vertLayout)

            horiLayout = QtGui.QHBoxLayout()
            horiName = QtGui.QLabel()
            horiName.setText("intensity: ")
            horiLayout.addWidget(horiName)
            horiLabel = QtGui.QLabel()
            horiLabel.setText(str(round(self.cursorHori.pos()[0], 2)))
            horiLayout.addWidget(horiLabel)
            curLayout.addLayout(horiLayout)

            # define the acquisition controls
            acqLayout = QtGui.QVBoxLayout()
            cpLayout.addWidget(LabelWidget("acquisition", acqLayout))

            # integration
            integLayout = QtGui.QHBoxLayout()
            acqLayout.addLayout(integLayout)

            integTimeLabel = QtGui.QLabel()
            integTimeLabel.setText("integration: ")
            integLayout.addWidget(integTimeLabel)

            def integTimeUpdate():
                newTime = integTimeSpin.value()
                self.client.setIntegrationTime(newTime)

            integTimeSpin = QtGui.QDoubleSpinBox()
            integTimeSpin.setRange(0.001, 10)
            integTimeSpin.setDecimals(3)
            integTimeSpin.setValue(0.100)
            integTimeSpin.setSingleStep(0.05)
            integTimeSpin.setSuffix("s")
            integTimeSpin.editingFinished.connect(integTimeUpdate)
            integLayout.addWidget(integTimeSpin)

            # averaging
            avgLayout = QtGui.QHBoxLayout()
            acqLayout.addLayout(avgLayout)

            avgLabel = QtGui.QLabel()
            avgLabel.setText("averaging: ")
            avgLayout.addWidget(avgLabel)

            def avgUpdate():
                self.numberToAverage = avgSpin.value()

            avgSpin = QtGui.QSpinBox()
            avgSpin.setRange(1, 10000)
            avgSpin.setValue(1)
            avgSpin.valueChanged.connect(avgUpdate)
            avgLayout.addWidget(avgSpin)

            # dark spectrum
            darkLayout = QtGui.QHBoxLayout()
            acqLayout.addLayout(darkLayout)

            @inlineCallbacks
            def getDark():
                resetDark()
                self.gettingDark = True
                self.numberAcquired = 0
                wasInAuto = self.freeRunStatus
                if self.freeRunStatus:
                    freeRun()  # if in auto mode, stop it
                self.specProcessed = np.zeros(NUM_PIXELS)
                for specCount in range(self.numberToAverage):
                    yield capture()
                self.darkSpectrum = self.specProcessed
                self.specProcessed = np.zeros(NUM_PIXELS)
                if wasInAuto:
                    freeRun()
                self.numberAcquired = 0
                self.gettingDark = False

            darkSpecButton = QtGui.QPushButton("dark")
            darkSpecButton.clicked.connect(getDark)
            darkLayout.addWidget(darkSpecButton)

            def resetDark():
                self.darkSpectrum = np.zeros(NUM_PIXELS)
                self.specProcessed = np.zeros(NUM_PIXELS)

            resetDarkButton = QtGui.QPushButton("reset")
            resetDarkButton.clicked.connect(resetDark)
            darkLayout.addWidget(resetDarkButton)

            # define the timestamp panel
            self.timestamp = QtGui.QLabel()
            self.timestamp.setText("last update: never")
            self.timestamp.setAlignment(QtCore.Qt.AlignCenter)
            fullLayout.addWidget(self.timestamp)

        onInit()

    def refresh(self):
        time.sleep(0.5)
        self.update_plot()
        self.refresh()

    def closeEvent(self, event):
        reactor.stop()
        event.accept()
Example #14
0
class SpectrogramWindow(QWidget):
    """
    This is the class for the spectrogram window
    """
    def __init__(self, station_list):
        super(QWidget, self).__init__()
        self.layout = QGridLayout(self)
        self.station_list = station_list
        self.hidden = False

        self.spectrogram_1 = PlotWidget(self)
        self.spectrogram_1.setFixedWidth(400)
        self.spectrogram_1.setFixedHeight(550)
        self.spectrogram_2 = PlotWidget(self)
        self.spectrogram_2.setFixedWidth(400)

        self.station_box_1 = QComboBox(self)
        self.station_box_2 = QComboBox(self)

        self.waiting_traces = [None, None]
        self.waiting_p_picks = [None, None]
        self.filter_stats = FilterStats(True)

        self.spectrogram_threads = [None, None]
        self.spectrogram_threads[0] = SpectrogramCalculatorThread(
            self.filter_stats, 0)
        self.spectrogram_threads[0].signal.connect(self.plotSpectrogram)
        self.spectrogram_threads[1] = SpectrogramCalculatorThread(
            self.filter_stats, 1)
        self.spectrogram_threads[1].signal.connect(self.plotSpectrogram)

        self.filter_widget = FilterWidget(self, self.filter_stats)

        self.layout.addWidget(self.spectrogram_1, 0, 0, 1, 2)
        self.layout.addWidget(self.spectrogram_2, 0, 2, 1, 2)
        self.layout.addWidget(self.station_box_1, 1, 0)
        self.layout.addWidget(self.station_box_2, 1, 2)
        self.layout.addWidget(self.filter_widget, 2, 0)

        self.station_box_1.activated.connect(self.replotSpectrogram1)
        self.station_box_2.activated.connect(self.replotSpectrogram2)
        self.setStationsFromNewEvent()

    def closeEvent(self, event):
        """
        This function will be called when the spectrogramWindow Closes
        """
        self.hidden = True

    def replotSpectrogram1(self):
        """
        This function is to be used only by station_box_1
        """
        self.getTraceForSpectrogramThread(0)

    def replotSpectrogram2(self):
        """
        This function is to be used only by station_box_2
        """
        self.getTraceForSpectrogramThread(1)

    def getTraceForSpectrogramThread(self, spectrogram_id):
        """
        Fetch correct trace for the spectrogram_thread. Choose this from the value from station_box_1 or station_box_2
        """
        station_name = None
        if spectrogram_id == 0:
            station_name = self.station_box_1.currentText()
        elif spectrogram_id == 1:
            station_name = self.station_box_2.currentText()

        trace, p_pick = self.station_list.getCurrentTraceAndPPickForStation(
            station_name)

        if trace is None:
            return

        self.calculateSpectrogram(trace, p_pick, spectrogram_id)

    def setStationsFromNewEvent(self):
        """
        Set the focused event to spectrogram window
        """
        stations = [x[0] for x in self.station_list.getOrderedStationList()]

        if len(stations) < 2:
            return

        self.station_box_1.clear()
        self.station_box_2.clear()

        for stat in stations:
            self.station_box_1.addItem(stat)
            self.station_box_2.addItem(stat)

        self.station_box_1.setCurrentIndex(0)
        self.station_box_2.setCurrentIndex(1)

        self.getTraceForSpectrogramThread(0)
        self.getTraceForSpectrogramThread(1)

    def filterChange(self):
        """
        Function that is called when the filters have been changed
        """
        self.getTraceForSpectrogramThread(0)
        self.getTraceForSpectrogramThread(1)

    def calculateSpectrogram(self, waveform_trace, p_pick, spectrogram_id):
        """
        Function for calculating a spectrogram
        """
        if self.spectrogram_threads[spectrogram_id].running:
            self.waiting_traces[spectrogram_id] = waveform_trace
            self.waiting_p_picks[spectrogram_id] = p_pick
            self.spectrogram_threads[spectrogram_id].interrupt = True
        else:
            self.spectrogram_threads[
                spectrogram_id].waveform_trace = waveform_trace
            self.spectrogram_threads[spectrogram_id].p_pick = p_pick
            self.spectrogram_threads[spectrogram_id].running = True
            self.spectrogram_threads[spectrogram_id].start()

    def plotSpectrogram(self, return_values):
        """
        Function for plotting a spectrogram
        """
        spectrogram_id, spectrogram, sample_frequencies, sample_times = return_values
        print("Window {0} done".format(spectrogram_id))

        self.spectrogram_threads[spectrogram_id].running = False
        self.spectrogram_threads[spectrogram_id].interrupt = False

        if self.waiting_traces[spectrogram_id] is not None:
            self.calculateSpectrogram(self.waiting_traces[spectrogram_id],
                                      self.waiting_p_picks[spectrogram_id],
                                      spectrogram_id)
            self.waiting_traces[spectrogram_id] = None
            self.waiting_p_picks[spectrogram_id] = None

        if spectrogram is None:
            return

        if spectrogram_id == 0:
            self.spectrogram_1.clear()
            self.spectrogram_1.addItem(spectrogram)
        elif spectrogram_id == 1:
            self.spectrogram_2.clear()
            self.spectrogram_2.addItem(spectrogram)
Example #15
0
class RatingView(QtWidgets.QWidget):
    _ratings_ready = QtCore.pyqtSignal(object, object)
    _node_ratings_ready = QtCore.pyqtSignal(object)

    def __init__(self):
        super().__init__()

        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)

        self._cubeable_plot = PlotWidget(
            axisItems={'bottom': TimeAxisItem(orientation='bottom')})
        self._nodes_plot = PlotWidget(
            axisItems={'bottom': TimeAxisItem(orientation='bottom')})

        self._splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
        self._splitter.setStretchFactor(0, 1)
        self._splitter.setStretchFactor(1, 1)

        layout.addWidget(self._splitter)

        self._splitter.addWidget(self._cubeable_plot)
        self._splitter.addWidget(self._nodes_plot)

        self._display_target: t.Optional[t.Tuple[int,
                                                 CardboardCubeable]] = None

        self._ratings_ready.connect(self._set_cubeable_ratings)
        self._node_ratings_ready.connect(self._set_nodes_ratings)
        LOGIN_CONTROLLER.login_success.connect(self._on_login)

    @classmethod
    def _get_color(cls, n: int = 0) -> QColor:
        return QColor(100 + (n * 70) % 155, 100 + ((n + 1) * 50) % 155,
                      100 + ((n + 2) * 40) % 155)

    @functools.lru_cache(maxsize=128)
    def _get_rating_points(
        self, release_id: int, cardboard_cubeable: CardboardCubeable
    ) -> Promise[t.Sequence[RatingPoint]]:
        return Context.cube_api_client.rating_history_for_cardboard_cubeable(
            release_id,
            cardboard_cubeable,
        )

    @functools.lru_cache(maxsize=256)
    def _get_node_rating_points(
            self, release_id: int,
            node: CardboardNodeChild) -> Promise[t.Sequence[NodeRatingPoint]]:
        return Context.cube_api_client.rating_history_for_node(
            release_id,
            node,
        ).then(lambda ratings: (node, ratings))

    def _on_login(self, *args, **kwargs) -> None:
        self._get_rating_points.cache_clear()
        self._get_node_rating_points.cache_clear()

    def _set_cubeable_ratings(self, cardboard_cubeable: CardboardCubeable,
                              ratings: t.Sequence[RatingPoint]) -> None:
        self._cubeable_plot.clear()
        data_item = self._cubeable_plot.plot(
            [p.rating_map.created_at.timestamp() for p in ratings],
            [p.rating for p in ratings])
        legend = self._cubeable_plot.addLegend(labelTextSize='15pt')
        legend.addItem(
            data_item, cardboard_cubeable.name if isinstance(
                cardboard_cubeable, Cardboard) else
            cardboard_cubeable.description)
        self._cubeable_plot.getPlotItem().enableAutoRange()

    def _set_nodes_ratings(
        self, ratings: t.Iterable[t.Tuple[CardboardNodeChild,
                                          t.Sequence[NodeRatingPoint]]]
    ) -> None:
        self._nodes_plot.show()
        self._nodes_plot.clear()
        legend = self._nodes_plot.addLegend(labelTextSize='15pt')

        for idx, (node_child, ratings) in enumerate(ratings):
            data_item = self._nodes_plot.plot(
                [p.rating_map.created_at.timestamp() for p in ratings],
                [p.rating for p in ratings],
                pen=mkPen(color=self._get_color(idx)),
            )
            legend.addItem(
                data_item,
                node_child.name if isinstance(node_child, Cardboard) else
                node_child.get_minimal_string())
        self._nodes_plot.getPlotItem().enableAutoRange()

    def on_focus_event(self, focus_event: FocusEvent) -> None:
        if not self.isVisible(
        ) or not focus_event.release_id or Context.focus_card_frozen:
            return

        cardboard_cubeable = focusable_as_cardboards(focus_event.focusable)

        display_target = (focus_event.release_id, cardboard_cubeable)
        if display_target == self._display_target:
            return
        self._display_target = display_target

        promise = self._get_rating_points(focus_event.release_id,
                                          cardboard_cubeable)

        if promise.is_pending:
            promise.then(lambda ratings: self._ratings_ready.emit(
                cardboard_cubeable, ratings)).catch(logging.warning)
        elif promise.is_fulfilled:
            self._set_cubeable_ratings(cardboard_cubeable, promise.get())

        if isinstance(
                cardboard_cubeable, CardboardTrap
        ) and cardboard_cubeable.intention_type == IntentionType.GARBAGE:
            promise = Promise.all([
                self._get_node_rating_points(focus_event.release_id, node) for
                node in cardboard_cubeable.node.children.distinct_elements()
            ])
            if promise.is_pending:
                promise.then(self._node_ratings_ready.emit).catch(
                    logging.warning)
            elif promise.is_fulfilled:
                self._set_nodes_ratings(promise.get())
        else:
            self._nodes_plot.hide()
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)
        self._plot_widget.getPlotItem().sigRangeChanged.connect(self.limits_changed)

        self._curves = {}
        self._current_vline = None

    def add_curve(self, curve_id, curve_name, curve_color=QColor(Qt.blue), markers_on=False):
        pen = mkPen(curve_color, width=1)
        symbol = "o"
        symbolPen = mkPen(QColor(Qt.black))
        symbolBrush = mkBrush(curve_color)
        # this adds the item to the plot and legend
        if markers_on:
            plot = self._plot_widget.plot(name=curve_name, pen=pen, symbol=symbol, symbolPen=symbolPen, symbolBrush=symbolBrush, symbolSize=4)
        else:
            plot = self._plot_widget.plot(name=curve_name, pen=pen)
        self._curves[curve_id] = plot

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.removeItem(self._curves[curve_id])
            del self._curves[curve_id]
            self._update_legend()
           
    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.addItem(curve)
        if self._current_vline:
            self._plot_widget.addItem(self._current_vline)
 
    def redraw(self):
        pass

    def set_values(self, curve_id, data_x, data_y):
        curve = self._curves[curve_id]
        curve.setData(data_x, data_y)

    def vline(self, x, color):
        if self._current_vline:
            self._plot_widget.removeItem(self._current_vline)
        self._current_vline = self._plot_widget.addLine(x=x, pen=color)

    def set_xlim(self, limits):
        # TODO: this doesn't seem to handle fast updates well
        self._plot_widget.setXRange(limits[0], limits[1], padding=0)

    def set_ylim(self, limits):
        self._plot_widget.setYRange(limits[0], limits[1], padding=0)

    def get_xlim(self):
        x_range, _ = self._plot_widget.viewRange()
        return x_range

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
Example #17
0
class UIMainWindow(object):
    labels: List[QtWidgets.QLabel]
    operations_amount_fields: List[QtWidgets.QSpinBox]
    additional_operations_checkboxes: List[QtWidgets.QCheckBox]
    procedural_times_output_fields: List[QtWidgets.QLineEdit]
    oop_times_output_fields: List[QtWidgets.QLineEdit]

    def __init__(self):
        self.labels = []
        self.operations_amount_fields = []
        self.additional_operations_checkboxes = []
        self.procedural_times_output_fields = []
        self.oop_times_output_fields = []

        self.thread_pool = QThreadPool()
        self.thread_pool.setMaxThreadCount(1)

        self.main_operations_number = 0
        self.execution_times = [[0], [0]]

    def setup_ui(self, MainWindow):
        font_size_9 = QtGui.QFont()
        font_size_9.setPointSize(9)

        font_size_10 = QtGui.QFont()
        font_size_10.setPointSize(10)

        font_size_12 = QtGui.QFont()
        font_size_12.setPointSize(12)

        self.central_widget = QtWidgets.QWidget(MainWindow)
        self.central_widget.setObjectName("central_widget")

        self.labels.insert(0, QtWidgets.QLabel(self.central_widget))
        self.labels[0].setObjectName("label_operation_amount")
        self.labels[0].setGeometry(QtCore.QRect(10, 40, 91, 16))
        self.labels[0].setText(
            QtCore.QCoreApplication.translate("MainWindow", "Ilość operacji"))

        self.labels.insert(1, QtWidgets.QLabel(self.central_widget))
        self.labels[1].setObjectName("label_operations_select")
        self.labels[1].setGeometry(QtCore.QRect(110, 40, 141, 16))
        self.labels[1].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Wybór operacji do wykonania"))

        self.labels.insert(2, QtWidgets.QLabel(self.central_widget))
        self.labels[2].setObjectName("label_elapsed_time")
        self.labels[2].setGeometry(QtCore.QRect(290, 10, 231, 21))
        self.labels[2].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Czasy wykonania (milisekundy)"))
        self.labels[2].setFont(font_size_12)

        self.labels.insert(3, QtWidgets.QLabel(self.central_widget))
        self.labels[3].setObjectName("label_result_console")
        self.labels[3].setGeometry(QtCore.QRect(10, 310, 111, 16))
        self.labels[3].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Konsola wynikowa"))
        self.labels[3].setFont(font_size_10)

        self.labels.insert(4, QtWidgets.QLabel(self.central_widget))
        self.labels[4].setObjectName("label_time_chart_by_approach")
        self.labels[4].setGeometry(QtCore.QRect(550, 10, 321, 21))
        self.labels[4].setText(
            QtCore.QCoreApplication.translate(
                "MainWindow",
                "Wykres czasu działania programu w zależności od podejścia"))
        self.labels[4].setFont(font_size_9)

        self.labels.insert(5, QtWidgets.QLabel(self.central_widget))
        self.labels[5].setObjectName("label_operations_amount")
        self.labels[5].setGeometry(QtCore.QRect(550, 260, 321, 30))
        self.labels[5].setAlignment(QtCore.Qt.AlignCenter)
        self.labels[5].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Ilość operacji (w tysiącach)"))
        self.labels[5].setFont(font_size_10)

        self.labels.insert(6, VerticalLabel(self.central_widget))
        self.labels[6].setObjectName("label_chart_elapsed_time")
        self.labels[6].setGeometry(QtCore.QRect(520, 40, 30, 221))
        self.labels[6].setLayoutDirection(QtCore.Qt.LeftToRight)
        self.labels[6].setAutoFillBackground(False)
        self.labels[6].setScaledContents(False)
        self.labels[6].setWordWrap(False)
        self.labels[6].setOpenExternalLinks(False)
        self.labels[6].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Czas wykonania (milisekundy)"))
        self.labels[6].setFont(font_size_10)

        self.labels.insert(7, QtWidgets.QLabel(self.central_widget))
        self.labels[7].setObjectName("label_input_data")
        self.labels[7].setGeometry(QtCore.QRect(10, 10, 121, 21))
        self.labels[7].setText(
            QtCore.QCoreApplication.translate("MainWindow", "Dane wejściowe"))
        self.labels[7].setFont(font_size_12)

        self.labels.insert(8, QtWidgets.QLabel(self.central_widget))
        self.labels[8].setObjectName("label_procedural")
        self.labels[8].setGeometry(QtCore.QRect(290, 40, 107, 26))
        self.labels[8].setAlignment(QtCore.Qt.AlignCenter)
        self.labels[8].setStyleSheet("background-color: #f00")
        self.labels[8].setText(
            QtCore.QCoreApplication.translate("MainWindow", "Proceduralnie"))

        self.labels.insert(9, QtWidgets.QLabel(self.central_widget))
        self.labels[9].setObjectName("label_oop")
        self.labels[9].setGeometry(QtCore.QRect(403, 40, 108, 26))
        self.labels[9].setAlignment(QtCore.Qt.AlignCenter)
        self.labels[9].setStyleSheet("background-color: #0ff")
        self.labels[9].setText(
            QtCore.QCoreApplication.translate("MainWindow", "Obiektowo"))

        self.vertical_line = QtWidgets.QFrame(self.central_widget)
        self.vertical_line.setObjectName("vertical_line")
        self.vertical_line.setGeometry(QtCore.QRect(260, 10, 21, 271))
        self.vertical_line.setFrameShape(QtWidgets.QFrame.VLine)
        self.vertical_line.setFrameShadow(QtWidgets.QFrame.Sunken)

        self.horizontal_line = QtWidgets.QFrame(self.central_widget)
        self.horizontal_line.setObjectName("horizontal_line")
        self.horizontal_line.setGeometry(QtCore.QRect(10, 290, 861, 20))
        self.horizontal_line.setFrameShape(QtWidgets.QFrame.HLine)
        self.horizontal_line.setFrameShadow(QtWidgets.QFrame.Sunken)

        self.operations_amount_widget = QtWidgets.QWidget(self.central_widget)
        self.operations_amount_widget.setGeometry(QtCore.QRect(
            10, 60, 91, 171))
        self.operations_amount_widget.setObjectName("operations_amount_widget")

        self.operations_amount_layout = QtWidgets.QVBoxLayout(
            self.operations_amount_widget)
        self.operations_amount_layout.setContentsMargins(0, 0, 0, 0)
        self.operations_amount_layout.setObjectName("operations_amount_layout")

        self.operations_amount_fields.insert(
            0, QtWidgets.QSpinBox(self.operations_amount_widget))
        self.operations_amount_fields[0].setObjectName(
            "operations_amount_field_0")
        self.operations_amount_fields[0].setRange(10000, 1000000)
        self.operations_amount_fields[0].setSingleStep(1000)
        self.operations_amount_fields[0].setValue(15000)
        self.operations_amount_layout.addWidget(
            self.operations_amount_fields[0])

        self.operations_amount_fields.insert(
            1, QtWidgets.QSpinBox(self.operations_amount_widget))
        self.operations_amount_fields[1].setObjectName(
            "operations_amount_field_1")
        self.operations_amount_fields[1].setRange(10000, 1000000)
        self.operations_amount_fields[1].setSingleStep(1000)
        self.operations_amount_fields[1].setValue(50000)
        self.operations_amount_layout.addWidget(
            self.operations_amount_fields[1])

        self.operations_amount_fields.insert(
            2, QtWidgets.QSpinBox(self.operations_amount_widget))
        self.operations_amount_fields[2].setObjectName(
            "operations_amount_field_2")
        self.operations_amount_fields[2].setRange(10000, 1000000)
        self.operations_amount_fields[2].setSingleStep(1000)
        self.operations_amount_fields[2].setValue(150000)
        self.operations_amount_layout.addWidget(
            self.operations_amount_fields[2])

        self.operations_amount_fields.insert(
            3, QtWidgets.QSpinBox(self.operations_amount_widget))
        self.operations_amount_fields[3].setObjectName(
            "operations_amount_field_3")
        self.operations_amount_fields[3].setRange(10000, 1000000)
        self.operations_amount_fields[3].setSingleStep(1000)
        self.operations_amount_fields[3].setValue(300000)
        self.operations_amount_layout.addWidget(
            self.operations_amount_fields[3])

        self.operations_amount_fields.insert(
            4, QtWidgets.QSpinBox(self.operations_amount_widget))
        self.operations_amount_fields[4].setObjectName(
            "operations_amount_field_4")
        self.operations_amount_fields[4].setRange(10000, 1000000)
        self.operations_amount_fields[4].setSingleStep(1000)
        self.operations_amount_fields[4].setValue(1000000)
        self.operations_amount_layout.addWidget(
            self.operations_amount_fields[4])

        self.additional_operations_widget = QtWidgets.QWidget(
            self.central_widget)
        self.additional_operations_widget.setObjectName(
            "additional_operations_widget")
        self.additional_operations_widget.setGeometry(
            QtCore.QRect(110, 60, 141, 171))

        self.additional_operations_layout = QtWidgets.QVBoxLayout(
            self.additional_operations_widget)
        self.additional_operations_layout.setObjectName(
            "additional_operations_layout")
        self.additional_operations_layout.setContentsMargins(0, 0, 0, 0)

        self.additional_operations_checkboxes.insert(
            0, QtWidgets.QCheckBox(self.additional_operations_widget))
        self.additional_operations_checkboxes[0].setObjectName(
            "additional_operations_checkbox_0")
        self.additional_operations_checkboxes[0].setEnabled(False)
        self.additional_operations_checkboxes[0].setChecked(True)
        self.additional_operations_checkboxes[0].setText(
            QtCore.QCoreApplication.translate("MainWindow", "Operacji"))
        self.additional_operations_layout.addWidget(
            self.additional_operations_checkboxes[0])

        self.additional_operations_checkboxes.insert(
            1, QtWidgets.QCheckBox(self.additional_operations_widget))
        self.additional_operations_checkboxes[1].setObjectName(
            "additional_operations_checkbox_1")
        self.additional_operations_checkboxes[1].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Operacji dodatkowych"))
        self.additional_operations_layout.addWidget(
            self.additional_operations_checkboxes[1])

        self.additional_operations_checkboxes.insert(
            2, QtWidgets.QCheckBox(self.additional_operations_widget))
        self.additional_operations_checkboxes[2].setObjectName(
            "additional_operations_checkbox_2")
        self.additional_operations_checkboxes[2].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Operacji dodatkowych"))
        self.additional_operations_layout.addWidget(
            self.additional_operations_checkboxes[2])

        self.additional_operations_checkboxes.insert(
            3, QtWidgets.QCheckBox(self.additional_operations_widget))
        self.additional_operations_checkboxes[3].setObjectName(
            "additional_operations_checkbox_3")
        self.additional_operations_checkboxes[3].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Operacji dodatkowych"))
        self.additional_operations_layout.addWidget(
            self.additional_operations_checkboxes[3])

        self.additional_operations_checkboxes.insert(
            4, QtWidgets.QCheckBox(self.additional_operations_widget))
        self.additional_operations_checkboxes[4].setObjectName(
            "additional_operations_checkbox_4")
        self.additional_operations_checkboxes[4].setText(
            QtCore.QCoreApplication.translate("MainWindow",
                                              "Operacji dodatkowych"))
        self.additional_operations_layout.addWidget(
            self.additional_operations_checkboxes[4])

        self.operation_times_widget = QtWidgets.QWidget(self.central_widget)
        self.operation_times_widget.setObjectName("operation_times_widget")
        self.operation_times_widget.setGeometry(QtCore.QRect(
            290, 72, 221, 171))

        self.operation_times_layout = QtWidgets.QHBoxLayout(
            self.operation_times_widget)
        self.operation_times_layout.setObjectName("operation_times_layout")
        self.operation_times_layout.setContentsMargins(0, 0, 0, 0)

        self.procedural_times_output_layout = QtWidgets.QVBoxLayout()
        self.procedural_times_output_layout.setObjectName(
            "procedural_times_output_layout")

        self.procedural_times_output_fields.insert(
            0, QtWidgets.QLineEdit(self.operation_times_widget))
        self.procedural_times_output_fields[0].setObjectName(
            "procedural_time_output_fields_0")
        self.procedural_times_output_fields[0].setAlignment(
            QtCore.Qt.AlignCenter)
        self.procedural_times_output_fields[0].setReadOnly(True)
        self.procedural_times_output_fields[0].setText("-")
        self.procedural_times_output_layout.addWidget(
            self.procedural_times_output_fields[0])

        self.procedural_times_output_fields.insert(
            1, QtWidgets.QLineEdit(self.operation_times_widget))
        self.procedural_times_output_fields[1].setObjectName(
            "procedural_time_output_fields_1")
        self.procedural_times_output_fields[1].setAlignment(
            QtCore.Qt.AlignCenter)
        self.procedural_times_output_fields[1].setReadOnly(True)
        self.procedural_times_output_fields[1].setText("-")
        self.procedural_times_output_layout.addWidget(
            self.procedural_times_output_fields[1])

        self.procedural_times_output_fields.insert(
            2, QtWidgets.QLineEdit(self.operation_times_widget))
        self.procedural_times_output_fields[2].setObjectName(
            "procedural_time_output_fields_2")
        self.procedural_times_output_fields[2].setAlignment(
            QtCore.Qt.AlignCenter)
        self.procedural_times_output_fields[2].setReadOnly(True)
        self.procedural_times_output_fields[2].setText("-")
        self.procedural_times_output_layout.addWidget(
            self.procedural_times_output_fields[2])

        self.procedural_times_output_fields.insert(
            3, QtWidgets.QLineEdit(self.operation_times_widget))
        self.procedural_times_output_fields[3].setObjectName(
            "procedural_time_output_fields_3")
        self.procedural_times_output_fields[3].setAlignment(
            QtCore.Qt.AlignCenter)
        self.procedural_times_output_fields[3].setReadOnly(True)
        self.procedural_times_output_fields[3].setText("-")
        self.procedural_times_output_layout.addWidget(
            self.procedural_times_output_fields[3])

        self.procedural_times_output_fields.insert(
            4, QtWidgets.QLineEdit(self.operation_times_widget))
        self.procedural_times_output_fields[4].setObjectName(
            "procedural_time_output_fields_4")
        self.procedural_times_output_fields[4].setAlignment(
            QtCore.Qt.AlignCenter)
        self.procedural_times_output_fields[4].setReadOnly(True)
        self.procedural_times_output_fields[4].setText("-")
        self.procedural_times_output_layout.addWidget(
            self.procedural_times_output_fields[4])

        self.operation_times_layout.addLayout(
            self.procedural_times_output_layout)

        self.oop_times_output_layout = QtWidgets.QVBoxLayout()
        self.oop_times_output_layout.setObjectName("oop_times_output_layout")

        self.oop_times_output_fields.insert(
            0, QtWidgets.QLineEdit(self.operation_times_widget))
        self.oop_times_output_fields[0].setObjectName("timeOutputField0")
        self.oop_times_output_fields[0].setAlignment(QtCore.Qt.AlignCenter)
        self.oop_times_output_fields[0].setReadOnly(True)
        self.oop_times_output_fields[0].setText("-")
        self.oop_times_output_layout.addWidget(self.oop_times_output_fields[0])

        self.oop_times_output_fields.insert(
            1, QtWidgets.QLineEdit(self.operation_times_widget))
        self.oop_times_output_fields[1].setObjectName("timeOutputField1")
        self.oop_times_output_fields[1].setAlignment(QtCore.Qt.AlignCenter)
        self.oop_times_output_fields[1].setReadOnly(True)
        self.oop_times_output_fields[1].setText("-")
        self.oop_times_output_layout.addWidget(self.oop_times_output_fields[1])

        self.oop_times_output_fields.insert(
            2, QtWidgets.QLineEdit(self.operation_times_widget))
        self.oop_times_output_fields[2].setObjectName("timeOutputField2")
        self.oop_times_output_fields[2].setAlignment(QtCore.Qt.AlignCenter)
        self.oop_times_output_fields[2].setReadOnly(True)
        self.oop_times_output_fields[2].setText("-")
        self.oop_times_output_layout.addWidget(self.oop_times_output_fields[2])

        self.oop_times_output_fields.insert(
            3, QtWidgets.QLineEdit(self.operation_times_widget))
        self.oop_times_output_fields[3].setObjectName("timeOutputField3")
        self.oop_times_output_fields[3].setAlignment(QtCore.Qt.AlignCenter)
        self.oop_times_output_fields[3].setReadOnly(True)
        self.oop_times_output_fields[3].setText("-")
        self.oop_times_output_layout.addWidget(self.oop_times_output_fields[3])

        self.oop_times_output_fields.insert(
            4, QtWidgets.QLineEdit(self.operation_times_widget))
        self.oop_times_output_fields[4].setObjectName("timeOutputField4")
        self.oop_times_output_fields[4].setAlignment(QtCore.Qt.AlignCenter)
        self.oop_times_output_fields[4].setReadOnly(True)
        self.oop_times_output_fields[4].setText("-")
        self.oop_times_output_layout.addWidget(self.oop_times_output_fields[4])

        self.operation_times_layout.addLayout(self.oop_times_output_layout)

        self.calculate_button = QtWidgets.QPushButton(self.central_widget)
        self.calculate_button.setObjectName("calculate_button")
        self.calculate_button.setGeometry(QtCore.QRect(10, 240, 241, 41))
        self.calculate_button.setText(
            QtCore.QCoreApplication.translate("MainWindow", "Oblicz"))
        self.calculate_button.clicked.connect(lambda: self.count())

        self.chart = PlotWidget(self.central_widget)
        self.chart.setObjectName("chart")
        self.chart.setGeometry(QtCore.QRect(550, 40, 321, 221))
        self.chart.showGrid(x=True, y=True)

        self.console = QtWidgets.QTextBrowser(self.central_widget)
        self.console.setObjectName("console")
        self.console.setGeometry(QtCore.QRect(10, 330, 861, 91))
        self.console.setAutoFillBackground(False)

        MainWindow.setObjectName("MainWindow")
        MainWindow.setFixedSize(880, 430)
        MainWindow.setCentralWidget(self.central_widget)
        MainWindow.setWindowTitle(
            QtCore.QCoreApplication.translate(
                "MainWindow",
                "Porównanie czasów operacji wykonanych proceduralnie i obiektowo (M. Liber, P. Lyschik, 2020)"
            ))
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def disable_ui(self):
        self.calculate_button.setEnabled(False)

        for field in self.operations_amount_fields:
            field.setEnabled(False)

        for check_box in self.additional_operations_checkboxes[1:]:
            check_box.setEnabled(False)

    def enable_ui(self):
        self.calculate_button.setEnabled(True)

        for field in self.operations_amount_fields:
            field.setEnabled(True)

        for check_box in self.additional_operations_checkboxes[1:]:
            check_box.setEnabled(True)

    def clear_time_tables(self):
        for field in self.procedural_times_output_fields:
            field.setText("-")

        for field in self.oop_times_output_fields:
            field.setText("-")

    def is_calculation_finished(self):
        for element in self.procedural_times_output_fields[:self.
                                                           main_operations_number
                                                           - 1]:
            if element.text() == "-":
                return False

        for element in self.oop_times_output_fields[:self.
                                                    main_operations_number -
                                                    1]:
            if element.text() == "-":
                return False

        return True

    def clear_chart(self):
        self.chart.clear()

    def clear_times(self):
        self.execution_times = [[0], [0]]

    def clear_console(self):
        self.console.clear()

    def clear_data(self):
        self.clear_time_tables()
        self.clear_chart()
        self.clear_times()
        self.clear_console()

    def console_print_line(self, message):
        date_time_now = datetime.datetime.now()
        current_date_time = date_time_now.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]

        self.console.append("[{0}] {1}".format(current_date_time, message))

    def print_execution_time(self, operation_type, operations_number,
                             execution_time):
        self.console_print_line(
            "Wykonanie {0:,} operacji w podejściu {1} zajęło {2} ms.".format(
                operations_number, operation_type,
                execution_time).replace(',', ' '))

    def get_data(self):
        data_table = [0, self.operations_amount_fields[0].value()]

        if self.additional_operations_checkboxes[1].isChecked():
            data_table.append(self.operations_amount_fields[1].value())

        if self.additional_operations_checkboxes[2].isChecked():
            data_table.append(self.operations_amount_fields[2].value())

        if self.additional_operations_checkboxes[3].isChecked():
            data_table.append(self.operations_amount_fields[3].value())

        if self.additional_operations_checkboxes[4].isChecked():
            data_table.append(self.operations_amount_fields[4].value())

        return data_table

    def count(self):
        self.disable_ui()
        self.clear_data()
        self.console_print_line("Rozpoczęto obliczenia.")

        number_of_operations = self.get_data()
        self.main_operations_number = len(number_of_operations)

        for i in range(1, len(number_of_operations)):
            self.multi_thread_execute(number_of_operations[i],
                                      operation_procedural)
            self.multi_thread_execute(number_of_operations[i],
                                      operation_objective)

    def update_procedural(self, result):
        self.execution_times[0].append(result[0])
        self.procedural_times_output_fields[len(self.execution_times[0]) -
                                            2].setText(str(result[0]))
        self.update_plots()
        self.print_execution_time("proceduralnym", result[1],
                                  self.execution_times[0][-1])

        if self.is_calculation_finished():
            self.console_print_line("Zakończono obliczenia.")
            self.enable_ui()

    def update_objective(self, result):
        self.execution_times[1].append(result[0])
        self.oop_times_output_fields[len(self.execution_times[1]) - 2].setText(
            str(result[0]))
        self.update_plots()
        self.print_execution_time("obiektowym", result[1],
                                  self.execution_times[1][-1])

        if self.is_calculation_finished():
            self.console_print_line("Zakończono obliczenia.")
            self.enable_ui()

    def update_plots(self):
        chart_data_procedural = self.prepare_chart_data(0)

        self.chart.plot(chart_data_procedural[0],
                        chart_data_procedural[1],
                        name='Proceduralnie',
                        pen=(255, 0, 0),
                        symbol='o',
                        symbolSize=5,
                        symbolPen=(255, 0, 0),
                        symbolBrush=(255, 0, 0))

        chart_data_oop = self.prepare_chart_data(1)

        self.chart.plot(chart_data_oop[0],
                        chart_data_oop[1],
                        name='Obiektowo',
                        pen=(0, 255, 255),
                        symbol='o',
                        symbolSize=5,
                        symbolPen=(0, 255, 255),
                        symbolBrush=(0, 255, 255))

    def prepare_chart_data(self, data_id):
        number_of_operations = self.reduce_data_for_chart_by_thousand(
            self.get_data()[:len(self.execution_times[data_id])])
        times = self.execution_times[data_id]

        return self.sort_two_tables_by_first(number_of_operations, times)

    def sort_two_tables_by_first(self, sorted_table, other_table):
        while True:
            edition_flag = 0

            for i in range(len(sorted_table) - 1):
                if sorted_table[i] > sorted_table[i + 1]:
                    tmp = sorted_table[i]
                    sorted_table[i] = sorted_table[i + 1]
                    sorted_table[i + 1] = tmp

                    tmp_other = other_table[i]
                    other_table[i] = other_table[i + 1]
                    other_table[i + 1] = tmp_other

                    edition_flag += 1

            if edition_flag == 0:
                return (sorted_table, other_table)

    def reduce_data_for_chart_by_thousand(self, data):
        reduced_data = []

        for element in data:
            reduced_data.append(element / 1000)

        return reduced_data

    def multi_thread_execute(self, operations_number, operation_type):
        worker = Worker(operation_type, operations_number)

        if operation_type == operation_procedural:
            worker.signals.result.connect(self.update_procedural)
        else:
            worker.signals.result.connect(self.update_objective)

        self.thread_pool.start(worker)
Example #18
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1103, 561)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.Connect_box = QtWidgets.QGroupBox(self.centralwidget)
        self.Connect_box.setGeometry(QtCore.QRect(10, 10, 191, 121))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.Connect_box.setFont(font)
        self.Connect_box.setObjectName("Connect_box")
        self.COM = QtWidgets.QComboBox(self.Connect_box)
        self.COM.setGeometry(QtCore.QRect(50, 30, 131, 22))
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.COM.setFont(font)
        self.COM.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.COM.setObjectName("COM")
        self.COM.addItem("")
        self.COM.addItem("")
        self.COM.addItem("")
        self.COM.addItem("")
        self.COM.addItem("")
        self.COM.addItem("")
        self.connect = QtWidgets.QPushButton(self.Connect_box)
        self.connect.setGeometry(QtCore.QRect(20, 70, 151, 41))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.connect.setFont(font)
        self.connect.setObjectName("connect")
        self.label = QtWidgets.QLabel(self.Connect_box)
        self.label.setGeometry(QtCore.QRect(10, 30, 31, 21))
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.Mode_box = QtWidgets.QGroupBox(self.centralwidget)
        self.Mode_box.setGeometry(QtCore.QRect(200, 10, 481, 121))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.Mode_box.setFont(font)
        self.Mode_box.setObjectName("Mode_box")
        self.Start = QtWidgets.QPushButton(self.Mode_box)
        self.Start.setGeometry(QtCore.QRect(10, 40, 101, 51))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.Start.setFont(font)
        self.Start.setObjectName("Start")
        self.Stop = QtWidgets.QPushButton(self.Mode_box)
        self.Stop.setGeometry(QtCore.QRect(130, 40, 101, 51))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.Stop.setFont(font)
        self.Stop.setObjectName("Stop")
        self.Reset = QtWidgets.QPushButton(self.Mode_box)
        self.Reset.setGeometry(QtCore.QRect(250, 40, 101, 51))
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.Reset.setFont(font)
        self.Reset.setObjectName("Reset")
        self.draw_graph = QtWidgets.QPushButton(self.Mode_box)
        self.draw_graph.setGeometry(QtCore.QRect(370, 40, 101, 51))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.draw_graph.setFont(font)
        self.draw_graph.setObjectName("draw_graph")
        self.PIDStatus_box = QtWidgets.QGroupBox(self.centralwidget)
        self.PIDStatus_box.setGeometry(QtCore.QRect(680, 10, 411, 121))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.PIDStatus_box.setFont(font)
        self.PIDStatus_box.setObjectName("PIDStatus_box")
        self.label_6 = QtWidgets.QLabel(self.PIDStatus_box)
        self.label_6.setGeometry(QtCore.QRect(20, 30, 31, 31))
        font = QtGui.QFont()
        font.setFamily("MS Shell Dlg 2")
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.Kp_data = QtWidgets.QTextEdit(self.PIDStatus_box)
        self.Kp_data.setGeometry(QtCore.QRect(60, 30, 71, 31))
        font = QtGui.QFont()
        font.setBold(False)
        font.setWeight(50)
        self.Kp_data.setFont(font)
        self.Kp_data.setObjectName("Kp_data")
        self.label_7 = QtWidgets.QLabel(self.PIDStatus_box)
        self.label_7.setGeometry(QtCore.QRect(20, 80, 31, 31))
        font = QtGui.QFont()
        font.setFamily("MS Shell Dlg 2")
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.Ki_data = QtWidgets.QTextEdit(self.PIDStatus_box)
        self.Ki_data.setGeometry(QtCore.QRect(60, 80, 71, 31))
        font = QtGui.QFont()
        font.setBold(False)
        font.setWeight(50)
        self.Ki_data.setFont(font)
        self.Ki_data.setObjectName("Ki_data")
        self.label_8 = QtWidgets.QLabel(self.PIDStatus_box)
        self.label_8.setGeometry(QtCore.QRect(190, 30, 31, 31))
        font = QtGui.QFont()
        font.setFamily("MS Shell Dlg 2")
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.label_8.setFont(font)
        self.label_8.setObjectName("label_8")
        self.Kd_data = QtWidgets.QTextEdit(self.PIDStatus_box)
        self.Kd_data.setGeometry(QtCore.QRect(230, 30, 71, 31))
        font = QtGui.QFont()
        font.setBold(False)
        font.setWeight(50)
        self.Kd_data.setFont(font)
        self.Kd_data.setObjectName("Kd_data")
        self.label_9 = QtWidgets.QLabel(self.PIDStatus_box)
        self.label_9.setGeometry(QtCore.QRect(160, 80, 71, 31))
        font = QtGui.QFont()
        font.setFamily("MS Shell Dlg 2")
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.Setpoint_data = QtWidgets.QTextEdit(self.PIDStatus_box)
        self.Setpoint_data.setGeometry(QtCore.QRect(230, 80, 71, 31))
        font = QtGui.QFont()
        font.setBold(False)
        font.setWeight(50)
        self.Setpoint_data.setFont(font)
        self.Setpoint_data.setObjectName("Setpoint_data")
        self.send_PID = QtWidgets.QPushButton(self.PIDStatus_box)
        self.send_PID.setGeometry(QtCore.QRect(320, 80, 81, 31))
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.send_PID.setFont(font)
        self.send_PID.setObjectName("send_PID")
        self.get_PID = QtWidgets.QPushButton(self.PIDStatus_box)
        self.get_PID.setGeometry(QtCore.QRect(320, 30, 81, 31))
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.get_PID.setFont(font)
        self.get_PID.setObjectName("get_PID")
        self.Graph_box = QtWidgets.QGroupBox(self.centralwidget)
        self.Graph_box.setGeometry(QtCore.QRect(10, 130, 761, 401))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.Graph_box.setFont(font)
        self.Graph_box.setObjectName("Graph_box")
        self.tabWidget = QtWidgets.QTabWidget(self.Graph_box)
        self.tabWidget.setGeometry(QtCore.QRect(0, 20, 761, 381))
        self.tabWidget.setObjectName("tabWidget")
        self.Velocity_tab = QtWidgets.QWidget()
        self.Velocity_tab.setObjectName("Velocity_tab")
        self.Velocity_graph = PlotWidget(self.Velocity_tab)
        self.Velocity_graph.setGeometry(QtCore.QRect(10, 10, 741, 331))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.Velocity_graph.sizePolicy().hasHeightForWidth())
        self.Velocity_graph.setSizePolicy(sizePolicy)
        self.Velocity_graph.setObjectName("Velocity_graph")
        self.tabWidget.addTab(self.Velocity_tab, "")
        self.Position_tab = QtWidgets.QWidget()
        self.Position_tab.setObjectName("Position_tab")
        self.Position_graph = PlotWidget(self.Position_tab)
        self.Position_graph.setGeometry(QtCore.QRect(10, 10, 741, 331))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.Position_graph.sizePolicy().hasHeightForWidth())
        self.Position_graph.setSizePolicy(sizePolicy)
        self.Position_graph.setObjectName("Position_graph")
        self.tabWidget.addTab(self.Position_tab, "")
        self.groupBox_10 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_10.setGeometry(QtCore.QRect(770, 130, 321, 311))
        font = QtGui.QFont()
        font.setFamily("MS Shell Dlg 2")
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.groupBox_10.setFont(font)
        self.groupBox_10.setObjectName("groupBox_10")
        self.re_se_data = QtWidgets.QTextBrowser(self.groupBox_10)
        self.re_se_data.setEnabled(True)
        self.re_se_data.setGeometry(QtCore.QRect(10, 20, 301, 241))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.re_se_data.sizePolicy().hasHeightForWidth())
        self.re_se_data.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.re_se_data.setFont(font)
        self.re_se_data.setObjectName("re_se_data")
        self.testsend = QtWidgets.QTextEdit(self.groupBox_10)
        self.testsend.setGeometry(QtCore.QRect(10, 270, 231, 31))
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.testsend.setFont(font)
        self.testsend.setObjectName("testsend")
        self.send = QtWidgets.QPushButton(self.groupBox_10)
        self.send.setGeometry(QtCore.QRect(250, 270, 61, 31))
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.send.setFont(font)
        self.send.setObjectName("send")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.ser = serial.Serial()
        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)

        #connect serial
        self.connect.clicked.connect(self.clickedCONNECT)

        #enter mode
        self.Start.clicked.connect(self.clickedStart)
        self.Stop.clicked.connect(self.clickedStop)
        self.Reset.clicked.connect(self.clickedReset)

        #draw graph
        self.draw_graph.clicked.connect(self.clickeddrawgraph)

        #set up Position_graph
        self.Position_graph.setBackground('w')
        self.Position_graph.showGrid(x=True, y=True)
        self.Position_graph.setYRange(Y_min, Y_max, padding=0)
        self.Position_graph.setMouseEnabled(x=False, y=False)

        #set up Velocity_graph
        self.Velocity_graph.setBackground('w')
        self.Velocity_graph.showGrid(x=True, y=True)
        self.Velocity_graph.setYRange(Y_min, Y_max, padding=0)
        self.Velocity_graph.setMouseEnabled(x=False, y=False)

        #get PID status
        self.get_PID.clicked.connect(self.clickedgetPID)

        #transmit data
        # self.send.clicked.connect(self.clickedSEND)
        self.send_PID.clicked.connect(self.clickedsendPID)

        #set time for recive function
        self.timer_getdata = QtCore.QTimer()
        self.timer_getdata.setInterval(100)
        self.timer_getdata.timeout.connect(self.recive)

        #set time run system
        self.timer_run = QtCore.QTimer()
        self.timer_run.setInterval(1500)
        self.timer_run.timeout.connect(self.clickedCONNECT)

        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.Connect_box.setTitle(_translate("MainWindow", "Connect"))
        self.COM.setCurrentText(_translate("MainWindow", "COM1"))
        self.COM.setItemText(0, _translate("MainWindow", "COM1"))
        self.COM.setItemText(1, _translate("MainWindow", "COM2"))
        self.COM.setItemText(2, _translate("MainWindow", "COM3"))
        self.COM.setItemText(3, _translate("MainWindow", "COM4"))
        self.COM.setItemText(4, _translate("MainWindow", "COM5"))
        self.COM.setItemText(5, _translate("MainWindow", "COM6"))
        self.connect.setText(_translate("MainWindow", "CONNECT"))
        self.label.setText(_translate("MainWindow", "COM:"))
        self.Mode_box.setTitle(_translate("MainWindow", "Mode"))
        self.Start.setText(_translate("MainWindow", "START"))
        self.Stop.setText(_translate("MainWindow", "STOP"))
        self.Reset.setText(_translate("MainWindow", "RESET"))
        self.draw_graph.setText(_translate("MainWindow", "DRAW"))
        self.PIDStatus_box.setTitle(_translate("MainWindow", "PID Status"))
        self.label_6.setText(_translate("MainWindow", "Kp:"))
        self.Kp_data.setHtml(
            _translate(
                "MainWindow",
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                "p, li { white-space: pre-wrap; }\n"
                "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
                "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>"
            ))
        self.label_7.setText(_translate("MainWindow", "Ki:"))
        self.Ki_data.setHtml(
            _translate(
                "MainWindow",
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                "p, li { white-space: pre-wrap; }\n"
                "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
                "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>"
            ))
        self.label_8.setText(_translate("MainWindow", "Kd:"))
        self.Kd_data.setHtml(
            _translate(
                "MainWindow",
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                "p, li { white-space: pre-wrap; }\n"
                "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
                "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>"
            ))
        self.label_9.setText(_translate("MainWindow", "Setpoint:"))
        self.Setpoint_data.setHtml(
            _translate(
                "MainWindow",
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                "p, li { white-space: pre-wrap; }\n"
                "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:10pt; font-weight:400; font-style:normal;\">\n"
                "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;\"><br /></p></body></html>"
            ))
        self.send_PID.setText(_translate("MainWindow", "Send PID"))
        self.get_PID.setText(_translate("MainWindow", "Get PID"))
        self.Graph_box.setTitle(_translate("MainWindow", "Graph"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Velocity_tab),
                                  _translate("MainWindow", "Velocity"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Position_tab),
                                  _translate("MainWindow", "Position"))
        self.groupBox_10.setTitle(
            _translate("MainWindow", "Received/Send data"))
        self.re_se_data.setHtml(
            _translate(
                "MainWindow",
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                "p, li { white-space: pre-wrap; }\n"
                "</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; font-weight:400; font-style:normal;\">\n"
                "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;\"><br /></p></body></html>"
            ))
        self.send.setText(_translate("MainWindow", "SEND"))

        #disable button, box
        self.Start.setEnabled(False)
        self.Stop.setEnabled(False)
        self.Reset.setEnabled(False)
        self.testsend.setEnabled(False)
        self.send.setEnabled(False)
        self.re_se_data.setEnabled(False)
        self.send_PID.setEnabled(False)
        # self.draw_graph.setEnabled(False)

    def clickedCONNECT(self):
        global comconnect, ser, i
        NameCOM = self.COM.currentText()
        try:
            if (comconnect == False):
                self.ser = serial.Serial(NameCOM, 115200, timeout=2.5)
                self.COM.setEnabled(False)
                self.Start.setEnabled(True)
                self.Stop.setEnabled(True)
                self.Reset.setEnabled(True)
                self.re_se_data.setEnabled(True)
                self.testsend.setEnabled(True)
                self.send.setEnabled(True)
                self.send_PID.setEnabled(True)
                self.draw_graph.setEnabled(False)
                self.connect.setText('DISCONNECT')
                self.connect.setStyleSheet('QPushButton {color: red;}')
                self.re_se_data.append('Serial port ' + NameCOM + ' opened')
                self.timer_getdata.start()
                comconnect = True
            else:
                self.COM.setEnabled(True)
                self.ser.close()
                self.Start.setEnabled(False)
                self.Stop.setEnabled(False)
                self.Reset.setEnabled(False)
                self.re_se_data.setEnabled(False)
                self.testsend.setEnabled(False)
                self.send.setEnabled(False)
                self.send_PID.setEnabled(False)
                self.draw_graph.setEnabled(True)
                self.connect.setText('CONNECT')
                self.connect.setStyleSheet('QPushButton {color: green;}')
                self.re_se_data.append('Serial port ' + NameCOM + ' closed')
                self.timer_getdata.stop()
                self.timer_run.stop()
                comconnect = False
                i = 0
        except IOError:
            if (comconnect == False):
                self.re_se_data.append('Serial port ' + NameCOM +
                                       ' opening error')
            else:
                self.re_se_data.append('Serial port ' + NameCOM +
                                       ' closing error')

    def clickedStart(self):
        self.re_se_data.append('Motor is runing')
        strs_tmp = ['0', '0', '\n']
        Startdata_send = ' '.join(strs_tmp)
        self.ser.write(Startdata_send.encode())
        #self.timer_run.start()

    def clickedStop(self):
        self.re_se_data.append('Motor stopped')
        strs_tmp = ['0', '1', '\n']
        Stopdata_send = ' '.join(strs_tmp)
        self.ser.write(Stopdata_send.encode())

    def clickedReset(self):
        global i, axis
        self.Position_graph.clear()
        self.Velocity_graph.clear()
        i = 1
        axis = []
        self.re_se_data.append('System reseted')
        strs_tmp = ['0', '2', '\n']
        Resetdata_send = ' '.join(strs_tmp)
        self.ser.write(Resetdata_send.encode())

    # def clickedSEND(self):
    #     datasend = self.testsend.toPlainText()
    #     self.re_se_data.append(datasend)
    #     self.ser.write('2'.encode())   #recognize the data test
    #     self.ser.write(datasend.encode())

    def clickedgetPID(self):
        global Kp_send, Ki_send, Kd_send, Setpoint_send, PID_send
        Kp_send = self.Kp_data.toPlainText()
        Ki_send = self.Ki_data.toPlainText()
        Kd_send = self.Kd_data.toPlainText()
        Setpoint_send = self.Setpoint_data.toPlainText()
        strs_tmp = ['1', Kp_send, Ki_send, Kd_send, Setpoint_send, '\n']
        PID_send = ' '.join(strs_tmp)

    def clickedsendPID(self):
        global Kp_send, Ki_send, Kd_send, Setpoint_send, PID_send
        self.ser.write(PID_send.encode())

    def recive(self):
        global axis, ser, i
        bytetoread = self.ser.inWaiting()
        try:
            if bytetoread > 0:
                receive_data = self.ser.read(bytetoread)
                axis = receive_data.split()
                axis_Velocity[i] = int(str(axis[0], 'UTF-8'))
                axis_Position[i] = int(str(axis[1], 'UTF-8'))
                self.re_se_data.append(str(axis[0], 'UTF-8'))
                self.re_se_data.append(str(axis[1], 'UTF-8'))
                i += 1
        except:
            self.re_se_data.append('bug roi con ga')

    def clickeddrawgraph(self):
        global axis_Position, axis_Velocity
        pen = pg.mkPen(color=(255, 0, 0), width=3)
        self.Velocity_graph.plot(time, axis_Velocity, pen=pen)
        self.Position_graph.plot(time, axis_Position, pen=pen)
Example #19
0
class SmartScanGUI(QtGui.QWidget):
    # oh god i'm so sorry. don't listen to him; he's never sorry.
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setLayout(QtGui.QHBoxLayout())
        
        # a dict to store data
        self.dataMatrix = {}
        self.refData = {}
        
        ########################################## create a plot and associated widget ###########################################################
        self.plotWidget = PlotWidget()
        self.layout().addWidget(self.plotWidget,1)
        
        def xYPlot(plotWidget,x,y,yerr=None,xerr=None,color='w',name='Current'):
            thisPlot = plotWidget.plot(x,y,pen=mkPen(color,width=2))
            plotWidget.addItem(
                ErrorBarItem(
                    x=np.asarray(x),
                    y=np.asarray(y),
                    top=np.asarray(yerr) if yerr is not None else None,
                    bottom=np.asarray(yerr) if yerr is not None else None,
                    left=np.asarray(xerr) if xerr is not None else None,
                    right=np.asarray(xerr) if xerr is not None else None,
                    beam=.05,
                    pen=mkPen(color)
                )
            )
            
        # method for updating plot with new data (plot has to be cleared first)
        def updatePlot():
            self.plotWidget.clear()
            for name, rData in self.refData.iteritems():
                xYPlot(
                    self.plotWidget,
                    rData['data'][0],
                    rData['data'][1],
                    yerr=rData['data'][2],
                    color=rData['color'],
                    name=name
                )
            if len(self.dataMatrix.keys()) >= 1:
                for xVal, yValues in self.dataMatrix.items():
                    if xVal in self.xVals:
                        oldMean = self.yVals[self.xVals.index(xVal)]
                        thisMean = np.mean(yValues)
                        newMean = (oldMean+thisMean)/2.
                        self.yVals[self.xVals.index(xVal)] = newMean
                        newErr = np.std(yValues)/np.sqrt(len(yValues))
                        self.errVals[self.xVals.index(xVal)] = newErr
                    else:
                        self.xVals.append(xVal)
                        mean = np.mean(yValues)
                        self.yVals.append(mean)
                        err = np.std(yValues)/np.sqrt(len(yValues))
                        self.errVals.append(err)
                xYPlot(self.plotWidget,self.xVals,self.yVals,yerr=self.errVals) 

        
        ############################################## configure a control panel layout ########################################################
        cpLayout = QtGui.QVBoxLayout()
        self.layout().addLayout(cpLayout)

        # configure the output widget
        outputPane = QtGui.QTabWidget()
        cpLayout.addWidget(LabelWidget('output',outputPane))


            
        @inlineCallbacks
        def onInit():
            ############################################################# VOLTMETER OUTPUT ###########################################################
            # add volt meter to scan output
            if DEBUG:
                vmURL = TEST_VOLTMETER_SERVER
            else:
                vmURL = VOLTMETER_SERVER
            vmProtocol = yield getProtocol(vmURL)
            vmClient = VoltMeterClient(vmProtocol)    
            vmWidget = VoltMeterOutputWidget(vmClient)
            outputPane.addTab(vmWidget,'voltmeter')


            ############################################################# BEGIN INPUTS ###########################################################

            # configure the input widget
            inputPane = QtGui.QTabWidget()
            inputPane.setTabPosition(inputPane.West)
            cpLayout.addWidget(LabelWidget('input',inputPane),1)    

            
            # algorithm for scan inputs is:
            # 0. check to see if input is disabled
            # 1. create client for server from protocol object
            # 2. create combo widget to hold interval and list widgets
            # 3. create interval widget using client object, add to combo
            # 4. same for list widget
            # 5. add combo widget to base combo widget (resulting in 2-D tab widget)

            
            ############################################################# MANUAL INPUT ###########################################################
            class ManualInputWidget(QtGui.QWidget):
                def __init__(self,parentWidget):
                    QtGui.QWidget.__init__(self)
                    self.parentWidget = parentWidget
                    self.done = False
                
                def initScan(self):
                    return
                
                def checkIfDone(self):
                    return
                
                def next(self):
                    result, valid = QtGui.QInputDialog.getDouble(
                        self.parentWidget, 
                        'next x value', 
                        'enter next x value',
                        decimals=6
                    )
                    if valid:
                        return result
                    else:
                        return None
                
                def cancel(self):
                    return

            inputPane.addTab(
                ManualInputWidget(self),
                'manual'
            )
            
            
            
            ############################################################# MANUAL SCAN INPUT ###########################################################
            
            class ManualScanInputWidget(InputWidget):
                def __init__(self,parent):
                    spinBoxProps = {
                        'rangeMin':-100000,
                        'rangeMax':100000,
                        'stepMin':.000001,
                        'stepMax':100000,
                        'startInit':0,
                        'stopInit':1,
                        'stepSizeInit':.1
                    }
                    
                    def setPosition(position):
                        msgBox = QtGui.QMessageBox()
                        msgBox.setText("next position:\t"+str(position))
                        msgBox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
                        msgBox.setDefaultButton(QtGui.QMessageBox.Ok)
                        ret = msgBox.exec_()
                        if ret == QtGui.QMessageBox.Ok:
                            return position
                        elif ret == QtGui.QMessageBox.Cancel:
                            return None
                    
                    InputWidget.__init__(self,lambda(x):None,setPosition,spinBoxProperties = spinBoxProps)
                    
            inputPane.addTab(
                ManualScanInputWidget(self),
                'manual scan'
            )

            
            ############################################################# STEPPER MOTOR INPUTS ###########################################################
            
            # load in the stepper motor names
            from config.steppermotor import KDP, BBO, PDL, LID, POL 
            
            # get stepper motor protocol (how to communicate to stepper motor server)
            smProtocol = yield getProtocol(
                TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER 
            )
            
            # define a chunked (cancellable) client for each stepper motor
            stepperMotorsClients = {}
            for stepperMotorName in (KDP,BBO,PDL,LID,POL):
                stepperMotorsClients[stepperMotorName] = ChunkedStepperMotorClient(smProtocol,stepperMotorName)

            # define an input widget for each stepper motor, each add to input pane
            for smID,smClient in stepperMotorsClients.items():
                spinBoxProps = {
                    'rangeMin':-100000,
                    'rangeMax':100000,
                    'stepMin':1,
                    'stepMax':100000,
                    'startInit':0,
                    'stopInit':100,
                    'stepSizeInit':1
                }
                
                thisInputWidget = InputWidget(
                    smClient.getPosition,
                    smClient.setPosition,
                    cancelCommand = smClient.cancel,
                    spinBoxProperties = spinBoxProps
                )
            
                inputPane.addTab(
                    thisInputWidget,
                    smID
                )
            
            
            
            ############################################################# WAVELENGTH SERVER INPUT ###########################################################

            '''
            # add wavelength client to scan input
            wlProtocol = yield getProtocol(
                TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER
            )
            wlClient = WavelengthClient(wlProtocol)
            
            spinBoxProps = {
                'rangeMin':24100,
                'rangeMax':25000,
                'stepMin':.01,
                'stepMax':900,
                'startInit':24200,
                'stopInit':24220,
                'stepSizeInit':1
            }
           
            wlInputWidget = InputWidget(
                    wlClient.getWavelength,
                    wlClient.setWavelength,
                    cancelCommand = wlClient.cancelWavelengthSet,
                    spinBoxProperties = spinBoxProps
            )

            inputPane.addTab(
                wlInputWidget,
                'wl'
            )
            '''
            
            
            
            ############################################################# POLARIZER SERVER INPUT ###########################################################
            '''
            # get protocol
            polProtocol = yield getProtocol(
                TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER
            )
            
            # define the client
            polClient = PolarizerClient(polProtocol)
            
            # set limits on spinboxes
            spinBoxProps = {
                'rangeMin':-720,
                'rangeMax':720,
                'stepMin':.01,
                'stepMax':720,
                'startInit':0,
                'stopInit':90,
                'stepSizeInit':5
            }
            
            polInputWidget = InputWidget(
                    polClient.getAngle,
                    polClient.setAngle,
                    cancelCommand = polClient.cancelAngleSet,
                    spinBoxProperties = spinBoxProps
                )

            inputPane.addTab(
                polInputWidget,
                'pol'
            )
            '''
            
            
            
            ############################################################# DDG INPUTS ###########################################################
            
            # load in the delay generator names
            from config.delaygenerator import MAV_PUMP_LAMP, MAV_PUMP_QSW, MAV_PROBE_LAMP, MAV_PROBE_QSW, MAV_NOZZLE
            
            # load in the delay generator limits
            from config.delaygenerator import MIN_DELAY, MAX_DELAY, DELAY_RES
            
            # get the delay generator protocol
            dgProtocol = yield getProtocol(
                TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER
            )
            dgClient = DelayGeneratorClient(dgProtocol)
            
            # define an input widget for each delay generator, each add to input pane 
            for dgName in (MAV_PUMP_LAMP, MAV_PUMP_QSW, MAV_PROBE_LAMP, MAV_PROBE_QSW, MAV_NOZZLE):
                
                spinBoxProps = {
                    'rangeMin':MIN_DELAY,
                    'rangeMax':MAX_DELAY,
                    'stepMin':DELAY_RES,
                    'stepMax':MAX_DELAY-MIN_DELAY,
                    'startInit':1,
                    'stopInit':1001,
                    'stepSizeInit':10
                }

                # because there is one DG client for all DGs (unlike SM client), we use partial to map the client\
                # commands to individual DGs so that we preserve as much of the same structure as possible.
                thisInputWidget = InputWidget(
                    partial(dgClient.getDelay,dgName),
                    partial(dgClient.setPartnerDelay,dgName),
                    spinBoxProperties = spinBoxProps
                )
            
                inputPane.addTab(
                    thisInputWidget,
                    dgName
                )
                
            ############################################################# END INPUTS ###########################################################


            ############################################################# SCANNING ###########################################################

            #define fundamental scan logic:
            #   1: ask independent variable to change, wait
            #   2: measure dependent
            #   3: perform onStep task with x-y pair (e.g. update plot)
            
            class Scan:
                def __init__(self,inputWidget,outputWidget,onStepFunct,repeats=1,plotWidget=None):
                    self.input = inputWidget
                    self.output = outputWidget
                    self.onStep = onStepFunct
                    self.output.plot = plotWidget
                    self.repeatTotal = repeats
                    self.activeRepeat = 1
                    self.startScan()
                    
                def startScan(self):
                    if len(self.input.scanValues) == 0: self.input.initScan()
                    self.output.initScan()
                    self.paused = False
                    self.done = False
                    self.loop()

                @inlineCallbacks
                def loop(self):
                    # pause if paused
                    if self.paused:
                        resumeCancelDialog = QtGui.QMessageBox()
                        resumeCancelDialog.setText("the scan has been paused.")
                        resumeCancelDialog.setInformativeText("do you want to cancel the scan?")
                        resumeCancelDialog.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
                        resumeCancelDialog.setDefaultButton(QtGui.QMessageBox.No)
                    
                        option = resumeCancelDialog.exec_()
                        
                        if option == QtGui.QMessageBox.Yes:
                            #quit the scan
                            self.cancel()
                            return
                            
                        if option == QtGui.QMessageBox.No:
                            #resume the scan
                            self.resume()
                    
                        while self.paused:
                            QtGui.QApplication.processEvents()
                            sleep(.1)
                        
                    # check if done by asking input
                    self.input.checkIfDone()
                    inputDone = self.input.done
                    
                    # if done, finish to clean up
                    if inputDone:
                        self.finish()
                    
                    # if not done, continue onto next point & measure
                    if not inputDone:
                        inputData = yield self.input.next()
                        if inputData == None:
                            yield self.cancel()
                            return
                        else:
                            self.output.setPlotterXVal(inputData)
                            outputDataDefer = self.output.startAcquisition()
                            outputData = yield outputDataDefer
                            yield self.onStep(inputData,outputData)
                            self.loop()
                    
                def pause(self):
                    self.paused = True
                
                def resume(self):
                    self.paused = False
                    
                def cancel(self):
                    self.done = True
                    self.input.cancel()
                    self.output.cancel()
                    scanToggleClicked()
                    
                @inlineCallbacks    
                def finish(self):
                    if self.activeRepeat == self.repeatTotal:
                        self.done = True
                        yield self.input.cancel()
                        self.output.cancel()
                        scanToggleClicked()
                    else:
                        self.activeRepeat += 1
                        if self.activeRepeat % 2 == 0:
                            self.input.initFlipScan()
                        else:
                            self.input.initScan()
                        self.startScan()

            # define what to do after values are acquired at a position
            def onStepped(input,output):
                # unpack scan step data
                position, output = input, output
                if position == None or output == None: 
                    return
                else:
                    # update data array
                    if position not in self.dataMatrix.keys():
                        self.dataMatrix[position] = []
                    for value in output:
                        self.dataMatrix[position].append(value)

                    # update plot
                    updatePlot()
               
            # define scanning start/pause/cancel logic
            def scanToggleClicked():
                if self.scanning:
                    #currently scanning so check if the scan is done, if not this was a pause
                    if not self.thisScan.done:
                        #pause the scan, pop resume/cancel dialog
                        self.thisScan.pause()

                    else:
                        self.scanning = False
                        scanToggleButton.setText("start")
                        return
                    
                if not self.scanning:
                    #not currently scanning, so start the scan
                    self.scanning = True
                    
                    #gather the agents (classes with specific methods) that progress scan and measure values
                    inputAgent = inputPane.currentWidget()
                    outputAgent = outputPane.currentWidget()
                    updateAgent = onStepped
                    
                    #dump whatever data is in the matrix, prepare the plot
                    for xVal in self.dataMatrix.keys():
                        del self.dataMatrix[xVal]
                    
                    # clear the lists that the plot uses to plot
                    self.xVals = []
                    self.yVals = []
                    self.errVals = []

                    updatePlot()
                    self.plotWidget.enableAutoRange()
                    
                    #define the scan, which automatically starts it
                    numToRepeat = self.repeatSpinBox.value()
                    self.thisScan = Scan(inputAgent, outputAgent, updateAgent, numToRepeat, self.plotWidget)
                    
                    #rename our button so users know about the other half of this function
                    scanToggleButton.setText("pause/cancel")
                
                return
            
            self.scanning = False
            
            # set up the GUI to have the scan start/pause/cancel button and repeat spinbox    
            scanPane = QtGui.QHBoxLayout()
            scanToggleButton = QtGui.QPushButton("start")
            scanToggleButton.clicked.connect(scanToggleClicked)
            scanPane.addWidget(scanToggleButton)
            
            self.repeatSpinBox = QtGui.QSpinBox()
            self.repeatSpinBox.setRange(1,10000)
            self.repeatSpinBox.setValue(1)
            scanPane.addWidget(self.repeatSpinBox)
            
            cpLayout.addWidget(LabelWidget('scan',scanPane))


            ############################################################# LOAD FUNCTIONS ###########################################################

            refLayout = QtGui.QHBoxLayout()
            
            def onLoadClicked():
                dir, filePrefix = filenameGen()
                dir = join(POOHDATAPATH,dir)
                
                refFileName = QtGui.QFileDialog.getOpenFileName(self,'select file', dir,"CSV Files (*.csv)")
                
                rData = np.loadtxt(open(refFileName[0],"rb"),delimiter=",")
                name = refFileName[0].rpartition('/')[2]
                
                color = QtGui.QColorDialog.getColor()
                
                if 'matrix' in refFileName[0]:
                    xVals = rData[:,0]
                    yVals = []
                    errVals = []
                    for rowNum in range(len(xVals)):
                        thisYList = rData[rowNum,1:]
                        yVals.append(np.mean(thisYList))
                        errVals.append(np.std(thisYList)/np.sqrt(len(thisYList)))
                    self.refData[name] = {
                        'color': color,
                        'data': [xVals, yVals, errVals]
                    }
                else:
                    self.refData[name] = {
                        'color': color,
                        'data': [rData[:,0], rData[:,1], rData[:,2]]
                    }
                
                updatePlot()
            
            loadButton = QtGui.QPushButton('load')
            loadButton.clicked.connect(onLoadClicked)
            refLayout.addWidget(SqueezeRow(loadButton))

            def onClearClicked():
                for refs in self.refData.keys():
                    del self.refData[refs]
                    
                updatePlot()

            clearButton = QtGui.QPushButton('clear all')
            clearButton.clicked.connect(onClearClicked)
            refLayout.addWidget(SqueezeRow(clearButton))

            cpLayout.addWidget(LabelWidget('reference',refLayout))    

            
            ############################################################# SAVE FUNCTIONS ###########################################################
            
            saveLayout = QtGui.QHBoxLayout()
            
            def onSaveRawClicked():
                dataType = np.dtype(np.float32)
                orderedDataDict = OrderedDict(sorted(self.dataMatrix.items()))
                data = np.reshape(np.asarray(orderedDataDict.keys(),dtype=dataType),(len(orderedDataDict.keys()),1)) #just x values as a column
                yVals = np.asarray(orderedDataDict.values(),dtype=dataType)
                data = np.hstack((data,yVals))
                saveFile(data,'matrix')
            saveRawButton = QtGui.QPushButton('save (raw)')
            saveRawButton.clicked.connect(onSaveRawClicked)
            saveLayout.addWidget(SqueezeRow(saveRawButton))
            
            def onSaveStatsClicked():
                xData = self.dataMatrix.keys()
                yData = []
                errData = []
                for rawValues in self.dataMatrix.values():
                    yData.append(np.mean(rawValues))
                    errData.append(np.std(rawValues)/np.sqrt(len(rawValues)))
                data = np.asarray([xData, yData, errData], dtype=np.dtype(np.float32))
                saveFile(np.transpose(data),'stats')
            saveStatsButton = QtGui.QPushButton('save (stats)')
            saveStatsButton.clicked.connect(onSaveStatsClicked)
            saveLayout.addWidget(SqueezeRow(saveStatsButton))
                
            def saveFile(dataToSave,prefix):
                dir, filePrefix = filenameGen()
                dir = join(POOHDATAPATH,dir)
                checkPath(dir)
                subDir = QtGui.QFileDialog.getExistingDirectory(self,'select folder', dir)
                desc, valid = QtGui.QInputDialog.getText(self, 'enter file description','description' )
                
                if not valid:
                    desc = None
                else:
                    saveCSV(dataToSave, subDir=subDir, description=prefix+'_'+desc)
            
            cpLayout.addWidget(LabelWidget('save',saveLayout))    

        onInit()

    def closeEvent(self, event):
        if reactor.running: reactor.stop()
        event.accept()
Example #20
0
class VNAPowerSweepWidget(VNAFitWidget):
    def __init__(self):
        super(VNAPowerSweepWidget, self).__init__()
        self.power_start = QDoubleSpinBox()
        self.power_stop = QDoubleSpinBox()
        self.power_step = QDoubleSpinBox()
        self.form_layout.addRow("Power Start", self.power_start)
        self.form_layout.addRow("Power Stop", self.power_stop)
        self.form_layout.addRow("Power Stop", self.power_step)

        self.start_sweep_button = QPushButton("Start Sweep")
        self.start_sweep_button.clicked.connect(self.start_sweep)
        self.button_layout.addWidget(self.start_sweep_button)

        self.traces_plot = ImageView()
        self.plot_layout.addWidget(self.traces_plot)
        self.qints_plot = PlotWidget()
        self.plot_layout.addWidget(self.qints_plot)

        self.current_power = None
        self.traces = []
        self.qints = []

    def start_sweep(self):
        powers = arange(self.power_start.value(), self.power_stop.value(),
                        self.power_step.value())
        vna = self.get_vna()
        for i, power in enumerate(powers):
            self.current_power = power
            vna.set_power(power)
            self.grab_trace()
            self.fit_trace()
            self.save_trace()

            self.traces.append(self.mags)
            self.traces_plot.setImage(array(self.traces))

            self.qints.append(self.fit_params['qint'].value)
            self.qints_plot.clear()
            self.qints_plot.plot(self.powers[:i], self.qints)
        self.current_power = None
        g = self.get_h5group()
        g['freqs'] = vna.get_xaxis()
        g['powers'] = powers
        g['qints'] = self.qints
        g['traces'] = self.traces
        dataserver_helpers.set_scale(g, 'powers', 'qints')
        dataserver_helpers.set_scale(g, 'powers', 'traces')
        dataserver_helpers.set_scale(g, 'powers', 'freqs', dim=1)

    def get_h5group(self):
        if self.current_power is not None:
            dataset = str(self.dataset_edit.text())
            self.dataset_edit.setText(dataset + "/%.1f" % self.current_power)
            g = super(VNAPowerSweepWidget, self).get_h5group()
            self.dataset_edit.setText(dataset)
        else:
            return super(VNAPowerSweepWidget, self).get_h5group()

    def grab_trace(self):
        super(VNAPowerSweepWidget, self).grab_trace()
        power_array = self.get_h5group(use_power_child=False)
Example #21
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)
Example #22
0
class UiMainWindow(object):
    def setupUi(self, MainWindow, function):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.data = []
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graph = PlotWidget(self.centralwidget)
        self.graph.setGeometry(QtCore.QRect(20, 20, 371, 251))
        self.graph.setObjectName("graph")
        self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
        self.stackedWidget.setGeometry(QtCore.QRect(420, 20, 331, 281))
        self.stackedWidget.setObjectName("stackedWidget")
        self.rectangles = QtWidgets.QWidget()
        self.rectangles.setObjectName("rectangles")
        self.formLayoutWidget = QtWidgets.QWidget(self.rectangles)
        self.formLayoutWidget.setGeometry(QtCore.QRect(30, 30, 271, 276))
        self.formLayoutWidget.setObjectName("formLayoutWidget")
        self.formLayout = QtWidgets.QFormLayout(self.formLayoutWidget)
        self.formLayout.setContentsMargins(0, 0, 0, 0)
        self.formLayout.setObjectName("formLayout")
        self.rect_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_label.setObjectName("rect_label")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_label)
        self.rect_left = QtWidgets.QLineEdit(self.formLayoutWidget)
        self.rect_left.setObjectName("rect_left")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_left)
        self.rect_right = QtWidgets.QLineEdit(self.formLayoutWidget)
        self.rect_right.setObjectName("rect_right")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_right)
        self.rect_min = QtWidgets.QLineEdit(self.formLayoutWidget)
        self.rect_min.setObjectName("rect_min")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_min)
        self.rect_max = QtWidgets.QLineEdit(self.formLayoutWidget)
        self.rect_max.setObjectName("rect_max")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_max)
        self.rect_accuracy = QtWidgets.QLineEdit(self.formLayoutWidget)
        self.rect_accuracy.setObjectName("rect_accuracy")
        self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_accuracy)
        self.rect_type = QtWidgets.QComboBox(self.formLayoutWidget)
        self.rect_type.setObjectName("rect_type")
        self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole,
                                  self.rect_type)
        self.rect_type.addItem("Левые")
        self.rect_type.addItem("Правые")
        self.rect_type.addItem("Середина")
        self.rect_left_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_left_label.setObjectName("rect_left_label")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole,
                                  self.rect_left_label)
        self.rect_right_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_right_label.setObjectName("rect_right_label")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole,
                                  self.rect_right_label)
        self.rect_min_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_min_label.setObjectName("rect_min_label")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole,
                                  self.rect_min_label)
        self.rect_max_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_max_label.setObjectName("rect_max_label")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole,
                                  self.rect_max_label)
        self.rect_accuracy_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_accuracy_label.setObjectName("rect_accuracy_label")
        self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole,
                                  self.rect_accuracy_label)
        self.rect_type_label = QtWidgets.QLabel(self.formLayoutWidget)
        self.rect_type_label.setObjectName("rect_type_label")
        self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole,
                                  self.rect_type_label)
        self.start_rect_label = QtWidgets.QPushButton(self.formLayoutWidget)
        self.start_rect_label.setObjectName("start_rect_label")
        self.formLayout.setWidget(8, QtWidgets.QFormLayout.FieldRole,
                                  self.start_rect_label)
        self.stackedWidget.addWidget(self.rectangles)
        self.trapeze = QtWidgets.QWidget()
        self.trapeze.setObjectName("trapeze")
        self.formLayoutWidget_2 = QtWidgets.QWidget(self.trapeze)
        self.formLayoutWidget_2.setGeometry(QtCore.QRect(30, 30, 271, 237))
        self.formLayoutWidget_2.setObjectName("formLayoutWidget_2")
        self.formLayout_3 = QtWidgets.QFormLayout(self.formLayoutWidget_2)
        self.formLayout_3.setContentsMargins(0, 0, 0, 0)
        self.formLayout_3.setObjectName("formLayout_3")
        self.start_trapeze_label = QtWidgets.QPushButton(
            self.formLayoutWidget_2)
        self.start_trapeze_label.setObjectName("start_trapeze_label")
        self.formLayout_3.setWidget(9, QtWidgets.QFormLayout.FieldRole,
                                    self.start_trapeze_label)
        self.trapeze_label = QtWidgets.QLabel(self.formLayoutWidget_2)
        self.trapeze_label.setObjectName("trapeze_label")
        self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole,
                                    self.trapeze_label)
        self.trapeze_right = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        self.trapeze_right.setObjectName("trapeze_right")
        self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.FieldRole,
                                    self.trapeze_right)
        self.trapeze_left = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        self.trapeze_left.setObjectName("trapeze_left")
        self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.FieldRole,
                                    self.trapeze_left)
        self.trapeze_left_label = QtWidgets.QLabel(self.formLayoutWidget_2)
        self.trapeze_left_label.setObjectName("trapeze_left_label")
        self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.LabelRole,
                                    self.trapeze_left_label)
        self.trapeze_right_label = QtWidgets.QLabel(self.formLayoutWidget_2)
        self.trapeze_right_label.setObjectName("trapeze_right_label")
        self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.LabelRole,
                                    self.trapeze_right_label)
        self.trapeze_accuracy = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        self.trapeze_accuracy.setObjectName("trapeze_accuracy")
        self.formLayout_3.setWidget(5, QtWidgets.QFormLayout.FieldRole,
                                    self.trapeze_accuracy)
        self.trapeze_min = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        self.trapeze_min.setObjectName("trapeze_min")
        self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.FieldRole,
                                    self.trapeze_min)
        self.trapeze_min_label = QtWidgets.QLabel(self.formLayoutWidget_2)
        self.trapeze_min_label.setObjectName("trapeze_min_label")
        self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.LabelRole,
                                    self.trapeze_min_label)
        self.trapeze_max = QtWidgets.QLineEdit(self.formLayoutWidget_2)
        self.trapeze_max.setObjectName("trapeze_max")
        self.formLayout_3.setWidget(4, QtWidgets.QFormLayout.FieldRole,
                                    self.trapeze_max)
        self.trapeze_max_label = QtWidgets.QLabel(self.formLayoutWidget_2)
        self.trapeze_max_label.setObjectName("trapeze_max_label")
        self.formLayout_3.setWidget(4, QtWidgets.QFormLayout.LabelRole,
                                    self.trapeze_max_label)
        self.trapeze_accuracy_label = QtWidgets.QLabel(self.formLayoutWidget_2)
        self.trapeze_accuracy_label.setObjectName("trapeze_accuracy_label")
        self.formLayout_3.setWidget(5, QtWidgets.QFormLayout.LabelRole,
                                    self.trapeze_accuracy_label)
        self.stackedWidget.addWidget(self.trapeze)
        self.simpson = QtWidgets.QWidget()
        self.simpson.setObjectName("simpson")
        self.formLayoutWidget_3 = QtWidgets.QWidget(self.simpson)
        self.formLayoutWidget_3.setGeometry(QtCore.QRect(30, 30, 271, 231))
        self.formLayoutWidget_3.setObjectName("formLayoutWidget_3")
        self.formLayout_5 = QtWidgets.QFormLayout(self.formLayoutWidget_3)
        self.formLayout_5.setContentsMargins(0, 0, 0, 0)
        self.formLayout_5.setObjectName("formLayout_5")
        self.start_simpson_label = QtWidgets.QPushButton(
            self.formLayoutWidget_3)
        self.start_simpson_label.setObjectName("start_simpson_label")
        self.formLayout_5.setWidget(6, QtWidgets.QFormLayout.FieldRole,
                                    self.start_simpson_label)
        self.simpson_label = QtWidgets.QLabel(self.formLayoutWidget_3)
        self.simpson_label.setObjectName("simpson_label")
        self.formLayout_5.setWidget(0, QtWidgets.QFormLayout.FieldRole,
                                    self.simpson_label)
        self.simpson_left = QtWidgets.QLineEdit(self.formLayoutWidget_3)
        self.simpson_left.setObjectName("simpson_left")
        self.formLayout_5.setWidget(1, QtWidgets.QFormLayout.FieldRole,
                                    self.simpson_left)
        self.simpson_right = QtWidgets.QLineEdit(self.formLayoutWidget_3)
        self.simpson_right.setObjectName("simpson_right")
        self.formLayout_5.setWidget(2, QtWidgets.QFormLayout.FieldRole,
                                    self.simpson_right)
        self.simpson_min = QtWidgets.QLineEdit(self.formLayoutWidget_3)
        self.simpson_min.setObjectName("simpson_min")
        self.formLayout_5.setWidget(3, QtWidgets.QFormLayout.FieldRole,
                                    self.simpson_min)
        self.simpson_max = QtWidgets.QLineEdit(self.formLayoutWidget_3)
        self.simpson_max.setObjectName("simpson_max")
        self.formLayout_5.setWidget(4, QtWidgets.QFormLayout.FieldRole,
                                    self.simpson_max)
        self.simpson_accuracy = QtWidgets.QLineEdit(self.formLayoutWidget_3)
        self.simpson_accuracy.setObjectName("simpson_accuracy")
        self.formLayout_5.setWidget(5, QtWidgets.QFormLayout.FieldRole,
                                    self.simpson_accuracy)
        self.simpson_left_label = QtWidgets.QLabel(self.formLayoutWidget_3)
        self.simpson_left_label.setObjectName("simpson_left_label")
        self.formLayout_5.setWidget(1, QtWidgets.QFormLayout.LabelRole,
                                    self.simpson_left_label)
        self.simpson_right_label = QtWidgets.QLabel(self.formLayoutWidget_3)
        self.simpson_right_label.setObjectName("simpson_right_label")
        self.formLayout_5.setWidget(2, QtWidgets.QFormLayout.LabelRole,
                                    self.simpson_right_label)
        self.simpson_min_label = QtWidgets.QLabel(self.formLayoutWidget_3)
        self.simpson_min_label.setObjectName("simpson_min_label")
        self.formLayout_5.setWidget(3, QtWidgets.QFormLayout.LabelRole,
                                    self.simpson_min_label)
        self.simpson_max_label = QtWidgets.QLabel(self.formLayoutWidget_3)
        self.simpson_max_label.setObjectName("simpson_max_label")
        self.formLayout_5.setWidget(4, QtWidgets.QFormLayout.LabelRole,
                                    self.simpson_max_label)
        self.simpson_accuracy_label = QtWidgets.QLabel(self.formLayoutWidget_3)
        self.simpson_accuracy_label.setObjectName("simpson_accuracy_label")
        self.formLayout_5.setWidget(5, QtWidgets.QFormLayout.LabelRole,
                                    self.simpson_accuracy_label)
        self.stackedWidget.addWidget(self.simpson)
        self.table = QtWidgets.QTableView(self.centralwidget)
        self.table.setGeometry(QtCore.QRect(55, 341, 691, 211))
        self.table.setObjectName("table")
        self.graph.showGrid(x=True, y=True)
        self.error = QtWidgets.QLabel(self.centralwidget)
        self.error.setGeometry(QtCore.QRect(300, 300, 270, 16))
        self.error.setText("")
        self.error.setObjectName("error")
        self.save = QtWidgets.QPushButton(self.centralwidget)
        self.save.setGeometry(QtCore.QRect(150, 300, 121, 24))
        self.save.setObjectName("save")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(630, 300, 121, 28))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.function = function
        self.pushButton.clicked.connect(self.change_method)
        self.start_simpson_label.clicked.connect(self.simpson_init)
        self.start_rect_label.clicked.connect(self.rect_init)
        self.start_trapeze_label.clicked.connect(self.trapeze_init)
        self.save.clicked.connect(self.save_to_file)
        self.update_graph(-10, 10)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.rect_label.setText(
            _translate("MainWindow", "Метод прямоугольников"))
        self.rect_left_label.setText(_translate("MainWindow", "Левая граница"))
        self.rect_right_label.setText(
            _translate("MainWindow", "Правая граница"))
        self.rect_min_label.setText(
            _translate("MainWindow", "Минимум интервалов"))
        self.rect_max_label.setText(
            _translate("MainWindow", "Максимум интервалов"))
        self.rect_accuracy_label.setText(_translate("MainWindow", "Точность"))
        self.rect_type_label.setText(_translate("MainWindow", "Тип метода"))
        self.start_rect_label.setText(_translate("MainWindow", "Рассчитать"))
        self.start_trapeze_label.setText(_translate("MainWindow",
                                                    "Рассчитать"))
        self.trapeze_label.setText(_translate("MainWindow", "Метод трапеций"))
        self.trapeze_left_label.setText(
            _translate("MainWindow", "Левая граница"))
        self.trapeze_right_label.setText(
            _translate("MainWindow", "Правая граница"))
        self.trapeze_min_label.setText(
            _translate("MainWindow", "Минимум интервалов"))
        self.trapeze_max_label.setText(
            _translate("MainWindow", "Максимум интервалов"))
        self.trapeze_accuracy_label.setText(
            _translate("MainWindow", "Точность"))
        self.start_simpson_label.setText(_translate("MainWindow",
                                                    "Рассчитать"))
        self.simpson_label.setText(_translate("MainWindow", "Метод Симпсона"))
        self.simpson_left_label.setText(
            _translate("MainWindow", "Левая граница"))
        self.simpson_right_label.setText(
            _translate("MainWindow", "Правая граница"))
        self.simpson_min_label.setText(
            _translate("MainWindow", "Минимум интервалов"))
        self.simpson_max_label.setText(
            _translate("MainWindow", "Максимум интервалов"))
        self.simpson_accuracy_label.setText(
            _translate("MainWindow", "Точность"))
        self.save.setText(_translate("MainWindow", "Сохранить в файл"))
        self.pushButton.setText(_translate("MainWindow", "Сменить метод"))

    def update_graph(self, a, b):
        delta = abs(b - a) / 100
        values = []
        plots = []
        for i in range(100):
            plots.append(a + i * delta)
            values.append(self.function(a + i * delta))
        self.graph.clear()
        self.graph.plot(plots, values)

    def change_method(self):
        index = self.stackedWidget.currentIndex()
        if index > 1:
            index = 0
        else:
            index = index + 1
        self.stackedWidget.setCurrentIndex(index)

    def simpson_init(self):
        try:
            a = float(self.simpson_left.text())
            b = float(self.simpson_right.text())
            acc = float(self.simpson_accuracy.text())
            min_intervals = float(self.simpson_min.text())
            max_intervals = float(self.simpson_max.text())
            if not validate_params(a, b, min_intervals, max_intervals):
                raise ValueError
            self.error.setText('')
            delta = abs(b - a)
            self.update_graph(a - delta * 0.1, b + delta * 0.1)
            data = imath.simpson(self.function, a, b, acc, min_intervals,
                                 max_intervals)
            self.data = data
            model = tablemodel.TableModel(data, ["Sum", "N"])
            self.table.setModel(model)
            self.table.update()
        except ValueError:
            self.error.setText('Invalid params')
        except imath.RequirementException:
            self.error.setText("Convergence requirements faild")
        except imath.BadParamsExceptions:
            self.error.setText('Invalid params')

    def rect_init(self):
        try:
            a = float(self.rect_left.text())
            b = float(self.rect_right.text())
            acc = float(self.rect_accuracy.text())
            min_intervals = float(self.rect_min.text())
            max_intervals = float(self.rect_max.text())

            if not validate_params(a, b, min_intervals, max_intervals):
                raise ValueError
            self.error.setText('')
            delta = abs(b - a)
            self.update_graph(a - delta * 0.1, b + delta * 0.1)
            if self.rect_type.currentIndex() == 0:
                data = imath.rectangles_left(self.function, a, b, acc,
                                             min_intervals, max_intervals)
            elif self.rect_type.currentIndex() == 1:
                data = imath.rectangles_right(self.function, a, b, acc,
                                              min_intervals, max_intervals)
            elif self.rect_type.currentIndex() == 2:
                data = imath.rectangles_middle(self.function, a, b, acc,
                                               min_intervals, max_intervals)
            self.data = data
            model = tablemodel.TableModel(data, ["Sum", "N"])
            self.table.setModel(model)
            self.table.update()
        except ValueError:
            self.error.setText('Invalid params')
        except imath.RequirementException:
            self.error.setText("Convergence requirements faild")
        except imath.BadParamsExceptions:
            self.error.setText('Invalid params')

    def trapeze_init(self):
        try:
            a = float(self.trapeze_left.text())
            b = float(self.trapeze_right.text())
            acc = float(self.trapeze_accuracy.text())
            min_intervals = float(self.trapeze_min.text())
            max_intervals = float(self.trapeze_max.text())
            if not validate_params(a, b, min_intervals, max_intervals):
                raise ValueError
            self.error.setText('')
            delta = abs(b - a)
            self.update_graph(a - delta * 0.1, b + delta * 0.1)
            data = imath.trapeze(self.function, a, b, acc, min_intervals,
                                 max_intervals)
            self.data = data
            model = tablemodel.TableModel(data, ["Sum", "N"])
            self.table.setModel(model)
            self.table.update()
        except ValueError:
            self.error.setText("Invalid Params")
        except imath.RequirementException:
            self.error.setText("Convergence requirements faild")
        except imath.BadParamsExceptions:
            self.error.setText('Invalid params')

    def save_to_file(self):
        openfile = QtGui.QFileDialog.getOpenFileName(self, 'Open file')[0]
        f = open(openfile, 'w')
        data = self.data
        for d in data:
            f.write(','.join(list(map(str, d))))
        f.close()
Example #23
0
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)
        self._plot_widget.getPlotItem().sigRangeChanged.connect(
            self.limits_changed)

        self.bins = 10
        self.window = 100
        self._curves = {}
        self._current_vline = None

    def add_curve(self,
                  curve_id,
                  curve_name,
                  curve_color=QColor(Qt.blue),
                  markers_on=False):
        pen = mkPen(curve_color, width=1)
        # this adds the item to the plot and legend
        plot = self._plot_widget.plot(stepMode=True,
                                      fillLevel=0,
                                      brush=(0, 0, 255, 150))
        self._curves[curve_id] = plot

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.removeItem(self._curves[curve_id])
            del self._curves[curve_id]
            self._update_legend()

    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.addItem(curve)
        if self._current_vline:
            self._plot_widget.addItem(self._current_vline)

    def redraw(self):
        pass

    def set_values(self, curve_id, data_x, data_y):
        curve = self._curves[curve_id]
        if len(data_y) > 0:
            y, x = numpy.histogram(data_y[-self.window:], self.bins)
            curve.setData(x, y)
        else:
            curve.clear()
        self._plot_widget.autoRange()

    def vline(self, x, color):
        if self._current_vline:
            self._plot_widget.removeItem(self._current_vline)
        self._current_vline = self._plot_widget.addLine(x=x, pen=color)

    def set_xlim(self, limits):
        # TODO: this doesn't seem to handle fast updates well
        self._plot_widget.setXRange(limits[0], limits[1], padding=0)

    def set_ylim(self, limits):
        self._plot_widget.setYRange(limits[0], limits[1], padding=0)

    def get_xlim(self):
        x_range, _ = self._plot_widget.viewRange()
        return x_range

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
Example #24
0
class Ui_Op2(object):
    def setupUi(self, Op2):

        listChem = Equilibrium()
        Op2.setObjectName("Op2")
        Op2.resize(950, 640)
        Op2.setMinimumSize(QtCore.QSize(950, 640))
        Op2.setMaximumSize(QtCore.QSize(950, 640))
        Op2.setWindowIcon(QtGui.QIcon('images\Icone.jpg'))
        Op2.setFocusPolicy(QtCore.Qt.NoFocus)
        Op2.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
        self.centralwidget = QtWidgets.QWidget(Op2)
        self.centralwidget.setObjectName("centralwidget")

        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setGeometry(QtCore.QRect(0, -1, 951, 16))
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")

        self.line_2 = QtWidgets.QFrame(self.centralwidget)
        self.line_2.setGeometry(QtCore.QRect(0, 470, 961, 20))
        self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_2.setObjectName("line_2")

        self.graphicPlot = QtWidgets.QPushButton(self.centralwidget)
        self.graphicPlot.setGeometry(QtCore.QRect(480, 520, 161, 51))
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)

        self.graphicPlot.setFont(font)
        self.graphicPlot.setObjectName("graphicPlot")

        self.graphics1 = PlotWidget(self.centralwidget)
        self.graphics1.setGeometry(QtCore.QRect(10, 10, 461, 401))
        self.graphics1.setBackground('w')
        self.graphics1.showGrid(x=True, y=True)
        self.graphics1.setObjectName("graphics1")

        self.graphics2 = PlotWidget(self.centralwidget)
        self.graphics2.setGeometry(QtCore.QRect(480, 10, 461, 401))
        self.graphics2.setBackground('w')
        self.graphics2.showGrid(x=True, y=True)
        self.graphics2.setObjectName("graphics2")

        self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(310, 520, 171, 51))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")

        self.verticalLayout_2 = QtWidgets.QVBoxLayout(
            self.verticalLayoutWidget)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        self.pconst = QtWidgets.QRadioButton(self.verticalLayoutWidget)
        self.pconst.setEnabled(True)
        self.pconst.setCheckable(True)
        self.pconst.setChecked(False)
        self.pconst.setObjectName("pconst")
        self.verticalLayout_2.addWidget(self.pconst)

        self.tconst = QtWidgets.QRadioButton(self.verticalLayoutWidget)
        self.tconst.setChecked(True)
        self.tconst.setObjectName("tconst")
        self.verticalLayout_2.addWidget(self.tconst)

        self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(
            310, 490, 331, 31))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(
            self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItem = QtWidgets.QSpacerItem(40, 20,
                                           QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Minimum)

        self.horizontalLayout.addItem(spacerItem)
        self.changeTextVar = QtWidgets.QLabel(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)
        self.changeTextVar.setFont(font)
        self.changeTextVar.setObjectName("changeTextVar")
        self.horizontalLayout.addWidget(self.changeTextVar)

        self.databox = QtWidgets.QLineEdit(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.databox.setFont(font)
        self.databox.setValidator(QtGui.QDoubleValidator())
        self.databox.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
        self.databox.setToolTipDuration(1)
        self.databox.setObjectName("databox")

        self.horizontalLayout.addWidget(self.databox)
        self.changeTextUni = QtWidgets.QLabel(self.horizontalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)
        self.changeTextUni.setFont(font)
        self.changeTextUni.setObjectName("changeTextUni")

        self.horizontalLayout.addWidget(self.changeTextUni)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem1)

        self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(260, 420, 431, 53))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")

        self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setObjectName("gridLayout_2")

        self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.label_2.setFont(font)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setObjectName("label_2")
        self.gridLayout_2.addWidget(self.label_2, 0, 1, 1, 1)

        self.label = QtWidgets.QLabel(self.gridLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)

        self.comp2 = QtWidgets.QComboBox(self.gridLayoutWidget)
        font = QtGui.QFont()
        self.comp2.addItems(listChem.chemComp())
        font.setPointSize(9)
        self.comp2.setFont(font)
        self.comp2.setObjectName("comp2")
        self.gridLayout_2.addWidget(self.comp2, 1, 1, 1, 1)

        self.comp1 = QtWidgets.QComboBox(self.gridLayoutWidget)
        font = QtGui.QFont()
        self.comp1.addItems(listChem.chemComp())
        font.setPointSize(9)
        self.comp1.setFont(font)
        self.comp1.setObjectName("comp1")
        self.gridLayout_2.addWidget(self.comp1, 1, 0, 1, 1)

        Op2.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(Op2)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 950, 21))
        self.menubar.setObjectName("menubar")

        self.menuTools = QtWidgets.QMenu(self.menubar)
        self.menuTools.setObjectName("menuTools")
        self.menuAbout = QtWidgets.QMenu(self.menubar)
        self.menuAbout.setObjectName("menuAbout")

        Op2.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(Op2)
        self.statusbar.setObjectName("statusbar")
        Op2.setStatusBar(self.statusbar)

        self.actionsave2Excel = QtWidgets.QAction(Op2)
        self.actionsave2Excel.setObjectName("actionsave2Excel")

        #self.actionsavePlot = QtWidgets.QAction(Op2)
        #self.actionsavePlot.setObjectName("actionsavePlot")

        #self.addElement = QtWidgets.QAction(Op2)
        #self.addElement.setObjectName("addElement")

        self.about = QtWidgets.QAction(Op2)
        self.about.setObjectName("about")

        #self.removeElement = QtWidgets.QAction(Op2)
        #self.removeElement.setObjectName("removeElement")

        self.menuTools.addAction(self.actionsave2Excel)
        #self.menuTools.addAction(self.actionsavePlot)
        self.menuTools.addSeparator()
        #self.menuTools.addAction(self.addElement)
        #self.menuTools.addAction(self.removeElement)
        self.menuAbout.addAction(self.about)
        self.menubar.addAction(self.menuTools.menuAction())
        self.menubar.addAction(self.menuAbout.menuAction())

        self.retranslateUi(Op2)
        QtCore.QMetaObject.connectSlotsByName(Op2)

        self.pconst.toggled.connect(lambda: self.selected(self.pconst)
                                    )  #Selection RadioButton Pressão Constante
        self.tconst.toggled.connect(lambda: self.selected(
            self.tconst))  #Selection RadioButton Temperatura Constante
        self.graphicPlot.clicked.connect(
            lambda: self.call(float(self.databox.text(
            )), self.changeTextUni.text()))  #Call the plot function
        self.actionsave2Excel.triggered.connect(lambda: self.saveData())
        self.about.triggered.connect(lambda: self.aboutMsg())

    def retranslateUi(self, Op2):
        _translate = QtCore.QCoreApplication.translate
        Op2.setWindowTitle(_translate("Op2", "Op_2 App"))
        self.graphicPlot.setText(_translate("Op2", "Plot"))
        self.pconst.setText(_translate("Op2", "Constant pressure "))
        self.tconst.setText(_translate("Op2", "Constant temperature "))
        self.changeTextVar.setText(_translate("Op2", "Temperature"))
        self.changeTextUni.setText(_translate("Op2", "K"))
        self.label_2.setText(_translate("Op2", "Substance 2"))
        self.label.setText(_translate("Op2", "Substance 1"))
        self.menuTools.setTitle(_translate("Op2", "Tools"))
        self.menuAbout.setTitle(_translate("Op2", "About"))
        self.actionsave2Excel.setText(_translate("Op2", "Save data to Excel"))
        #self.actionsavePlot.setText(_translate("Op2", "Salvar gráficos"))
        #self.addElement.setText(_translate("Op2", "Adicionar Elemento"))
        self.about.setText(_translate("Op2", "about"))
        #self.removeElement.setText(_translate("Op2", "Remover Elemento"))

    def selected(self, b):

        if b.text() == "Constant pressure ":
            if b.isChecked() == True:
                self.changeTextVar.setText('Pressure')
                self.changeTextUni.setText("bar")

        elif b.text() == "Constant temperature ":
            if b.isChecked() == True:
                self.changeTextVar.setText('Temperature')
                self.changeTextUni.setText("K")

    def call(self, data, signal, n=1000):

        self.graphics1.clear(), self.graphics2.clear()
        x = np.arange(0, 1.0 + (1 / n), (1 / n))
        y, P, T = np.zeros(np.size(x)), np.zeros(np.size(x)), np.zeros(
            np.size(x))

        if signal == "bar":
            #Erase float_files
            if os.path.exists('float_files\\pconstdata.txt'):
                os.remove('float_files\\pconstdata.txt')
            try:
                data = open('float_files\\pconstdata.txt', 'a')
                newData = Equilibrium(
                    lchem=[self.comp1.currentText(),
                           self.comp2.currentText()],
                    p=float(self.databox.text()))
                self.A, self.B, self.C, self.Tmax, self.Tmin, self.DG = newData.compData(
                )
                Tsat = (
                    self.B /
                    (self.A - np.log10(float(self.databox.text())))) - self.C
                data.write('Temperature [K], x, y\n')
                for i in range(np.size(x)):
                    T0 = np.sum(np.asarray([x[i], 1 - x[i]]) * Tsat)
                    while (True):
                        a12 = 10**(self.A[0] - self.A[1] - (self.B[0] /
                                                            (T0 + self.C[0])) +
                                   (self.B[1] / (T0 + self.C[1])))
                        coef = UNIFAC(T=T0,
                                      xs=[x[i], 1 - x[i]],
                                      chemgroups=self.DG)
                        P2sat = (float(self.databox.text()) /
                                 (x[i] * coef[0] * a12 + (1 - x[i]) * coef[1]))
                        Tn = (self.B[1] /
                              (self.A[1] - np.log10(P2sat))) - self.C[1]
                        if (abs(Tn - T0) < 0.001):
                            break
                        T0 = Tn
                    T[i] = T0
                    y[i] = 1 - ((1 - x[i]) * coef[1] * P2sat) / (float(
                        self.databox.text()))
                    data.write(
                        str(round(T[i], 4)) + ', ' + str(round(x[i], 4)) +
                        ', ' + str(round(y[i], 4)))
                    data.write('\n')

                self.graphics1.plot(x, y, pen='r')
                self.graphics1.plot(x, x, pen='r')
                self.graphics1.setLabel('left',
                                        'Gas composition of ' +
                                        self.comp1.currentText(),
                                        color='r',
                                        size=20)
                self.graphics1.setLabel('bottom',
                                        'Liquid composition of ' +
                                        self.comp1.currentText(),
                                        color='b',
                                        size=20)

                self.graphics2.plot(x, T, pen='g')
                self.graphics2.plot(y, T, pen='k')
                self.graphics2.setLabel('left',
                                        'Temperature of ' +
                                        self.comp1.currentText() + ' [K]',
                                        color='r',
                                        size=20)
                self.graphics2.setLabel('bottom',
                                        'Composition of ' +
                                        self.comp1.currentText(),
                                        color='b',
                                        size=20)

                data.close()

            except:
                print('error')

        elif signal == "K":
            #Erase float_files
            if os.path.exists('float_files\\tconstdata.txt'):
                os.remove('float_files\\tconstdata.txt')

            try:
                data = open('float_files\\tconstdata.txt', 'a')
                newData = Equilibrium(
                    lchem=[self.comp1.currentText(),
                           self.comp2.currentText()],
                    t=float(self.databox.text()))
                self.A, self.B, self.C, self.Tmax, self.Tmin, self.DG = newData.compData(
                )
                Pvap = 10**(self.A - (self.B /
                                      (float(self.databox.text()) + self.C)))
                data.write('Pressure [bar], x, y\n')
                for i in range(np.size(x)):
                    actCoef = UNIFAC(T=float(self.databox.text()),
                                     xs=[x[i], 1 - x[i]],
                                     chemgroups=self.DG)
                    P[i] = np.sum(Pvap * np.asarray(actCoef) *
                                  np.asarray([x[i], 1 - x[i]]))
                    y[i] = ((x[i] * actCoef[0] * Pvap[0])) / P[i]
                    data.write(
                        str(round(P[i], 4)) + ', ' + str(round(x[i], 4)) +
                        ', ' + str(round(y[i], 4)))
                    data.write('\n')

                self.graphics1.plot(x, y, pen='r')
                self.graphics1.plot(x, x, pen='r')
                self.graphics1.setLabel('left',
                                        'Gas composition of ' +
                                        self.comp1.currentText(),
                                        color='r',
                                        size=20)
                self.graphics1.setLabel('bottom',
                                        'Liquid composition of ' +
                                        self.comp1.currentText(),
                                        color='b',
                                        size=20)

                self.graphics2.plot(x, P, pen='b')
                self.graphics2.plot(y, P, pen='r')
                self.graphics2.setLabel('left',
                                        'Pressure of ' +
                                        self.comp1.currentText() + ' [bar]',
                                        color='r',
                                        size=20)
                self.graphics2.setLabel('bottom',
                                        'Composition of ' +
                                        self.comp1.currentText(),
                                        color='b',
                                        size=20)

                data.close()

            except:

                print('Error!')

    def saveData(self):

        if self.changeTextUni.text() == 'bar':
            try:
                filename = QtWidgets.QFileDialog.getSaveFileName(
                    caption='Salvar arquivo',
                    directory='c:\\',
                    filter='(*.xlsx)',
                    initialFilter='')
                data = pd.read_csv('float_files\\pconstdata.txt', sep=', ')
                data.to_excel(excel_writer=filename[0])
                os.remove('float_files\\pconstdata.txt')
            except:
                pass

        elif self.changeTextUni.text() == 'K':
            try:
                filename = QtWidgets.QFileDialog.getSaveFileName(
                    caption='Salvar arquivo',
                    directory='c:\\',
                    filter='(*.xlsx)',
                    initialFilter='')
                data = pd.read_csv('float_files\\tconstdata.txt', sep=', ')
                data.to_excel(excel_writer=filename[0])
                os.remove('float_files\\tconstdata.txt')
            except:
                pass

    def aboutMsg(self):

        msg = QtWidgets.QMessageBox()
        msg.setWindowTitle('Sobre')
        msg.setWindowIcon(QtGui.QIcon('images\Icone.jpg'))
        msg.setText(
            'Programa desenvolvido para calcular o equilíbrio de fase líquido-vapor de um sistema binário com fase vapor ideal e fase liquída não ideal cujo'
            + ' coeficiente de atividade é obtido por meio do método UNIFAC')
        x = msg.exec_()
Example #25
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 Window(QWidget):
    def __init__(self, *args, **kwargs):
        super(Window, self).__init__(*args, **kwargs)

        self.title = "Motor Control"
        self.setWindowTitle(self.title)

        #Application Size
        self.left = 100
        self.top = 100
        self.width = 1000
        self.height = 700
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.initUI()

    def initUI(self):

        self.setStyleSheet(qdarkstyle.load_stylesheet())

        self.horizontalLayout = QHBoxLayout()
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setSizeConstraint(QLayout.SetDefaultConstraint)
        self.verticalLayout.setSpacing(6)
        self.gridLayout = QGridLayout()

        self.imageLabel = QLabel()
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.imageLabel.sizePolicy().hasHeightForWidth())
        self.imageLabel.setSizePolicy(sizePolicy)
        self.imageLabel.setMinimumSize(QSize(200, 130))
        self.imageLabel.setMaximumSize(QSize(200, 130))
        self.imageLabel.setPixmap(
            QPixmap("./Arduino/logo/CUAtHomeLogo-Horz.png").scaled(
                200, 130, Qt.KeepAspectRatio, Qt.FastTransformation))
        self.verticalLayout.addWidget(self.imageLabel)

        self.startbutton = QPushButton("Start", self)
        self.startbutton.setCheckable(False)
        self.startbutton.clicked.connect(self.startbutton_pushed)
        self.startbutton.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.startbutton, 0, 0, 1, 1)

        self.stopbutton = QPushButton("Stop", self)
        self.stopbutton.setCheckable(False)
        self.stopbutton.clicked.connect(self.stopbutton_pushed)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.stopbutton.sizePolicy().hasHeightForWidth())
        self.stopbutton.setSizePolicy(sizePolicy)
        self.stopbutton.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.stopbutton, 0, 1, 1, 1)

        self.clearbutton = QPushButton("Clear", self)
        self.clearbutton.setCheckable(False)
        self.clearbutton.clicked.connect(self.clearbutton_pushed)
        self.clearbutton.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.clearbutton, 1, 0, 1, 1)

        self.savebutton = QPushButton("Save", self)
        self.savebutton.setCheckable(False)
        self.savebutton.clicked.connect(self.savebutton_pushed)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.savebutton.sizePolicy().hasHeightForWidth())
        self.savebutton.setSizePolicy(sizePolicy)
        self.savebutton.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.savebutton, 1, 1, 1, 1)

        self.settings = QPushButton("Settings", self)
        self.settings.clicked.connect(self.settingsMenu)
        self.settings.setMaximumSize(QSize(300, 20))
        self.gridLayout.addWidget(self.settings, 2, 0, 1, 2)

        self.checkBoxShowAll = QCheckBox("Show All Plots", self)
        self.checkBoxShowAll.setMaximumSize(QSize(100, 20))
        self.checkBoxShowAll.setChecked(True)
        self.checkBoxShowAll.toggled.connect(self.visibilityAll)
        self.gridLayout.addWidget(self.checkBoxShowAll, 3, 0, 1, 1)

        self.checkBoxHideAll = QCheckBox("Hide All Plots", self)
        self.checkBoxHideAll.setChecked(False)
        self.checkBoxHideAll.toggled.connect(self.hideAll)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.checkBoxHideAll.sizePolicy().hasHeightForWidth())
        self.checkBoxHideAll.setSizePolicy(sizePolicy)
        self.checkBoxHideAll.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.checkBoxHideAll, 3, 1, 1, 1)

        self.checkBoxPlot1 = QCheckBox("Plot 1", self)
        self.checkBoxPlot1.toggled.connect(self.visibility1)
        self.checkBoxPlot1.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.checkBoxPlot1, 4, 0, 1, 1)

        self.checkBoxPlot2 = QCheckBox("Plot 2", self)
        self.checkBoxPlot2.toggled.connect(self.visibility2)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.checkBoxPlot2.sizePolicy().hasHeightForWidth())
        self.checkBoxPlot2.setSizePolicy(sizePolicy)
        self.checkBoxPlot2.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.checkBoxPlot2, 4, 1, 1, 1)

        self.checkBoxShowAll.stateChanged.connect(self.checkbox_logic)
        self.checkBoxHideAll.stateChanged.connect(self.checkbox_logic)
        self.checkBoxPlot1.stateChanged.connect(self.checkbox_logic)
        self.checkBoxPlot2.stateChanged.connect(self.checkbox_logic)

        self.PowerScalingLabel = QLabel("Power Scaling (%)", self)
        self.PowerScalingLabel.setMinimumSize(QSize(100, 20))
        self.PowerScalingLabel.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.PowerScalingLabel, 7, 0, 1, 1)
        self.PowerScalingInput = QLineEdit("", self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.PowerScalingInput.sizePolicy().hasHeightForWidth())
        self.PowerScalingInput.setSizePolicy(sizePolicy)
        self.PowerScalingInput.setMaximumSize(QSize(100, 20))
        #self.PowerScalingInput.setValidator(QRegExpValidator(QRegExp("^[0-9][0-9]?$|^100$"))) #0-1 as a float FIX THIS
        self.gridLayout.addWidget(self.PowerScalingInput, 7, 1, 1, 1)

        self.FrequencyLabel = QLabel("Frequency (Hz)", self)
        self.FrequencyLabel.setMinimumSize(QSize(100, 20))
        self.FrequencyLabel.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.FrequencyLabel, 8, 0, 1, 1)
        self.FrequencyInput = QLineEdit("", self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.FrequencyInput.sizePolicy().hasHeightForWidth())
        self.FrequencyInput.setSizePolicy(sizePolicy)
        self.FrequencyInput.setMaximumSize(QSize(100, 20))
        self.FrequencyInput.setValidator(QDoubleValidator())
        self.gridLayout.addWidget(self.FrequencyInput, 8, 1, 1, 1)

        PID_validator = QDoubleValidator(
            0.0000, 50.000, 4, notation=QDoubleValidator.StandardNotation)

        self.PCheckBox = QCheckBox("P", self)
        self.PCheckBox.setMaximumSize(QSize(100, 20))
        self.PCheckBox.setChecked(True)
        self.PCheckBox.toggled.connect(self.PCheckBoxLogic)
        self.gridLayout.addWidget(self.PCheckBox, 9, 0, 1, 1)
        self.PInput = QLineEdit("", self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.PInput.sizePolicy().hasHeightForWidth())
        self.PInput.setSizePolicy(sizePolicy)
        self.PInput.setMaximumSize(QSize(100, 20))
        self.PInput.setValidator(PID_validator)
        self.gridLayout.addWidget(self.PInput, 9, 1, 1, 1)

        self.ICheckBox = QCheckBox("I", self)
        self.ICheckBox.setMaximumSize(QSize(100, 20))
        self.ICheckBox.setChecked(True)
        self.ICheckBox.toggled.connect(self.ICheckBoxLogic)
        self.gridLayout.addWidget(self.ICheckBox, 10, 0, 1, 1)
        self.IInput = QLineEdit("", self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.IInput.sizePolicy().hasHeightForWidth())
        self.IInput.setSizePolicy(sizePolicy)
        self.IInput.setMaximumSize(QSize(100, 20))
        self.IInput.setValidator(PID_validator)
        self.gridLayout.addWidget(self.IInput, 10, 1, 1, 1)

        self.DCheckBox = QCheckBox("D", self)
        self.DCheckBox.setMaximumSize(QSize(100, 20))
        self.DCheckBox.setChecked(True)
        self.DCheckBox.toggled.connect(self.DCheckBoxLogic)
        self.gridLayout.addWidget(self.DCheckBox, 11, 0, 1, 1)
        self.DInput = QLineEdit("", self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.DInput.sizePolicy().hasHeightForWidth())
        self.DInput.setSizePolicy(sizePolicy)
        self.DInput.setMaximumSize(QSize(100, 20))
        self.DInput.setValidator(PID_validator)
        self.gridLayout.addWidget(self.DInput, 11, 1, 1, 1)

        self.LabType = QComboBox()
        self.LabType.addItems(["Position", "Speed"])
        #self.LabType.activated.connect(self.getLabType)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.LabType.sizePolicy().hasHeightForWidth())
        self.LabType.setSizePolicy(sizePolicy)
        self.LabType.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.LabType, 5, 1, 1, 1)
        self.LabLabel = QLabel("Lab Type")
        self.LabLabel.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.LabLabel, 5, 0, 1, 1)

        self.inputForms = QComboBox()
        self.inputForms.addItems(["Sine", "Step"])
        self.inputForms.activated.connect(self.getInput)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.inputForms.sizePolicy().hasHeightForWidth())
        self.inputForms.setSizePolicy(sizePolicy)
        self.inputForms.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.inputForms, 6, 1, 1, 1)
        self.inputType = QLabel("Input Type")
        self.inputType.setMaximumSize(QSize(100, 20))
        self.gridLayout.addWidget(self.inputType, 6, 0, 1, 1)

        self.verticalLayout.addLayout(self.gridLayout)
        spacerItem = QSpacerItem(20, 80, QSizePolicy.Minimum,
                                 QSizePolicy.Fixed)
        self.verticalLayout.addItem(spacerItem)

        #What is this?

        self.label = QLabel()
        self.label.setMaximumSize(QSize(200, 130))
        self.label.setText("")
        self.verticalLayout.addWidget(self.label)

        self.horizontalLayout.addLayout(self.verticalLayout)
        self.rightVerticalLayout = QVBoxLayout()

        self.graphWidgetOutput = PlotWidget()
        self.graphWidgetInput = PlotWidget()

        #Adds grid lines
        self.graphWidgetOutput.showGrid(x=True, y=True, alpha=None)
        self.graphWidgetInput.showGrid(x=True, y=True, alpha=None)

        #self.graphWidget.setXRange(0, 100, padding=0) #Doesn't move with the plot. Can drag around
        #self.graphWidget.setLimits(xMin=0, xMax=100)#, yMin=c, yMax=d) #Doesn't move with the plot. Cannot drag around

        #self.graphWidget.setYRange(0, 4, padding=0)
        self.graphWidgetOutput.setYRange(-11, 11, padding=0)
        self.graphWidgetOutput.enableAutoRange()
        self.graphWidgetInput.setYRange(-11, 11, padding=0)
        self.graphWidgetInput.enableAutoRange()

        #Changes background color of graph
        self.graphWidgetOutput.setBackground((0, 0, 0))
        self.graphWidgetInput.setBackground((0, 0, 0))

        #Adds a legend after data starts to plot NOT before
        self.graphWidgetOutput.addLegend()

        #Adds title to graphs
        self.graphWidgetOutput.setTitle("Response", color="w", size="12pt")
        self.graphWidgetInput.setTitle("PWM Actuation Signal",
                                       color="w",
                                       size="12pt")

        self.rightVerticalLayout.addWidget(self.graphWidgetOutput)
        self.rightVerticalLayout.addWidget(self.graphWidgetInput)
        self.horizontalLayout.addLayout(self.rightVerticalLayout)

        self.setLayout(self.horizontalLayout)

        #Plot time update settings
        self.timer = QTimer()
        self.timer.setInterval(
            50
        )  #Changes the plot speed. Defaulted to 50. Can be placed in startbutton_pushed() method
        self.initialState()
        time.sleep(2)
        try:
            self.timer.timeout.connect(self.update)
        except:
            raise Exception("Not Connected")
        #self.show()

    #Checkbox logic
    def checkbox_logic(self, state):

        # checking if state is checked
        if state == Qt.Checked:

            if self.sender() == self.checkBoxShowAll:
                self.checkBoxHideAll.setChecked(False)
                self.checkBoxPlot1.setChecked(False)
                self.checkBoxPlot2.setChecked(False)
                #self.checkBoxShow.stateChanged.disconnect(self.uncheck)

            elif self.sender() == self.checkBoxHideAll:
                #self.checkBoxShow.stateChanged.connect(self.uncheck)
                self.checkBoxShowAll.setChecked(False)
                self.checkBoxPlot1.setChecked(False)
                self.checkBoxPlot2.setChecked(False)

            elif self.sender() == self.checkBoxPlot1:
                self.checkBoxShowAll.setChecked(False)
                self.checkBoxHideAll.setChecked(False)
                self.checkBoxPlot2.setChecked(False)

            elif self.sender() == self.checkBoxPlot2:
                self.checkBoxShowAll.setChecked(False)
                self.checkBoxHideAll.setChecked(False)
                self.checkBoxPlot1.setChecked(False)

    #Resets data arrays and establishes serial communcation. Disables itself after clicking
    def startbutton_pushed(self):
        self.initialState(
        )  #Reinitializes arrays in case you have to retake data
        self.size = self.serial_values[3]  #Value from settings. Windows data
        #self.buffersize = self.serial_values[4] #Value from settings. Restricts buffer data
        '''
        self.ser = serial.Serial(port = self.serial_values[0], 
                                 baudrate = self.serial_values[1],
                                 timeout = self.serial_values[2])
        self.ser.flushInput()
        self.ser.write(b'A')
        time.sleep(2)
        print("Recording Data")
        self.timer.start()
        #self.timer.setInterval(50)
        self.curve()
        self.startbutton.clicked.disconnect(self.startbutton_pushed)
        '''
        self.serialInstance = SerialComm(self.serial_values[0],
                                         self.serial_values[1],
                                         self.serial_values[2])
        self.serialInstance.serialOpen()
        time.sleep(2)
        print("Recording Data")
        self.timer.start()
        self.curve()
        self.startbutton.clicked.disconnect(self.startbutton_pushed)

    #Stops timer and ends serial communication
    def stopbutton_pushed(self):
        self.timer.stop()
        #self.ser.close()
        self.serialInstance.serialClose()
        '''
        print("y1 zeros:", self.y1_zeros)
        print("y2 zeros:", self.y2_zeros)
        print("y1 full:", self.y1)
        print("y2 full:", self.y2)
        '''

    #Resets both plotting windows and reenables Start Button
    def clearbutton_pushed(self):
        self.graphWidgetOutput.clear()
        self.graphWidgetInput.clear()
        self.graphWidgetOutput.enableAutoRange(axis=None,
                                               enable=True,
                                               x=None,
                                               y=None)
        self.startbutton.clicked.connect(self.startbutton_pushed)

    #Dumps data into a csv file to a selected path
    def savebutton_pushed(self):
        self.createCSV()
        path = QFileDialog.getSaveFileName(self, 'Save CSV', os.getenv('HOME'),
                                           'CSV(*.csv)')
        if path[0] != '':
            with open(path[0], 'w', newline='') as csvfile:
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow(self.header)
                csvwriter.writerows(self.data_set)

    #Creates csv data
    def createCSV(self):
        self.header = ['time', 'y1', 'y2']
        self.data_set = zip(self.time, self.y1, self.y2)

    #Initilizes lists/arrays
    def initialState(self):
        self.buffersize = 500  #np array size that is used to plot data
        self.step = 0  #Used for repositioning data in plot window to the left

        #Data buffers. What is being plotted in the 2 windows
        self.time_zeros = np.zeros(self.buffersize + 1, float)
        self.y1_zeros = np.zeros(self.buffersize + 1, float)
        self.y2_zeros = np.zeros(self.buffersize + 1, float)
        self.y3_zeros = np.zeros(self.buffersize + 1, float)

        #Complete data. What will be written to the csv file
        self.time = list()
        self.y1 = list()
        self.y2 = list()
        self.y3 = list()

        self.getLabType()

    '''
    def readValues(self):
        arduinoData = self.ser.readline().decode().replace('\r\n','').split(",")
        return arduinoData
    '''

    #Initializes data# to have specific attributes
    def curve(self):
        pen1 = pg.mkPen(color=(255, 0, 0), width=1)
        pen2 = pg.mkPen(color=(0, 255, 0), width=1)
        pen3 = pg.mkPen(color=(0, 0, 255), width=1)

        self.data1 = self.graphWidgetOutput.plot(pen=pen1,
                                                 name="Data 1")  #Response
        self.data2 = self.graphWidgetOutput.plot(pen=pen2,
                                                 name="Data 2")  #Setpoint
        self.data3 = self.graphWidgetInput.plot(
            pen=pen3, name="Data 3")  #PWM Actuation Signal

    #Connected to timer to update plot. Incoming data is in the form of timestamp,data1,data2...
    def update(self):
        #fulldata = self.readValues()
        #print(fulldata)
        fulldata = self.serialInstance.readValues()

        self.step = self.step + 1

        time_index = int(self.time_zeros[self.buffersize])
        self.time_zeros[time_index] = self.time_zeros[time_index +
                                                      self.size] = float(
                                                          fulldata[0])
        self.time_zeros[self.buffersize] = time_index = (time_index +
                                                         1) % self.size
        self.time.append(fulldata[0])

        i = int(self.y1_zeros[self.buffersize])
        self.y1_zeros[i] = self.y1_zeros[i + self.size] = float(fulldata[1])
        self.y1_zeros[self.buffersize] = i = (i + 1) % self.size
        self.y1.append(fulldata[1])

        j = int(self.y2_zeros[self.buffersize])
        self.y2_zeros[j] = self.y2_zeros[j + self.size] = float(fulldata[2])
        self.y2_zeros[self.buffersize] = j = (j + 1) % self.size
        self.y2.append(fulldata[2])

        k = int(self.y3_zeros[self.buffersize])
        self.y3_zeros[k] = self.y3_zeros[k + self.size] = float(fulldata[3])
        self.y3_zeros[self.buffersize] = k = (k + 1) % self.size
        self.y3.append(fulldata[3])

        self.data1.setData(self.time_zeros[time_index:time_index + self.size],
                           self.y1_zeros[i:i + self.size])
        self.data1.setPos(self.step, 0)
        self.data2.setData(self.time_zeros[time_index:time_index + self.size],
                           self.y2_zeros[j:j + self.size])
        self.data2.setPos(self.step, 0)
        self.data3.setData(self.time_zeros[time_index:time_index + self.size],
                           self.y3_zeros[k:k + self.size])
        self.data3.setPos(self.step, 0)

    #Below 4 change visibility of data# in the curves() method
    def visibilityAll(self):
        showall = self.sender()
        if showall.isChecked() == True:
            self.data1.setVisible(True)
            self.data2.setVisible(True)

    def hideAll(self):
        disappearall = self.sender()
        if disappearall.isChecked() == True:
            self.data1.setVisible(False)
            self.data2.setVisible(False)

    def visibility1(self):
        test1 = self.sender()
        if test1.isChecked() == True:
            self.data1.setVisible(True)
            self.data2.setVisible(False)

    def visibility2(self):
        test2 = self.sender()
        if test2.isChecked() == True:
            self.data2.setVisible(True)
            self.data1.setVisible(False)

    #Class instance of settings menu. Creates a dialog (popup)
    def settingsMenu(self):
        self.settingsPopUp = Dialog1()
        self.settingsPopUp.show()
        #self.settingsPopUp.exec()
        self.serial_values = self.settingsPopUp.getDialogValues()

    def PCheckBoxLogic(self):
        test1 = self.sender()
        if test1.isChecked() == True:
            self.PInput.setEnabled(True)
        elif test1.isChecked() == False:
            self.PInput.setEnabled(False)

    def ICheckBoxLogic(self):
        test1 = self.sender()
        if test1.isChecked() == True:
            self.IInput.setEnabled(True)
        elif test1.isChecked() == False:
            self.IInput.setEnabled(False)

    def DCheckBoxLogic(self):
        test1 = self.sender()
        if test1.isChecked() == True:
            self.DInput.setEnabled(True)
        elif test1.isChecked() == False:
            self.DInput.setEnabled(False)

    def PIDInput(self):
        if self.PInput.text() == "" or self.PCheckBox.checkState() == False:
            self.Pvalue = 0
        else:
            self.Pvalue = self.PInput.text()

        if self.IInput.text() == "" or self.ICheckBox.checkState() == False:
            self.Ivalue = 0
        else:
            self.Ivalue = self.IInput.text()

        if self.DInput.text() == "" or self.DCheckBox.checkState() == False:
            self.Dvalue = 0
        else:
            self.Dvalue = self.DInput.text()
        return ([self.Pvalue, self.Ivalue, self.Dvalue])

    #Function that connects output pyqtgraph widget, and the combobox
    def getInput(self):
        self.inputType = str(self.inputForms.currentText())
        pen_input = pg.mkPen(color=(255, 0, 0), width=1)

        if self.inputType == "Sine":
            print("Sine")
            self.graphWidgetInput.clear()
            self.x_input = np.arange(0, 10, 0.1)
            self.y_input = np.sin(self.x_input)
            self.data_input = self.graphWidgetInput.plot(self.x_input,
                                                         self.y_input,
                                                         pen=pen_input)
            self.data_input.setData(self.x_input, self.y_input)
            self.graphWidgetInput.setYRange(-2, 2, padding=0)

        elif self.inputType == "Step":
            print("Step")
            self.graphWidgetInput.clear()
            self.x_input = np.arange(0, 10, 0.1)
            self.y_input = np.heaviside(self.x_input, 1)
            self.data_input = self.graphWidgetInput.plot(self.x_input,
                                                         self.y_input,
                                                         pen=pen_input)
            self.data_input.setData(self.x_input, self.y_input)
            self.graphWidgetInput.setYRange(-2, 2, padding=0)

    def getLabType(self):
        self.inputType = str(self.LabType.currentText())
        if self.inputType == "Position":
            print("Lab: Position")
            return (
                self.graphWidgetOutput.setLabel(
                    'left',
                    "<span style=\"color:white;font-size:16px\">&theta; (°)</span>"
                ),
                self.graphWidgetInput.setLabel(
                    'left',
                    "<span style=\"color:white;font-size:16px\">Voltage</span>"
                ),
                self.graphWidgetOutput.setLabel(
                    'bottom',
                    "<span style=\"color:white;font-size:16px\">Time (s)</span>"
                ),
                self.graphWidgetInput.setLabel(
                    'bottom',
                    "<span style=\"color:white;font-size:16px\">Time (s)</span>"
                ))
        elif self.inputType == "Speed":
            print("Lab: Speed")
            return (
                self.graphWidgetOutput.setLabel(
                    'left',
                    "<span style=\"color:white;font-size:16px\">&omega; (°/s)</span>"
                ),
                self.graphWidgetInput.setLabel(
                    'left',
                    "<span style=\"color:white;font-size:16px\">Voltage</span>"
                ),
                self.graphWidgetOutput.setLabel(
                    'bottom',
                    "<span style=\"color:white;font-size:16px\">Time (s)</span>"
                ),
                self.graphWidgetInput.setLabel(
                    'bottom',
                    "<span style=\"color:white;font-size:16px\">Time (s)</span>"
                ),
            )
Example #27
0
class Ui_MainWindow(object):
    test_points = [(0.0, 1.0), (0.2, 1.02), (0.4, 1.08), (0.6, 1.12),
                   (0.8, 1.34), (1.0, 1.54), (1.2, 1.81), (1.4, 2.15)]

    interpolation_ins = Interpolation()

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(816, 480)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(10, 10, 121, 151))
        self.groupBox.setTitle("")
        self.groupBox.setObjectName("groupBox")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setWordWrap(True)
        self.label.setObjectName("label")
        self.verticalLayout_2.addWidget(self.label)
        self.editAppendX = QtWidgets.QLineEdit(self.groupBox)
        self.editAppendX.setAlignment(QtCore.Qt.AlignCenter)
        self.editAppendX.setObjectName("editAppendX")
        self.verticalLayout_2.addWidget(self.editAppendX)
        self.editAppendY = QtWidgets.QLineEdit(self.groupBox)
        self.editAppendY.setAlignment(QtCore.Qt.AlignCenter)
        self.editAppendY.setObjectName("editAppendY")
        self.verticalLayout_2.addWidget(self.editAppendY)
        self.appendPointBtn = QtWidgets.QPushButton(self.groupBox)
        self.appendPointBtn.setObjectName("appendPointBtn")
        self.appendPointBtn.clicked.connect(self.appendPointBtn_clicked)
        self.verticalLayout_2.addWidget(self.appendPointBtn)
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(10, 230, 121, 131))
        self.groupBox_2.setTitle("")
        self.groupBox_2.setAlignment(QtCore.Qt.AlignLeading
                                     | QtCore.Qt.AlignLeft
                                     | QtCore.Qt.AlignTop)
        self.groupBox_2.setObjectName("groupBox_2")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_2)
        self.verticalLayout.setObjectName("verticalLayout")
        self.label_2 = QtWidgets.QLabel(self.groupBox_2)
        self.label_2.setWordWrap(True)
        self.label_2.setObjectName("label_2")
        self.verticalLayout.addWidget(self.label_2)
        self.editFindX = QtWidgets.QLineEdit(self.groupBox_2)
        self.editFindX.setAlignment(QtCore.Qt.AlignCenter)
        self.editFindX.setObjectName("editFindX")
        self.verticalLayout.addWidget(self.editFindX)
        self.interpolateBtn = QtWidgets.QPushButton(self.groupBox_2)
        self.interpolateBtn.setObjectName("interpolateBtn")
        self.interpolateBtn.clicked.connect(self.interpolateBtn_clicked)
        self.verticalLayout.addWidget(self.interpolateBtn)
        # chart
        self.graphicsView = PlotWidget(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(170, 10, 621, 430))
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView0 = PlotWidget(self.centralwidget)
        self.graphicsView0.setGeometry(QtCore.QRect(170, 10, 621, 430))
        self.graphicsView0.setObjectName("graphicsView0")
        self.graphicsView0.hide()
        # Aitken table
        self.aitkenTable = QtWidgets.QTableWidget(self.centralwidget)
        self.aitkenTable.setGeometry(QtCore.QRect(170, 10, 621, 430))
        self.aitkenTable.setObjectName("aitkenTable")
        self.aitkenTable.setColumnCount(self.interpolation_ins.get_width() + 3)
        header = self.aitkenTable.horizontalHeader()
        header.setResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
        self.aitkenTable.hide()
        # Lagrangian polynomial
        self.lagrangianTextBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.lagrangianTextBrowser.setGeometry(QtCore.QRect(170, 10, 621, 430))
        self.lagrangianTextBrowser.setObjectName("lagrangianTextBrowser")
        self.lagrangianTextBrowser.hide()

        self.clearPointsBtn = QtWidgets.QPushButton(self.centralwidget)
        self.clearPointsBtn.setGeometry(QtCore.QRect(10, 180, 121, 32))
        self.clearPointsBtn.setObjectName("clearPointsBtn")
        self.clearPointsBtn.clicked.connect(self.clear_points)
        self.labelY = QtWidgets.QLabel(self.centralwidget)
        self.labelY.setGeometry(QtCore.QRect(15, 370, 130, 31))
        self.labelY.setObjectName("labelY")
        self.labelY0 = QtWidgets.QLabel(self.centralwidget)
        self.labelY0.setGeometry(QtCore.QRect(15, 390, 130, 31))
        self.labelY0.setObjectName("labelY0")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(5, 420, 151, 26))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItems([
            "Lagrangian Graph", "Aitken Graph", "Aitken Table",
            "Lagrangian Polynomial"
        ])
        self.comboBox.activated.connect(self.select_view)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 816, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "Append point to graph"))
        self.editAppendY.setPlaceholderText(_translate("MainWindow", "Y"))
        self.editAppendX.setPlaceholderText(_translate("MainWindow", "X"))
        self.appendPointBtn.setText(_translate("MainWindow", "Add Point"))
        self.label_2.setText(
            _translate("MainWindow", "Find Y for point with X coordinate"))
        self.labelY.setText(_translate("MainWindow", "Aitken Y: "))
        self.labelY0.setText(_translate("MainWindow", "Lgrngn Y: "))
        self.editFindX.setPlaceholderText(_translate("MainWindow", "X"))
        self.interpolateBtn.setText(_translate("MainWindow", "Interpolate"))
        self.clearPointsBtn.setText(_translate("MainWindow", "Clear Points"))
        self.comboBox.setItemText(0,
                                  _translate("MainWindow", "Lagrangian Graph"))
        self.comboBox.setItemText(1, _translate("MainWindow", "Aitken Graph"))
        self.comboBox.setItemText(2, _translate("MainWindow", "Aitken Table"))
        self.comboBox.setItemText(
            3, _translate("MainWindow", "Lagrangian Polynomial"))

    def clear_points(self):
        self.graphicsView.clear()
        self.graphicsView0.clear()
        self.interpolation_ins.clear_points()
        self.aitkenTable.clear()
        self.lagrangianTextBrowser.clear()

    def select_view(self, i):
        print(i)
        self.comboBox.setCurrentIndex(i)
        if i == 0:
            self.graphicsView.show()
            self.graphicsView0.hide()
            self.aitkenTable.hide()
            self.lagrangianTextBrowser.hide()
        elif i == 1:
            self.graphicsView.hide()
            self.graphicsView0.show()
            self.aitkenTable.hide()
            self.lagrangianTextBrowser.hide()
        elif i == 2:
            self.graphicsView.hide()
            self.graphicsView0.hide()
            self.aitkenTable.show()
            self.lagrangianTextBrowser.hide()
        elif i == 3:
            self.graphicsView.hide()
            self.graphicsView0.hide()
            self.aitkenTable.hide()
            self.lagrangianTextBrowser.show()

    def update_Aitken(self, points):
        self.aitkenTable.setRowCount(len(points))
        for i in range(len(points)):
            for j in range(len(points[0])):
                self.aitkenTable.setItem(
                    i, j, QtWidgets.QTableWidgetItem(str(points[i][j])))

    def update_Lagrangian(self):
        if not self.interpolation_ins.lagrangian:
            self.interpolation_ins.build_Lagrangian()
        self.lagrangianTextBrowser.clear()
        for i in self.interpolation_ins.lagrangian:
            self.lagrangianTextBrowser.append(i)
            self.lagrangianTextBrowser.append("\n")

    def add_default_points(self):
        if not len(self.interpolation_ins.get_points()):
            for (x, y) in self.test_points:
                p = Point(x, y)
                self.interpolation_ins.add_point(p)

    def appendPointBtn_clicked(self):
        try:
            x = float(self.editAppendX.text())
            y = float(self.editAppendY.text())
            p = Point(x, y)
        except Exception as e:
            print("-" * 50 + "\n", e)
            self.add_default_points()
        else:
            self.interpolation_ins.add_point(p)
        points = self.interpolation_ins.get_points()
        self.update_Lagrangian()
        self.update_Aitken(self.interpolation_ins.init_Aitken())
        self.editAppendX.setText("")
        self.editAppendY.setText("")
        massiv_x = self.scatter()
        self.small_interval_lagrangian(massiv_x)
        self.small_interval_Aitken(massiv_x)

    def scatter(self, step=0.01):
        points = self.interpolation_ins.get_points()
        start, end = points[0].get_x(), points[-1].get_x()
        massiv_x = np.arange(start, end, step)
        return massiv_x

    def small_interval_lagrangian(self, massiv_x):
        massiv_y = []
        for x in massiv_x:
            self.interpolation_ins.set_interpolation_point_x(x)
            y = self.interpolation_ins.Lagrangian_method()
            massiv_y.append(y)
        self.graphicsView.clear()
        self.graphicsView.plot(massiv_x, massiv_y)

    def small_interval_Aitken(self, massiv_x):
        massiv_y = []
        xs, ys = self.interpolation_ins.get_split_points()
        for x in massiv_x:
            y = self.interpolation_ins.method(x, xs, ys)
            massiv_y.append(y)
        self.graphicsView0.clear()
        self.graphicsView0.plot(massiv_x, massiv_y, pen=pyqtgraph.mkPen('g'))

    def interpolateBtn_clicked(self):
        try:
            x = float(self.editFindX.text())
        except Exception as e:
            print("Exception: ", e)
            return
        if not self.interpolation_ins.get_points():
            print("No points for interpolation")
        else:
            self.select_view(0)
            self.interpolation_ins.set_interpolation_point_x(x)
            xs, ys = self.interpolation_ins.get_split_points()
            y_E = self.interpolation_ins.method(x, xs, ys)
            y = self.interpolation_ins.test()
            y_L = self.interpolation_ins.Lagrangian_method()
            text = "Aitken Y: " + str(y_E)
            self.labelY.setText(text)
            text = "Lagrangian Y: " + str(y_L)
            self.labelY0.setText(text)
            if self.interpolation_ins.is_in_interval(x):
                self.update_Aitken(self.interpolation_ins.get_table())
                self.graphicsView.plot([x], [y_E], pen=None, symbol='o')
                self.graphicsView0.plot([x], [y_L],
                                        pen=pyqtgraph.mkPen('r'),
                                        symbol='o')
class Ui_MainWindow(object):
    accuracy_vals = []
    recording_vals = np.zeros([
        960 * 10 * 10,
    ])
    microphone_recorder = None
    train_thread = None
    recorder_thread = None
    ser_inference_model = SER_Inference_Model()
    ser_online_model = SER_Online_Model()
    label_7_line_nr = 0
    play_th = None

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.resize(1300, 900)

        qr = MainWindow.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        MainWindow.move(qr.topLeft())

        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setSpacing(0)
        self.gridLayout_2.setObjectName("gridLayout_2")

        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setContentsMargins(10, 10, 10, 10)
        self.verticalLayout.setSpacing(2)
        self.verticalLayout.setObjectName("verticalLayout")

        self.groupBox_4 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_4.setMinimumSize(QtCore.QSize(670, 860))
        self.groupBox_4.setObjectName("groupBox_4")

        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(40, 400, 400, 20))
        self.label_2.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_2.setObjectName("label_2")

        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(40, 400, 500, 40))
        self.progressBar.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar.setStyleSheet(COMPLETED_STYLE_ANGRY)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")

        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(40, 460, 400, 20))
        self.label_3.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_3.setObjectName("label_3")

        self.progressBar_2 = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar_2.setGeometry(QtCore.QRect(40, 460, 500, 40))
        self.progressBar_2.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar_2.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar_2.setStyleSheet(COMPLETED_STYLE_HAPPY)
        self.progressBar_2.setProperty("value", 0)
        self.progressBar_2.setObjectName("progressBar_2")

        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(40, 520, 400, 20))
        self.label_4.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_4.setObjectName("label_4")

        self.progressBar_3 = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar_3.setGeometry(QtCore.QRect(40, 520, 500, 40))
        self.progressBar_3.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar_3.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar_3.setStyleSheet(COMPLETED_STYLE_SAD)
        self.progressBar_3.setProperty("value", 0)
        self.progressBar_3.setObjectName("progressBar_3")

        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(40, 570, 400, 20))
        self.label_5.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_5.setObjectName("label_5")

        self.progressBar_4 = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar_4.setGeometry(QtCore.QRect(40, 560, 500, 40))
        self.progressBar_4.setMinimumSize(QtCore.QSize(500, 40))
        self.progressBar_4.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.progressBar_4.setProperty("value", 0)
        self.progressBar_4.setObjectName("progressBar_4")

        self.graphicsView = PlotWidget(self.groupBox_4)
        self.graphicsView.setGeometry(QtCore.QRect(10, 30, 650, 400))
        self.graphicsView.setObjectName("graphicsView")
        self.verticalLayout.addWidget(self.groupBox_4)
        self.gridLayout_2.addLayout(self.verticalLayout, 0, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 3, 1, 1)

        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setSizeConstraint(
            QtWidgets.QLayout.SetDefaultConstraint)
        self.verticalLayout_2.setContentsMargins(10, 10, 10, 10)
        self.verticalLayout_2.setSpacing(2)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_3.setMinimumSize(QtCore.QSize(603, 110))
        self.groupBox_3.setObjectName("groupBox_3")

        self.comboBox_2 = QtWidgets.QComboBox(self.groupBox_3)
        self.comboBox_2.setGeometry(QtCore.QRect(105, 72, 441, 30))
        self.comboBox_2.setObjectName("comboBox_2")

        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_2.setGeometry(QtCore.QRect(105, 35, 441, 30))
        self.lineEdit_2.setObjectName("lineEdit_2")

        self.label_9 = QtWidgets.QLabel(self.groupBox_3)
        self.label_9.setGeometry(QtCore.QRect(10, 37, 90, 30))
        self.label_9.setObjectName("label_9")

        self.label_10 = QtWidgets.QLabel(self.groupBox_3)
        self.label_10.setGeometry(QtCore.QRect(60, 71, 40, 30))
        self.label_10.setObjectName("label_10")

        self.pushButtonInfPlay = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButtonInfPlay.setGeometry(QtCore.QRect(550, 72, 48, 30))
        self.pushButtonInfPlay.setObjectName("pushButtonInfPlay")

        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setMinimumSize(QtCore.QSize(600, 280))
        self.groupBox_2.setObjectName("groupBox_2")

        self.label_18 = QtWidgets.QLabel(self.groupBox_2)
        self.label_18.setGeometry(QtCore.QRect(10, 75, 205, 25))
        self.label_18.setObjectName("label_18")

        self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox_2)
        self.radioButton_3.setGeometry(QtCore.QRect(215, 77, 165, 25))
        self.radioButton_3.setChecked(True)
        self.radioButton_3.setAutoRepeat(False)
        self.radioButton_3.setObjectName("radioButton_3")

        self.radioButton_4 = QtWidgets.QRadioButton(self.groupBox_2)
        self.radioButton_4.setGeometry(QtCore.QRect(325, 77, 120, 25))
        self.radioButton_4.setObjectName("radioButton_4")

        self.label_8 = QtWidgets.QLabel(self.groupBox_2)
        self.label_8.setGeometry(QtCore.QRect(10, 243, 94, 25))
        self.label_8.setObjectName("label_8")

        self.lineEdit = QtWidgets.QLineEdit(self.groupBox_2)
        self.lineEdit.setGeometry(QtCore.QRect(75, 240, 70, 30))
        self.lineEdit.setObjectName("lineEdit")

        self.label_17 = QtWidgets.QLabel(self.groupBox_2)
        self.label_17.setGeometry(QtCore.QRect(460, 243, 110, 30))
        self.label_17.setObjectName("label_17")

        self.label_19 = QtWidgets.QLabel(self.groupBox_2)
        self.label_19.setGeometry(QtCore.QRect(570, 243, 30, 30))
        self.label_19.setObjectName("label_19")

        self.comboBox = QtWidgets.QComboBox(self.groupBox_2)
        self.comboBox.setGeometry(QtCore.QRect(125, 38, 460, 30))
        self.comboBox.setMinimumSize(QtCore.QSize(200, 0))
        self.comboBox.setFocusPolicy(QtCore.Qt.WheelFocus)
        self.comboBox.setMaxVisibleItems(10)
        self.comboBox.setIconSize(QtCore.QSize(16, 16))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")

        self.label = QtWidgets.QLabel(self.groupBox_2)
        self.label.setGeometry(QtCore.QRect(10, 36, 105, 30))
        self.label.setObjectName("label")

        self.label_11 = QtWidgets.QLabel(self.groupBox_2)
        self.label_11.setGeometry(QtCore.QRect(10, 100, 130, 30))
        self.label_11.setObjectName("label_11")
        self.horizontalSlider = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider.setGeometry(QtCore.QRect(138, 109, 430, 17))
        self.horizontalSlider.setMaximum(10)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName("horizontalSlider")
        self.label_12 = QtWidgets.QLabel(self.groupBox_2)
        self.label_12.setGeometry(QtCore.QRect(570, 102, 31, 30))
        self.label_12.setObjectName("label_12")

        self.label_15 = QtWidgets.QLabel(self.groupBox_2)
        self.label_15.setGeometry(QtCore.QRect(10, 132, 121, 25))
        self.label_15.setObjectName("label_15")
        self.horizontalSlider_2 = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider_2.setGeometry(QtCore.QRect(138, 137, 430, 17))
        self.horizontalSlider_2.setMaximum(10)
        self.horizontalSlider_2.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider_2.setObjectName("horizontalSlider_2")
        self.label_16 = QtWidgets.QLabel(self.groupBox_2)
        self.label_16.setGeometry(QtCore.QRect(570, 134, 31, 25))
        self.label_16.setObjectName("label_15")

        self.ooda_check_box = QtWidgets.QCheckBox(self.groupBox_2)
        self.ooda_check_box.setGeometry(QtCore.QRect(15, 160, 120, 31))
        self.ooda_check_box.setObjectName("checkBoxOODA")
        self.horizontalSlider_ooda = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider_ooda.setGeometry(QtCore.QRect(138, 168, 430, 17))
        self.horizontalSlider_ooda.setMaximum(9)
        self.horizontalSlider_ooda.setMinimum(1)
        self.horizontalSlider_ooda.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider_ooda.setObjectName("horizontalSlider_ooda")
        self.label_ooda = QtWidgets.QLabel(self.groupBox_2)
        self.label_ooda.setGeometry(QtCore.QRect(570, 164, 31, 25))
        self.label_ooda.setObjectName("label_ooda")

        self.label_13 = QtWidgets.QLabel(self.groupBox_2)
        self.label_13.setGeometry(QtCore.QRect(10, 197, 121, 25))
        self.label_13.setObjectName("label_13")
        self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.groupBox_2)
        self.doubleSpinBox.setGeometry(QtCore.QRect(121, 197, 100, 31))
        self.doubleSpinBox.setDecimals(5)
        self.doubleSpinBox.setSingleStep(1e-05)
        self.doubleSpinBox.setObjectName("doubleSpinBox")

        self.verticalLayout_2.addWidget(self.groupBox_2)

        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setMinimumSize(QtCore.QSize(30, 70))
        self.groupBox.setObjectName("groupBox")

        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(10, 30, 60, 30))
        self.radioButton.setChecked(True)
        self.radioButton.setObjectName("radioButton")

        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(100, 30, 226, 30))
        self.radioButton_2.setObjectName("radioButton_2")

        self.pushButton = QtWidgets.QPushButton(self.groupBox)
        self.pushButton.setGeometry(QtCore.QRect(250, 30, 100, 30))
        self.pushButton.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButton.setIconSize(QtCore.QSize(16, 16))
        self.pushButton.setObjectName("pushButton")

        self.pushButtonStop = QtWidgets.QPushButton(self.groupBox)
        self.pushButtonStop.setGeometry(QtCore.QRect(380, 30, 100, 30))
        self.pushButtonStop.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonStop.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonStop.setObjectName("pushButtonStop")
        self.verticalLayout_2.addWidget(self.groupBox)

        self.groupBox_5 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_5.setMinimumSize(QtCore.QSize(30, 155))
        self.groupBox_5.setObjectName("groupBox_5")
        self.verticalLayout_2.addWidget(self.groupBox_3)
        self.verticalLayout_2.addWidget(self.groupBox_5)

        self.graphicsViewRec = PlotWidget(self.groupBox_5)
        self.graphicsViewRec.setGeometry(QtCore.QRect(115, 37, 480, 110))
        self.graphicsViewRec.setObjectName("graphicsViewRec")
        self.graphicsViewRec.setYRange(-20000, 20000, padding=0)
        self.graphicsViewRec.setXRange(0, 10 * 125 * 94, padding=0)

        self.pushButtonRecord = QtWidgets.QPushButton(self.groupBox_5)
        self.pushButtonRecord.setGeometry(QtCore.QRect(10, 37, 100, 30))
        self.pushButtonRecord.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonRecord.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonRecord.setObjectName("pushButtonRecord")

        self.pushButtonStopRecord = QtWidgets.QPushButton(self.groupBox_5)
        self.pushButtonStopRecord.setGeometry(QtCore.QRect(10, 77, 100, 30))
        self.pushButtonStopRecord.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonStopRecord.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonStopRecord.setObjectName("pushButtonStopRecord")

        self.pushButtonPlay = QtWidgets.QPushButton(self.groupBox_5)
        self.pushButtonPlay.setGeometry(QtCore.QRect(10, 117, 100, 30))
        self.pushButtonPlay.setMaximumSize(QtCore.QSize(100, 16777215))
        self.pushButtonPlay.setIconSize(QtCore.QSize(16, 16))
        self.pushButtonPlay.setObjectName("pushButtonPlay")

        self.tabs = QtWidgets.QTabWidget(self.groupBox_4)
        self.tabs.setGeometry(QtCore.QRect(10, 440, 600, 400))
        self.tabs.setMinimumHeight(400)
        self.tabs.setMinimumWidth(600)
        self.tabs.setIconSize(QtCore.QSize(30, 300))
        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setRowCount(5)
        self.tableWidget.setColumnCount(5)
        self.tableWidget.setHorizontalHeaderLabels(
            ["Angry", "Happy", "Sad", "Normal", " Total "])  #
        self.tableWidget.setVerticalHeaderLabels(
            ["Angry", "Happy", "Sad", "Normal", "Total"])  #

        self.tableWidget.setItem(0, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(0, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(1, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(2, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(3, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 0, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 1, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 2, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 3, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.setItem(4, 4, QtWidgets.QTableWidgetItem("0"))
        self.tableWidget.item(4, 4).setBackground(QtGui.QColor(102, 140, 255))
        self.tableWidget.item(3, 3).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(2, 2).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(1, 1).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(0, 0).setBackground(QtGui.QColor(125, 125, 125))

        for i in range(5):
            for j in range(5):
                self.tableWidget.item(i, j).setFlags(QtCore.Qt.ItemIsEnabled)
        self.tabs.resize(650, 425)

        self.label_7 = QtWidgets.QLabel(self.groupBox_4)
        self.label_7.setMinimumSize(QtCore.QSize(600, 425))
        self.label_7.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
        self.label_7.setStyleSheet("font: 9pt \"Sans Serif\";\n"
                                   "background-color: rgb(0, 0, 0);")
        self.label_7.setFrameShadow(QtWidgets.QFrame.Raised)
        self.label_7.setLineWidth(4)
        self.label_7.setTextFormat(QtCore.Qt.AutoText)
        self.label_7.setScaledContents(True)
        self.label_7.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft
                                  | QtCore.Qt.AlignTop)
        self.label_7.setWordWrap(True)
        self.label_7.setIndent(0)
        self.label_7.setOpenExternalLinks(False)
        self.label_7.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse
                                             | QtCore.Qt.TextSelectableByMouse)
        self.label_7.setObjectName("label_7")

        self.verticalLayoutTable = QtWidgets.QVBoxLayout()
        self.verticalLayoutTable.setSizeConstraint(
            QtWidgets.QLayout.SetDefaultConstraint)
        self.verticalLayoutTable.setContentsMargins(33, 95, 33, 70)
        self.verticalLayoutTable.setSpacing(9)
        self.verticalLayoutTable.setObjectName("verticalLayoutTable")

        self.label_total = QtWidgets.QLabel(self.groupBox_4)
        self.label_total.setObjectName("label_nr")

        self.tab2 = QtWidgets.QWidget()
        self.tabs.addTab(self.label_7, "Logs")
        self.tabs.addTab(self.tab2, "Confusion matrix")

        self.tab2.layout = self.verticalLayoutTable
        self.tab2.layout.addWidget(self.tableWidget)
        self.tab2.layout.addWidget(self.label_total)
        self.tab2.setLayout(self.tab2.layout)

        self.verticalLayout_2.addWidget(self.label_2)
        self.verticalLayout_2.addWidget(self.progressBar)
        self.verticalLayout_2.addWidget(self.label_3)
        self.verticalLayout_2.addWidget(self.progressBar_2)
        self.verticalLayout_2.addWidget(self.label_4)
        self.verticalLayout_2.addWidget(self.progressBar_3)
        self.verticalLayout_2.addWidget(self.label_5)
        self.verticalLayout_2.addWidget(self.progressBar_4)

        self.gridLayout.addLayout(self.verticalLayout_2, 0, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)

        self.actionReset = QtWidgets.QAction(MainWindow)
        self.actionReset.setObjectName("actionReset")

        self.retranslateUi(MainWindow)
        self.lineEdit_2.setText("Inference")
        self.lineEdit.setText("10")
        self.horizontalSlider_2.setValue(5)
        self.change_label_16()
        self.horizontalSlider.setValue(8)
        self.change_label_12()
        self.horizontalSlider_ooda.setValue(8)
        self.change_label_ooda()
        self.doubleSpinBox.setValue(0.0001)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.fill_file()
        self.ooda_check_box.setChecked(False)
        self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED)
        self.horizontalSlider_ooda.setEnabled(False)

        self.pushButton.clicked.connect(lambda: self.on_start_button_clicked())
        self.pushButtonStop.clicked.connect(
            lambda: self.on_buttonStop_clicked())
        self.pushButtonRecord.clicked.connect(
            lambda: self.on_buttonRecord_clicked())
        self.pushButtonPlay.clicked.connect(lambda: self.play_recording())
        self.pushButtonInfPlay.clicked.connect(
            lambda: self.play_recording(self.comboBox_2.currentText()))
        self.pushButtonStopRecord.clicked.connect(
            lambda: self.on_buttonStopRecord_clicked())
        self.lineEdit_2.returnPressed.connect(lambda: self.fill_file())
        self.radioButton_2.toggled.connect(lambda: self.init_inference())
        self.horizontalSlider.valueChanged.connect(
            lambda: self.change_label_12())
        self.horizontalSlider_2.valueChanged.connect(
            lambda: self.change_label_16())
        self.horizontalSlider_ooda.valueChanged.connect(
            lambda: self.change_label_ooda())
        self.ooda_check_box.stateChanged.connect(
            lambda: self.change_horizontal_ooda())
        self.print_accuracy_graph(0)

    def refresh_label_7(self):
        self.label_7_line_nr = 0
        _translate = QtCore.QCoreApplication.translate
        self.label_7.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; color:#55ff7f;\"> ...</span></p></body></html>"
            ))

    def refresh_graphics_view(self):
        self.graphicsView.clear()
        self.accuracy_vals = []
        self.print_accuracy_graph(0)

    def refresh_rec_graphics_view(self):
        self.recording_vals = np.zeros([
            960 * 10 * 10,
        ])

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "Speech Emotion Recognizer"))
        self.groupBox_4.setTitle(_translate("MainWindow", "Statistics"))
        self.groupBox_5.setTitle(_translate("MainWindow", "Recording"))
        self.label_2.setText(_translate("MainWindow", "Angry"))
        self.label_3.setText(_translate("MainWindow", "Happy"))
        self.label_4.setText(_translate("MainWindow", "Sad"))
        self.label_5.setText(_translate("MainWindow", "Neutral"))
        self.groupBox_3.setTitle(
            _translate("MainWindow", "Pick a file to classify"))
        self.label_9.setText(_translate("MainWindow", "Folder path:"))
        self.label_10.setText(_translate("MainWindow", "File:"))
        self.pushButtonInfPlay.setText(_translate("MainWindow", "Play"))
        self.groupBox_2.setTitle(_translate("MainWindow", "Model settings"))
        self.radioButton_3.setText(_translate("MainWindow", "End-to-end"))
        self.radioButton_4.setText(_translate("MainWindow", "Hand-Crafted"))
        self.label_8.setText(_translate("MainWindow", "Epochs:"))
        self.label_18.setText(
            _translate("MainWindow", "Feature extraction tehnioque:"))
        self.label_11.setText(_translate("MainWindow", "Train / Test Ratio:"))
        self.label_12.setText(_translate("MainWindow", "1"))
        self.label_13.setText(_translate("MainWindow", "Learning Rate:"))
        self.label_15.setText(_translate("MainWindow", "Dropout Rate:"))
        self.label_16.setText(_translate("MainWindow", "1"))
        self.label_17.setText(_translate("MainWindow", "Current epoch:"))
        self.label_19.setText(_translate("MainWindow", "0"))
        self.label_ooda.setText(_translate("MainWindow", "0"))
        self.label_total.setText(
            _translate("MainWindow", "Numarul total de intrari = 0"))
        self.comboBox.setItemText(0, _translate("MainWindow", "EMO-DB"))
        self.comboBox.setItemText(1, _translate("MainWindow", "SAVEE"))
        self.comboBox.setItemText(2, _translate("MainWindow", "RAVDESS"))
        self.comboBox.setItemText(3, _translate("MainWindow", "ENTERFACE"))
        self.comboBox.setItemText(4, _translate("MainWindow", "EMOVO"))
        self.comboBox.setItemText(5, _translate("MainWindow", "MAV"))
        self.comboBox.setItemText(6, _translate("MainWindow", "MELD"))
        self.comboBox.setItemText(7, _translate("MainWindow", "JL"))
        self.comboBox.setItemText(7, _translate("MainWindow", "INRP"))
        self.comboBox.setItemText(8, _translate("MainWindow", "MULTIPLE"))
        self.ooda_check_box.setText(_translate("MainWindow", "OODA loop"))
        self.label.setText(_translate("MainWindow", "Select dataset:"))
        self.groupBox.setTitle(_translate("MainWindow", "Actions"))
        self.radioButton.setToolTip(
            _translate(
                "MainWindow",
                "<html><head/><body><p align=\"center\"><br/></p></body></html>"
            ))
        self.radioButton.setText(_translate("MainWindow", "Train"))
        self.radioButton_2.setText(_translate("MainWindow", "Inference"))
        self.pushButton.setText(_translate("MainWindow", "Start"))
        self.pushButtonStop.setText(_translate("MainWindow", "Stop"))
        self.pushButtonRecord.setText(_translate("MainWindow", "Record"))
        self.pushButtonPlay.setText(_translate("MainWindow", "Play"))
        self.pushButtonStopRecord.setText(_translate("MainWindow", "Stop"))
        self.label_7.setText(
            _translate(
                "MainWindow",
                "<html><head/><body><p><span style=\" font-weight:600; color:#55ff7f;\"> ...</span></p></body></html>"
            ))
        self.actionReset.setText(_translate("MainWindow", "Reset"))
        self.pushButtonRecord.setEnabled(False)
        self.pushButtonStopRecord.setEnabled(False)
        self.pushButtonStop.setEnabled(False)
        self.pushButtonPlay.setEnabled(False)
        self.pushButtonInfPlay.setEnabled(False)

        self.progressBar.setEnabled(False)
        self.progressBar_2.setEnabled(False)
        self.progressBar_3.setEnabled(False)
        self.progressBar_4.setEnabled(False)
        self.label_2.setEnabled(False)
        self.label_3.setEnabled(False)
        self.label_4.setEnabled(False)
        self.label_5.setEnabled(False)
        self.groupBox_3.setEnabled(False)
        self.groupBox_5.setEnabled(False)

        self.graphicsViewRec.setYRange(-20000, 20000, padding=0)
        self.graphicsViewRec.setXRange(0, 10 * 960 * 10, padding=0)
        self.graphicsViewRec.getPlotItem().hideButtons()
        self.graphicsViewRec.getPlotItem().hideAxis('left')
        self.graphicsViewRec.getPlotItem().hideAxis('bottom')

    def print_accuracy_graph(self, accuracy):
        self.accuracy_vals.append(accuracy)
        self.graphicsView.plot(self.accuracy_vals)

    def print_recording_graph(self, frames=None):
        self.graphicsViewRec.clear()
        self.recording_vals[0:9 * 960 *
                            10] = self.recording_vals[1 * 960 * 10:10 * 10 *
                                                      960]
        self.recording_vals[9 * 960 * 10:10 * 960 * 10] = frames
        self.graphicsViewRec.plot(self.recording_vals)

    def print_stats_model(self, string):
        self.print_in_label_7(string)

    def print_label_19(self, epoch):
        self.label_19.setText(epoch)

    def print_accuracy_matrix(self, matrix):
        for i in range(matrix.shape[0]):
            for j in range(matrix.shape[1]):
                self.tableWidget.setItem(
                    i, j, QtWidgets.QTableWidgetItem(str(matrix[i][j])))
        for i in range(4):
            self.tableWidget.setItem(
                4, i, QtWidgets.QTableWidgetItem(str(np.sum(matrix[:, i]))))
            self.tableWidget.setItem(
                i, 4, QtWidgets.QTableWidgetItem(str(np.sum(matrix[i]))))
        self.tableWidget.setItem(
            4, 4, QtWidgets.QTableWidgetItem(str(np.sum(np.diag(matrix)))))
        self.tableWidget.item(4, 4).setBackground(QtGui.QColor(102, 140, 255))
        self.tableWidget.item(3, 3).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(2, 2).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(1, 1).setBackground(QtGui.QColor(125, 125, 125))
        self.tableWidget.item(0, 0).setBackground(QtGui.QColor(125, 125, 125))
        for i in range(5):
            for j in range(5):
                self.tableWidget.item(i, j).setFlags(QtCore.Qt.ItemIsEnabled)

    def open_alert_dialog(self, title="Alert", text="...", info="..."):
        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Critical)

        msg.setWindowTitle(title)
        msg.setText(text)
        msg.setInformativeText(info)
        msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
        msg.exec_()

    def on_start_button_clicked(self):
        if self.radioButton.isChecked():  # training
            self.pushButton.setEnabled(False)
            self.pushButtonStop.setEnabled(True)
            self.radioButton_2.setEnabled(False)
            self.refresh_label_7()
            self.refresh_graphics_view()
            self.train_thread = Train_App(self)
            self.train_thread.print_accuracy_signal.connect(
                self.print_accuracy_graph)
            self.train_thread.print_stats.connect(self.print_stats_model)
            self.train_thread.print_matrix.connect(self.print_accuracy_matrix)
            self.train_thread.print_epoch.connect(self.print_label_19)
            self.train_thread.start()
        elif self.radioButton_2.isChecked():  # inference
            vals = self.ser_inference_model.inference(
                self.comboBox_2.currentText()) * 100
            self.progressBar.setValue(vals[0])
            self.progressBar_2.setValue(vals[1])
            self.progressBar_3.setValue(vals[2])
            self.progressBar_4.setValue(vals[3])
            self.print_in_label_7(str(list(map('{:.8f}'.format, vals))))
        pass

    def on_buttonStop_clicked(self):
        if self.train_thread != None:
            self.train_thread.stopFlag = True
        pass

    def change_label_16(self):
        self.label_16.setText(str(float(self.horizontalSlider_2.value()) / 10))

    def change_label_12(self):
        self.label_12.setText(str(float(self.horizontalSlider.value()) / 10))

    def change_label_ooda(self):
        self.label_ooda.setText(
            str(float(self.horizontalSlider_ooda.value()) / 10))

    def change_horizontal_ooda(self):
        if self.ooda_check_box.isChecked():
            self.horizontalSlider_ooda.setStyleSheet(SLYDER_ENABLED)
            self.horizontalSlider_ooda.setEnabled(True)
        else:
            self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider_ooda.setEnabled(False)
        self.label_ooda.setEnabled(self.ooda_check_box.isChecked())

    def fill_file(self):
        self.ser_inference_model.files = get_files_from_directory(
            self.lineEdit_2.text())
        self.comboBox_2.clear()
        for file in self.ser_inference_model.files:
            self.comboBox_2.addItem(file)
        if self.radioButton_2.isChecked():  # inference
            self.pushButton.setEnabled(True)
            self.pushButtonInfPlay.setEnabled(True)
            self.ser_inference_model.init_model(self.lineEdit_2.text())
            if self.ser_inference_model.model == None:
                self.open_alert_dialog(
                    title="Missing Inference inference_files Alert",
                    text=
                    "We could no find any inference_files to classify in the stated folder.",
                    info=
                    "You can continue the inference process by using the online model."
                )
                self.pushButton.setEnabled(False)
                self.pushButtonInfPlay.setEnabled(False)
            self.ser_online_model.init_online_model()

    def init_inference(self):
        if self.radioButton_2.isChecked():  # inference
            if self.radioButton_4.isChecked():
                self.open_alert_dialog(
                    title=
                    "Inference is not available for hand-crafted extraction",
                    text=
                    "Hand-crafted feature extraction is used only as a baseline.",
                    info=
                    "Please train your model using the end-to-ed extraction method in order to make inference available."
                )
                self.radioButton.setChecked(True)
                self.radioButton_2.setChecked(False)
                return
            if [f for f in os.listdir("model") if not f.startswith('.')] == []:
                self.open_alert_dialog(
                    title="Missing model for Inference",
                    text="There is no machine learning model to be loaded.",
                    info=
                    "Please use the training mode to train a model before inference."
                )
                self.radioButton.setChecked(True)
                self.radioButton_2.setChecked(False)
                return
            self.pushButtonRecord.setEnabled(True)
            self.pushButtonInfPlay.setEnabled(True)
            self.progressBar.setEnabled(True)
            self.progressBar_2.setEnabled(True)
            self.progressBar_3.setEnabled(True)
            self.progressBar_4.setEnabled(True)
            self.label_2.setEnabled(True)
            self.label_3.setEnabled(True)
            self.label_4.setEnabled(True)
            self.label_5.setEnabled(True)
            self.groupBox_3.setEnabled(True)
            self.groupBox_5.setEnabled(True)
            self.groupBox_2.setEnabled(False)
            self.horizontalSlider.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider.setEnabled(False)
            self.horizontalSlider_2.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider_2.setEnabled(False)
            self.horizontalSlider_ooda.setStyleSheet(SLYDER_DISABLED)
            self.horizontalSlider_ooda.setEnabled(False)
            self.ser_inference_model.init_model(self.lineEdit_2.text())
            if self.ser_inference_model.model == None:
                self.open_alert_dialog(
                    title="Missing Inference inference_files Alert",
                    text=
                    "We could no find any inference_files to classify in the stated folder.",
                    info=
                    "You can continue the inference process by using the online model."
                )
                self.pushButton.setEnabled(False)
                self.pushButtonInfPlay.setEnabled(False)
            self.ser_online_model.init_online_model()
        elif self.ser_inference_model.session != None and self.radioButton.isChecked(
        ):
            self.pushButton.setEnabled(True)
            self.groupBox_2.setEnabled(True)
            self.pushButtonRecord.setEnabled(False)
            self.pushButtonInfPlay.setEnabled(False)
            self.pushButtonStopRecord.setEnabled(False)
            self.progressBar.setValue(0)
            self.progressBar.setEnabled(False)
            self.progressBar_2.setValue(0)
            self.progressBar_2.setEnabled(False)
            self.progressBar_3.setValue(0)
            self.progressBar_3.setEnabled(False)
            self.progressBar_4.setValue(0)
            self.progressBar_4.setEnabled(False)
            self.label_2.setEnabled(False)
            self.label_3.setEnabled(False)
            self.label_4.setEnabled(False)
            self.label_5.setEnabled(False)
            self.groupBox_3.setEnabled(False)
            self.groupBox_5.setEnabled(False)
            self.horizontalSlider.setStyleSheet(SLYDER_ENABLED)
            self.horizontalSlider.setEnabled(True)
            self.horizontalSlider_2.setStyleSheet(SLYDER_ENABLED)
            self.horizontalSlider_2.setEnabled(True)
            self.change_horizontal_ooda()
            self.ser_inference_model.close_model()

    def on_buttonRecord_clicked(self):
        self.refresh_rec_graphics_view()
        self.microphone_recorder = MicrophoneRecorder()
        if not self.microphone_recorder.check_device_availability():
            return
        self.recorder_thread = Record_App(self, self.microphone_recorder)
        self.recorder_thread.print_recording_signal.connect(
            self.print_recording_graph)
        self.recorder_thread.start()
        self.pushButtonStopRecord.setEnabled(True)
        self.pushButton.setEnabled(False)
        self.pushButtonInfPlay.setEnabled(False)
        self.pushButtonPlay.setEnabled(False)

    def on_buttonStopRecord_clicked(self):
        import librosa
        import pyaudio
        self.microphone_recorder.close()
        vals = []
        if np.array(self.microphone_recorder.get_frames()).shape[0] > 30:
            self.pushButtonPlay.setEnabled(True)
            self.microphone_recorder.save_to_wav()
            frames, _ = librosa.load("output.wav", 16000)
            vals = self.ser_online_model.online(frames, 44100) * 100
        else:
            self.pushButtonPlay.setEnabled(False)
            vals = [0 for _ in range(4)]
        self.progressBar.setValue(vals[0])
        self.progressBar_2.setValue(vals[1])
        self.progressBar_3.setValue(vals[2])
        self.progressBar_4.setValue(vals[3])
        self.print_in_label_7(str(list(map('{:.8f}'.format, vals))))
        self.pushButton.setEnabled(True)
        self.pushButtonRecord.setEnabled(True)
        self.pushButtonStopRecord.setEnabled(False)
        self.pushButtonInfPlay.setEnabled(True)
        self.pushButtonPlay.setEnabled(True)

    def print_in_label_7(self, str):
        _translate = QtCore.QCoreApplication.translate
        self.label_7_line_nr += 1
        if self.label_7_line_nr >= 24:
            txt = self.label_7.text().split("<html>")
            txt = "<html>".join(txt[1:25])
            self.label_7.setText(
                _translate(
                    "MainWindow", txt +
                    "<html><head/><body><span style=\" font-weight:600; color:#55ff7f;\">"
                    + str + "</span></body></html>"))
        else:
            self.label_7.setText(
                _translate(
                    "MainWindow",
                    self.label_7.text() +
                    "<html><head/><body><span style=\" font-weight:600; color:#55ff7f;\">"
                    + str + "</span></body></html>"))
        import time

    def play_recording(self, file="output.wav"):
        self.play_th = Play_App(self, file)
        self.play_th.start()
Example #29
0
class MaskInterpolator(QWidget):
    """
    Define masks based on an image file for two frames, then interpolate
    the masks for the intermediate frames. Also includes options to apply
    these masks to a target file.

    """
    def __init__(self, parent=None):
        super(MaskInterpolator, self).__init__(parent=parent)
        self.initUI()

    def initUI(self):

        # Main layout
        self.win = QWidget()
        L_master = QGridLayout(self.win)
        self.win.setWindowTitle("Mask interpolator")

        # Widget alignment
        widget_align = Qt.AlignLeft

        # Display the masks, when defined
        self.plotWidget = PlotWidget()
        L_master.addWidget(self.plotWidget, 0, 0, 1, 2, alignment=widget_align)

        # Button to select the first mask file
        self.B_select_mask_0 = QPushButton("Choose mask channel file 1", parent=self.win)
        self.B_select_mask_0.clicked.connect(self.B_select_mask_0_callback)
        L_master.addWidget(self.B_select_mask_0, 1, 0, 1, 1, alignment=widget_align)

        # Show the currently selected mask file 1
        self.mask_file_0_label = QLabel(parent=self.win)
        L_master.addWidget(self.mask_file_0_label, 2, 0, 1, 1, alignment=widget_align)

        # Generate the first set of masks
        self.B_generate_masks_0 = QPushButton("Draw mask 1", parent=self.win)
        self.B_generate_masks_0.clicked.connect(self.B_generate_masks_0_callback)
        L_master.addWidget(self.B_generate_masks_0, 3, 0, 1, 1, alignment=widget_align)

        # Alternatively, load masks from an existing file
        self.B_load_mask_0 = QPushButton("Load mask 1", parent=self.win)
        self.B_load_mask_0.clicked.connect(self.B_load_mask_0_callback)
        L_master.addWidget(self.B_load_mask_0, 4, 0, 1, 1, alignment=widget_align)

        # Button to select the second mask file
        self.B_select_mask_1 = QPushButton("Choose mask channel file 2", parent=self.win)
        self.B_select_mask_1.clicked.connect(self.B_select_mask_1_callback)
        L_master.addWidget(self.B_select_mask_1, 5, 0, 1, 1, alignment=widget_align)

        # Show the currently selected mask file 2
        self.mask_file_1_label = QLabel(parent=self.win)
        L_master.addWidget(self.mask_file_1_label, 6, 0, 1, 1, alignment=widget_align)

        # Generate the first set of masks
        self.B_generate_masks_1 = QPushButton("Draw mask 2", parent=self.win)
        self.B_generate_masks_1.clicked.connect(self.B_generate_masks_1_callback)
        L_master.addWidget(self.B_generate_masks_1, 7, 0, 1, 1, alignment=widget_align)       

        # Alternatively, load masks from an existing file
        self.B_load_mask_1 = QPushButton("Load mask 2", parent=self.win)
        self.B_load_mask_1.clicked.connect(self.B_load_mask_1_callback)
        L_master.addWidget(self.B_load_mask_1, 8, 0, 1, 1, alignment=widget_align)

        # Apply the set of masks to a file
        self.B_apply = QPushButton("Apply masks", parent=self)
        self.B_apply.clicked.connect(self.B_apply_callback)
        L_master.addWidget(self.B_apply, 9, 0, 1, 1, alignment=widget_align)

        # Show the main window
        self.win.show()

    ## CORE FUNCTIONS

    def get_currdir(self):
        """
        Get the last directory that was accessed by the user. If 
        no directory was previously accessed, then this is just 
        the same directory as the image file.

        """
        if not hasattr(self, "_currdir"):
            self.set_currdir(os.getcwd())
        return self._currdir

    def set_currdir(self, path):
        """
        Set the directory returned by self.get_currdir().

        args
        ----
            path            :   str, a file path or directory path. If 
                                a file path, its parent directory is used.

        """
        if os.path.isfile(path):
            self._currdir = os.path.split(os.path.abspath(path))[0]
        elif os.path.isdir(path):
            self._currdir = path

    def update_label(self, text, label=0):
        """
        args
        ----
            text        :   str, text to display in the QLabel
            label       :   0 or 1, corresponding to 
                            self.mask_file_0_label or 
                            self.mask_file_1_label respectively

        """
        if label == 0:
            self.mask_file_0_label.setText(text)
        elif label == 1:
            self.mask_file_1_label.setText(text)

    def select_mask_file(self, index):
        """
        Prompt the user to select an image file to user for masking.

        args
        ----
            index       :   int, either 0 or 1. If 0, the first mask 
                            file is selected and otherwise the second
                            mask is selected

        """
        path = getOpenFilePath(self.win, "Select masking channel file %d" % (index+1),
            "Image files (*.tif *.tiff *.nd2)",
            initialdir=self.get_currdir())
        self.set_currdir(path)
        self.update_label("{} (no masks defined)".format(path), label=index)
        setattr(self, "mask_path_{}".format(index), path)

        # Delete previously defined masks, if any
        if hasattr(self, "mask_edges_{}".format(index)):
            delattr(self, "mask_edges_{}".format(index))

    def load_mask(self, index, trial_interpolate=False, plot=False):
        """
        Load preexisting masks from a file.

        """
        # Prompt the user to enter a mask definitions file
        path = getOpenFilePath(self.win, "Select mask definitions %d" % (index+1),
            "Mask edge or image files (*.csv *.tif *.tiff *.nd2)",
            initialdir=self.get_currdir())
        self.set_currdir(path)

        # Delete the previously defined masks, if any
        if hasattr(self, "mask_path_{}".format(index)):
            delattr(self, "mask_path_{}".format(index))
        if hasattr(self, "mask_edges_{}".format(index)):
            delattr(self, "mask_edges_{}".format(index))

        # Calculate edges from this mask
        ext = os.path.splitext(path)[-1]
        if ext == ".csv":
            try:
                df = pd.read_csv(path)
                for c in ["filename", "mask_index", "y", "x", "vertex"]:
                    assert c in df.columns
            except:
                print("File {} not in the correct format; must be a CSV with " \
                    "the 'filename', 'mask_index', 'y', 'x', and 'vertex' " \
                    "columns".format(path))
                return 

            # Take only the first mask encountered
            mask_indices = df["mask_index"].unique()
            points = [np.asarray(df.loc[df["mask_index"] == mask_indices[0], ["y", "x"]])]

        elif ext in [".tif", ".tiff", ".nd2"]:
            with ImageReader(path) as f:
                mask_im = f.get_frame(0)
            edges = get_edges(mask_im>0)
            points = [get_ordered_mask_points(edges, max_points=200)]           

        setattr(self, "mask_edges_{}".format(index), points) 
        setattr(self, "mask_path_{}".format(index), path)
        self.update_label("{} ({} masks defined)".format(path, len(points)), index)

        # Show a trial interpolation (only if the other 
        # mask is also defined)
        if trial_interpolate and hasattr(self, "mask_edges_{}".format(1-index)):
            interpolator = QuotMaskInterpolator(
                [self.mask_edges_0[0], self.mask_edges_1[0]],
                [0, 100],
                n_vertices=101,
                interp_kind="linear",
                plot=False,
            )
            self.plot_mask_edges_interpolated(interpolator)

        elif plot:
            edges_0 = getattr(self, "mask_edges_0") if hasattr(self, "mask_edges_0") else None
            edges_1 = getattr(self, "mask_edges_1") if hasattr(self, "mask_edges_1") else None
            self.plot_mask_edges(edges_0=edges_0, edges_1=edges_1)

    def generate_masks(self, index, plot=False, trial_interpolate=False):
        """
        Prompt the user to define some masks. 

        args
        ----
            index       :   int, either 0 or 1. If 0, generate masks from
                            self.mask_path_0. If 1, generate masks from 
                            self.mask_path_1. 
            plot        :   bool, update the plot with the new masks
            trial_interpolate   :   bool, show a trial interpolation

        """
        # If the user has not yet selected a mask file, bail
        if not hasattr(self, "mask_path_{}".format(index)):
            print("Mask file {} not selected".format(index))
            return 
        else:
            path = getattr(self, "mask_path_{}".format(index))

        # Prompt the user to enter some masks
        ex = Masker(path, dialog_mode=True, parent=self.win)

        # If the user accepts the definitions, save
        if ex.exec_() == QDialog.Accepted:
            setattr(self, "mask_edges_{}".format(index), ex.return_val)
            self.update_label("{} ({} masks defined)".format(path, len(ex.return_val)), index)

            # Show a trial interpolation (only if the other 
            # mask is also defined)
            if trial_interpolate and hasattr(self, "mask_edges_{}".format(1-index)):
                interpolator = QuotMaskInterpolator(
                    [self.mask_edges_0[0], self.mask_edges_1[0]],
                    [0, 100],
                    n_vertices=101,
                    interp_kind="linear",
                    plot=False,
                )
                self.plot_mask_edges_interpolated(interpolator)

            elif plot:
                edges_0 = getattr(self, "mask_edges_0") if hasattr(self, "mask_edges_0") else None
                edges_1 = getattr(self, "mask_edges_1") if hasattr(self, "mask_edges_1") else None
                self.plot_mask_edges(edges_0=edges_0, edges_1=edges_1)

        else:
            print("Dialog canceled")

    def plot_mask_edges(self, edges_0=None, edges_1=None):
        """
        Plot a set of mask edges on the raw image.

        args
        ----
            edges_0         :   list of 2D ndarray of shape (n_points, 2),
                                the YX coordinates of each mask in the first
                                set
            edges_1         :   list of 2D ndarray of shape (n_points, 2),
                                the YX coordinates of each mask in the second
                                set

        """
        self.plotWidget.clear()
        if not edges_0 is None:
            for mask_edge in edges_0:
                M = np.concatenate((mask_edge, np.array([mask_edge[0,:]])), axis=0)
                self.plotWidget.plot(M[:,0], M[:,1], pen=(127, 253, 186))
        if not edges_1 is None:
            for mask_edge in edges_1:
                M = np.concatenate((mask_edge, np.array([mask_edge[0,:]])), axis=0)
                self.plotWidget.plot(M[:,0], M[:,1], pen=(36, 255, 28))           

    def plot_mask_edges_interpolated(self, quot_mask_interpolator):
        """
        Plot the interpolated set of mask edges.

        args
        ----
            quot_mask_interpolated      :   quot.mask.MaskInterpolator

        """
        E = quot_mask_interpolator.mask_edges
        mask_edges_0 = [E[:,0,:]]
        mask_edges_1 = [E[:,1,:]]
        self.plot_mask_edges(edges_0=mask_edges_0, edges_1=mask_edges_1)
        for j in range(E.shape[0]):
            self.plotWidget.plot(
                [mask_edges_0[0][j,0], mask_edges_1[0][j,0]],
                [mask_edges_0[0][j,1], mask_edges_1[0][j,1]],
                pen=(255, 165, 28)
            )

    def apply_masks(self, mode="single_point"):
        """
        Apply the currently defined masks to a set of localizations.

        """
        if not hasattr(self, "mask_edges_0"):
            print("Must define masks before applying to an image")
            return 

        # Prompt the user to select a file to apply the masks to 
        locs_file = getOpenFilePath(self.win, "Select localization CSV",
            "CSV files (*.csv)",
            initialdir=self.get_currdir())
        self.set_currdir(locs_file)
        locs = pd.read_csv(locs_file)

        # Only one set of masks defined - run static masking
        if not hasattr(self, "mask_edges_1"):
            mask_edges = [self.mask_edges_0[0]]
            mask_frames = [0]

        # Both sets of masks defined - run mask interpolation
        else:
            mask_edges = [self.mask_edges_0[0], self.mask_edges_1[0]]
            mask_frames = [0, int(locs["frame"].max()+1)]
        
        # Generate the mask interpolator
        print("Generating interpolator...")
        interpolator = QuotMaskInterpolator(mask_edges, mask_frames, n_vertices=101,
            interp_kind="linear", plot=False)

        # Plot the interpolated masks
        self.plot_mask_edges_interpolated(interpolator)

        # Run interpolation on the target set of localizations
        print("Running masking on the set of localizations...")
        locs["mask_index"] = interpolator(locs[['y', 'x']], locs['frame'],
            progress_bar=True)
        print(locs["mask_index"].unique())

        if mode == "single_point":
            locs = locs.join(
                locs.groupby("trajectory")["mask_index"].max().rename("_mask_index"),
                on="trajectory"
            )
            locs["mask_index"] = locs["_mask_index"]
            locs = locs.drop("_mask_index", axis=1)
        elif mode == "all_points":
            locs = locs.join(
                (locs.groupby("trajectory")["mask_index"].nunique() != 1).rename("_cross_border"),
                on="trajectory"
            )
            locs.loc[locs["_cross_border"], "mask_index"] = 0
            locs = locs.drop("_cross_border", axis=1)

        # Save to the same file
        print("Saving masked localizations to new files...")
        out_file_inside = "{}_in_mask.csv".format(os.path.splitext(locs_file)[0])
        out_file_outside = "{}_outside_mask.csv".format(os.path.splitext(locs_file)[0])
        locs[locs["mask_index"]>0].to_csv(out_file_inside, index=False)
        locs[locs["mask_index"]==0].to_csv(out_file_outside, index=False)
        print(locs["mask_index"].unique())

        print("Finished applying mask to localizations; now plotting...")

        point_sets = [
            interpolator.interpolate(frame)for frame \
                in np.linspace(
                    0,
                    int(locs["frame"].max()),
                    50
                ).astype(np.int64)
        ]

        show_mask_assignments(
            point_sets,
            locs,
            mask_col="mask_index",
            max_points_scatter=5000
        )

        print("Finished plotting")


    ## WIDGET CALLBACKS 

    def B_select_mask_0_callback(self):
        self.select_mask_file(0)

    def B_load_mask_0_callback(self):
        self.load_mask(0, plot=True, trial_interpolate=True)

    def B_select_mask_1_callback(self):
        self.select_mask_file(1)

    def B_generate_masks_0_callback(self):
        self.generate_masks(0, plot=True, trial_interpolate=True)

    def B_load_mask_1_callback(self):
        self.load_mask(1, plot=True, trial_interpolate=True) 

    def B_generate_masks_1_callback(self):
        self.generate_masks(1, trial_interpolate=True, plot=True)

    def B_apply_callback(self):

        # Prompt the user to select the way to apply masks
        options = ["by_localization", "single_point", "all_points"]
        box = SingleComboBoxDialog("Method by which trajectories are assigned to masks",
            options, init_value="single_point", title="Assignment mode", parent=self)
        box.exec_()
        if box.Accepted:
            mode = box.return_val 
        else:
            print("Dialog not accepted")
            return 

        self.apply_masks(mode=mode)
class Ui_MainWindow(QDialog):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(926, 645)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.widget = PlotWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(20, 30, 611, 381))
        self.widget.setObjectName("widget")
        self.widget.setBackground('w')
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(660, 430, 112, 34))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.browsefiles)  #click function
        self.buttonclear = QtWidgets.QPushButton(self.centralwidget)
        self.buttonclear.setGeometry(QtCore.QRect(500, 450, 112, 34))
        self.buttonclear.setObjectName("clearbutton")
        self.buttonclear.clicked.connect(self.cleargraph)  #click function
        self.horizontalScrollBar = QtWidgets.QScrollBar(self.centralwidget)
        self.horizontalScrollBar.setGeometry(QtCore.QRect(10, 430, 621, 20))
        self.horizontalScrollBar.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalScrollBar.setObjectName("horizontalScrollBar")
        self.verticalScrollBar = QtWidgets.QScrollBar(self.centralwidget)
        self.verticalScrollBar.setGeometry(QtCore.QRect(640, 40, 20, 381))
        self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
        self.verticalScrollBar.setObjectName("verticalScrollBar")
        self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(689, 19, 181, 401))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.checkBoxTemp = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxTemp.setEnabled(True)
        self.checkBoxTemp.setObjectName("checkBoxTemp")
        self.checkBoxTemp.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxTemp)
        self.checkBoxPres = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxPres.setObjectName("checkBoxPres")
        self.checkBoxPres.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxPres)
        self.checkBoxPH = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxPH.setObjectName("checkBoxPH")
        self.checkBoxPH.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxPH)
        self.checkBoxDO2 = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxDO2.setObjectName("checkBoxDO2")
        self.checkBoxDO2.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxDO2)
        self.checkBoxAIR = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxAIR.setObjectName("checkBoxAIR")
        self.checkBoxAIR.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxAIR)
        self.checkBoxO2 = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxO2.setObjectName("checkBoxO2")
        self.checkBoxO2.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxO2)
        self.checkBoxCO2 = QtWidgets.QCheckBox(self.verticalLayoutWidget)
        self.checkBoxCO2.setObjectName("checkBoxCO2")
        self.checkBoxCO2.stateChanged.connect(self.checked_item)
        self.verticalLayout.addWidget(self.checkBoxCO2)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 926, 31))
        self.menubar.setObjectName("menubar")
        self.menuCharts = QtWidgets.QMenu(self.menubar)
        self.menuCharts.setObjectName("menuCharts")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar.addAction(self.menuCharts.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Export"))
        self.buttonclear.setText(_translate("MainWindow", "Clear"))
        self.checkBoxTemp.setText(_translate("MainWindow",
                                             "Temperature - Red"))
        self.checkBoxPres.setText(_translate("MainWindow",
                                             "Pressure - Orange"))
        self.checkBoxPH.setText(_translate("MainWindow", "pH - Yellow"))
        self.checkBoxDO2.setText(_translate("MainWindow", "dO2 - Green"))
        self.checkBoxAIR.setText(_translate("MainWindow", "Airflow - Blue"))
        self.checkBoxO2.setText(_translate("MainWindow", "O2 Flow - Purple"))
        self.checkBoxCO2.setText(_translate("MainWindow", "CO2 Flow - Pink"))
        self.menuCharts.setTitle(_translate("MainWindow", "Charts"))

    def browsefiles(self):
        fname = QFileDialog.getSaveFileName(self, 'Open File', 'D:\Documents')

    def cleargraph(self):

        if self.checkBoxTemp.isChecked():
            self.checkBoxTemp.setCheckState(0)
            self.widget.clear()

        if self.checkBoxPres.isChecked():
            self.checkBoxPres.setCheckState(0)
            self.widget.clear()

        if self.checkBoxPH.isChecked():
            self.checkBoxPH.setCheckState(0)
            self.widget.clear()

        if self.checkBoxDO2.isChecked():
            self.checkBoxDO2.setCheckState(0)
            self.widget.clear()

        if self.checkBoxAIR.isChecked():
            self.checkBoxAIR.setCheckState(0)
            self.widget.clear()

        if self.checkBoxO2.isChecked():
            self.checkBoxO2.setCheckState(0)
            self.widget.clear()

        if self.checkBoxCO2.isChecked():
            self.checkBoxCO2.setCheckState(0)
            self.widget.clear()

    def checked_item(self):
        if self.checkBoxTemp.isChecked():
            x = [1, 2, 3]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(255, 0, 0), width=3)
            self.widget.plot(x, y, pen=pen)

        if self.checkBoxPres.isChecked():
            x = [2, 3, 4]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(255, 155, 55), width=3)
            self.widget.plot(x, y, pen=pen)

        if self.checkBoxPH.isChecked():
            x = [3, 4, 5]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(255, 255, 0), width=3)
            self.widget.plot(x, y, pen=pen)

        if self.checkBoxDO2.isChecked():
            x = [4, 5, 6]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(100, 200, 50), width=3)
            self.widget.plot(x, y, pen=pen)

        if self.checkBoxAIR.isChecked():
            x = [5, 6, 7]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(0, 0, 255), width=3)
            self.widget.plot(x, y, pen=pen)

        if self.checkBoxO2.isChecked():
            x = [6, 7, 8]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(200, 0, 255), width=3)
            self.widget.plot(x, y, pen=pen)

        if self.checkBoxCO2.isChecked():
            x = [7, 8, 9]
            y = [2, 3, 4]
            pen = pg.mkPen(color=(248, 24, 148), width=3)
            self.widget.plot(x, y, pen=pen)
class Ui_StateWise(object):
    def setupUi(self, StateWise):
        QtGui.QFontDatabase.addApplicationFont(
            resource_path("Pictures/BankGothic Md BT.ttf"))
        StateWise.setObjectName("StateWise")
        StateWise.resize(546, 539)
        StateWise.setFixedSize(StateWise.size())
        self.centralwidget = QtWidgets.QWidget(StateWise)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(0, 0, 546, 60))
        font = QtGui.QFont()
        font.setFamily("BankGothic Md BT")
        font.setPointSize(18)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(20, 100, 300, 41))
        font = QtGui.QFont()
        font.setFamily("BankGothic Md BT")
        font.setPointSize(14)
        font.setBold(False)
        font.setWeight(50)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect(360, 110, 161, 22))
        self.comboBox.setObjectName("comboBox")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(20, 150, 126, 60))
        font = QtGui.QFont()
        font.setFamily("BankGothic Md BT")
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(100)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(145, 150, 126, 60))
        font = QtGui.QFont()
        font.setFamily("BankGothic Md BT")
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(100)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(270, 150, 126, 60))
        font = QtGui.QFont()
        font.setFamily("BankGothic Md BT")
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(100)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(395, 150, 126, 60))
        font = QtGui.QFont()
        font.setFamily("BankGothic Md BT")
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(100)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.graphWidget = PlotWidget(self.centralwidget)
        self.graphWidget.setGeometry(QtCore.QRect(20, 230, 501, 251))
        self.graphWidget.setObjectName("graphWidget")
        StateWise.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(StateWise)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 546, 26))
        self.menubar.setObjectName("menubar")
        StateWise.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(StateWise)
        self.statusbar.setObjectName("statusbar")
        StateWise.setStatusBar(self.statusbar)
        self.comboBox.currentIndexChanged.connect(self.updates)
        StateWise.setStyleSheet("background-color:#fff9ea")
        self.comboBox_2 = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox_2.setGeometry(QtCore.QRect(360, 485, 161, 22))
        self.comboBox_2.setObjectName("comboBox_2")
        self.comboBox_2.currentIndexChanged.connect(self.updateGraph)
        self.retranslateUi(StateWise)
        QtCore.QMetaObject.connectSlotsByName(StateWise)

    def updateGraph(self):
        val = self.comboBox.currentText()

        stateCode = stateDict[val]
        stateDC = statedaily.loc[statedaily["Status"] == "Confirmed"]
        stateDR = statedaily.loc[statedaily["Status"] == "Recovered"]
        stateDD = statedaily.loc[statedaily["Status"] == "Deceased"]
        stateDCVal = list(stateDC[stateCode])
        stateDRVal = list(stateDR[stateCode])
        stateDDVal = list(stateDD[stateCode])
        stateDates = list(stateDC["Date"])
        tmp = self.comboBox_2.currentText()
        if (tmp == "Confirmed"):
            self.plot(stateDates, stateDCVal)
        if (tmp == "Recovered"):
            self.plot(stateDates,
                      stateDRVal,
                      c1='#C0E5C8',
                      c2='#E4F4E8',
                      c3='#29A746')
        if (tmp == "Deceased"):
            self.plot(stateDates,
                      stateDDVal,
                      c1='#706CC3',
                      c2='#E3E2F3',
                      c3='#3D37AD')

    def updates(self):
        _translate = QtCore.QCoreApplication.translate
        val = self.comboBox.currentText()
        state = statewise.loc[statewise['State'] == val]
        confirmed = int(state['Confirmed'])
        recovered = int(state['Recovered'])
        deaths = int(state['Deaths'])
        active = int(state['Active'])
        self.label_3.setText(
            _translate("StateWise", "Confirmed:" + "\n" + str(confirmed)))
        self.label_4.setText(
            _translate("StateWise", "Active:" + "\n" + str(active)))
        self.label_5.setText(
            _translate("StateWise", "Recovered:" + "\n" + str(recovered)))
        self.label_6.setText(
            _translate("StateWise", "Deceased:" + "\n" + str(deaths)))
        stateCode = stateDict[val]
        stateDC = statedaily.loc[statedaily["Status"] == "Confirmed"]
        stateDR = statedaily.loc[statedaily["Status"] == "Recovered"]
        stateDD = statedaily.loc[statedaily["Status"] == "Deceased"]
        stateDCVal = list(stateDC[stateCode])
        stateDRVal = list(stateDR[stateCode])
        stateDDVal = list(stateDD[stateCode])
        stateDates = list(stateDC["Date"])
        self.plot(stateDates, stateDCVal)
        self.updateGraph()

    def plot(self, x, y, c1="#FF6282", c2="#FFE0E6", c3="#FF083B"):
        xdict = dict(enumerate(x))
        xax = self.graphWidget.getAxis('bottom')
        xax.setTicks([xdict.items()])
        pen = pg.mkPen(
            color=c1,
            width=5,
        )
        self.graphWidget.clear()
        #self.graphWidget.setLabel('left', "<span style=\"color:#017CFF;font-size:20px;background-color:#EFF7FF\">&nbsp;Active </span>")
        #self.graphWidget.setLabel('bottom',"<span style=\"color:#29A746;font-size:20px;background-color:#E4F4E8\">&nbsp;Recovered </span>")
        self.data_line = self.graphWidget.plot(list(xdict),
                                               y,
                                               pen=pen,
                                               symbol='o',
                                               symbolSize=10,
                                               symbolBrush=(c3))
        self.graphWidget.setBackground(c2)

    def retranslateUi(self, StateWise):
        _translate = QtCore.QCoreApplication.translate
        StateWise.setWindowTitle(_translate("StateWise", "Statewise Analysis"))
        self.label.setText(_translate("StateWise", "Statewise Analysis"))
        self.label.setStyleSheet(
            'color: #FD7F15;background-color: #FFF3D0;background-image:url("");qproperty-alignment: AlignCenter;'
        )
        self.label_2.setText(_translate("StateWise", " Select a State/U.T  :"))
        self.label_2.setStyleSheet(
            'color: #FC9274;background-color: #FEE5D9;background-image:url("");'
        )
        self.label_3.setStyleSheet(
            'color: #FF2D58;background-color: #F8CCCA;background-image:url("");qproperty-alignment: AlignCenter;'
        )
        self.label_4.setStyleSheet(
            'color: #017CFF;background-color: #EFF7FF;background-image:url("");qproperty-alignment: AlignCenter;'
        )
        self.label_5.setStyleSheet(
            'color:#29A746;background-color: #E4F4E8;background-image:url("");qproperty-alignment: AlignCenter;'
        )
        self.label_6.setStyleSheet(
            'color:#767E85;background-color: #F6F6F7;background-image:url("");qproperty-alignment: AlignCenter;'
        )
        self.comboBox.addItems(StateList)
        self.comboBox_2.addItems(["Confirmed", "Recovered", "Deceased"])
        self.comboBox_2.setStyleSheet("background-color:white")
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.getPlotItem().addLegend()
        self._plot_widget.setBackground((255, 255, 255))
        self._plot_widget.setXRange(0, 10, padding=0)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)
        self._plot_widget.getPlotItem().sigRangeChanged.connect(
            self.limits_changed)

        self._curves = {}
        self._current_vline = None

    def add_curve(self,
                  curve_id,
                  curve_name,
                  curve_color=QColor(Qt.blue),
                  markers_on=False):
        pen = mkPen(curve_color, width=1)
        symbol = "o"
        symbolPen = mkPen(QColor(Qt.black))
        symbolBrush = mkBrush(curve_color)
        # this adds the item to the plot and legend
        if markers_on:
            plot = self._plot_widget.plot(name=curve_name,
                                          pen=pen,
                                          symbol=symbol,
                                          symbolPen=symbolPen,
                                          symbolBrush=symbolBrush,
                                          symbolSize=4)
        else:
            plot = self._plot_widget.plot(name=curve_name, pen=pen)
        self._curves[curve_id] = plot

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.removeItem(self._curves[curve_id])
            del self._curves[curve_id]
            self._update_legend()

    def _update_legend(self):
        # clear and rebuild legend (there is no remove item method for the legend...)
        self._plot_widget.clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.addItem(curve)
        if self._current_vline:
            self._plot_widget.addItem(self._current_vline)

    def redraw(self):
        pass

    def set_values(self, curve_id, data_x, data_y):
        curve = self._curves[curve_id]
        curve.setData(data_x, data_y)

    def vline(self, x, color):
        if self._current_vline:
            self._plot_widget.removeItem(self._current_vline)
        self._current_vline = self._plot_widget.addLine(x=x, pen=color)

    def set_xlim(self, limits):
        # TODO: this doesn't seem to handle fast updates well
        self._plot_widget.setXRange(limits[0], limits[1], padding=0)

    def set_ylim(self, limits):
        self._plot_widget.setYRange(limits[0], limits[1], padding=0)

    def get_xlim(self):
        x_range, _ = self._plot_widget.viewRange()
        return x_range

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
Example #33
0
class MainWindow(QMainWindow, capsula.Ui_MainWindow):
    def __init__(self):

        #Initialisation de la GUI, des connections actionneurs/fonctions et des modules supplémentaires non supportés par QtCreator
        os.chdir("/home/pi/Desktop/Résultats Capsula")  #dossier de travail
        super(self.__class__, self).__init__()
        self.setupUi(self)  #initialisation de la GUI Capsula
        #Ajout des Widgets non proposés par QtDesigner
        #Graphe intensité du laser
        self.graphicsViewLaserBeamProfile = PlotWidget(
            self.tabWidgetLaserControl)
        self.graphicsViewLaserBeamProfile.setGeometry(
            QtCore.QRect(310, 60, 475, 300))
        self.graphicsViewLaserBeamProfile.setXRange(0, 480)
        self.graphicsViewLaserBeamProfile.setYRange(0, 255)
        self.graphicsViewLaserBeamProfile.setObjectName(
            "graphicsViewLaserBeamProfile")
        #Graphe détection
        self.graphicsViewRealPlot = PlotWidget(self.tabWidgetDetection)
        self.graphicsViewRealPlot.setGeometry(QtCore.QRect(10, 10, 550, 310))
        self.graphicsViewRealPlot.setXRange(0, 400)
        self.graphicsViewRealPlot.setYRange(0, 1)
        self.graphicsViewRealPlot.setObjectName("graphicsViewRealPlot")
        #Message "Making reference, please wait"
        self.messageBoxBlank = QtGui.QProgressDialog(
            "Making reference, please wait...", "Cancel", 0, 100,
            self.tabWidgetDetection)
        self.messageBoxBlank.setWindowTitle("Wait...")

        #Initialisation des threads
        self.thread1 = thread.LoadingBar(self.messageBoxBlank)
        self.thread2 = thread.MakeBlank(self.messageBoxBlank)

        #Connexion boutons/méthodes
        self.checkBoxLaser532nm.clicked.connect(
            lambda: las.togglelaser532nm(self.checkBoxLaser532nm.isChecked()))
        self.checkBoxLaser635nm.clicked.connect(
            lambda: las.togglelaser635nm(self.checkBoxLaser635nm.isChecked()))
        self.pushButtonDutyCycleM.clicked.connect(
            lambda: mot.dutyCycleM(int(self.lcdNumberDutyCycleM.value())))
        self.pushButtonBlank.clicked.connect(self.makeBlank)
        self.pushButtonClear.clicked.connect(self.on_init)
        self.pushButtonChangeDirectionM.clicked.connect(mot.changeDirectionM)
        self.pushButtonRunAndGoBackM.clicked.connect(mot.runAndGoBackM)
        self.pushButtonSeeCamera.clicked.connect(lambda: las.cameraStart(
            self.graphicsViewLaserBeamProfile, self.labelBeamImage, self.
            labelHHWValue, int(self.lineEditExposureTime.displayText())))
        self.pushButtonStart.clicked.connect(self.startAcquisition)
        self.pushButtonStartMotor.clicked.connect(mot.startM)
        self.pushButtonStop.clicked.connect(self.stopAcquisition)
        self.pushButtonStopMotor.clicked.connect(mot.stopM)
        self.radioButtonContinu.clicked.connect(self.continuousDisplay)
        self.radioButtonSegmente.clicked.connect(self.segmentedDisplay)

        #Connexion actions/méthodes
        self.actionOpen_detection_configuration.triggered.connect(
            self.openDetectionConfiguration)
        self.actionOpen_pump_configuration.triggered.connect(
            self.openPumpConfiguration)
        self.actionOpen_motor_configuration.triggered.connect(
            self.openMotorConfiguration)
        self.actionPause.triggered.connect(self.pauseAcquisition)
        self.actionQuit.triggered.connect(self.closeEvent)
        self.actionSave_detection_configuration.triggered.connect(
            self.saveDetectionConfiguration)
        self.actionSave_pump_configuration.triggered.connect(
            self.savePumpConfiguration)
        self.actionSave_motor_configuration.triggered.connect(
            self.saveMotorConfiguration)
        self.actionStart_Aquisition.triggered.connect(self.startAcquisition)
        self.actionStop_Aquisition.triggered.connect(self.stopAcquisition)

        #Initialisation timer
        self.timer = QtCore.QTimer()
        self.pasDeTemps = int(
            self.lineEditSamplingPeriod.displayText())  #vitesse d'affichage
        self.timer.setInterval(self.pasDeTemps)
        self.timer.timeout.connect(
            self.update)  #connexion timer out/update data

        #Initialisation graphe
        self.on_init()

        #Initialisation lasers
        GPIO.output(22, True)
        GPIO.output(32, True)

        #Déclaration variables
        self.blankDone = False
        self.inCaps = False
        self.noFloatDetected = True
        self.oldLineEdit = ""
        self.pause = False
        self.start = False
        self.stop = False
        self.withlVid = False
        self.withrVid = False

        #Connexion Rpi/Arduino via USB
        self.ser = serial.Serial('/dev/ttyACM0', 115200)

        #Onglet Lasers
        """voir laser.py"""

        #Onglet Fluidics
        """rien pour l'instant"""

#Onglet Results

    def on_init(self):  #Initialise la GUI
        os.chdir("/home/pi/Desktop/Résultats Capsula")  #dossier de travail
        global blank, curve, datan, k, maxi, mini, n, ptr, label, tabCaps  #variables utilisées dans plusieurs fonctions
        self.graphicsViewRealPlot.clear()  #efface la courbe du graphe
        self.graphicsViewRealPlot.setXRange(0, 300)  #mise à l'echelle X

        datan = [0]  #initialise le tableau datas normalisées
        curve = self.graphicsViewRealPlot.plot(datan)  #initialise la courbe
        #initialisation des variables semi-locales
        k = 0
        label = 0
        maxi = 0  #maxi et mini sont changés à la première itération
        mini = 1000
        n = 300
        ptr = 0
        tabCaps = [
        ]  #initialise le tableau qui stocke les cellules à leur passage
        self.labelCurrentValue.setText("")  #reset l'affichage de Current value
        self.lcdNumberCapsuleCounter.display(0)  #reset le compteur de capsules
        self.labelConsole.setText("")  #reset l'affichage de la mini console
        self.segmented = True  #par défaut : affichage segmenté

    def makeBlank(
            self
    ):  #fait la reference et affiche son chargement via les threads
        if (self.checkBoxLaser635nm.isChecked()
                | self.checkBoxLaser532nm.isChecked()):
            #reset des threads
            self.thread1 = thread.LoadingBar(self.messageBoxBlank)
            self.thread2 = thread.MakeBlank(self.messageBoxBlank)
            #start des threads
            self.thread1.start()
            self.thread2.start()
            #autorise l'utilisateur à faire une acquisition
            self.pushButtonClear.setEnabled(True)
            self.pushButtonStart.setEnabled(True)
            self.pushButtonStop.setEnabled(True)
            self.lcdNumberCapsuleCounter.setEnabled(True)
            #la référence est désormais fait
            self.blankDone = True
        else:
            info.laserOnFirst()  #demande de faire le blanc en premier

    def startAcquisition(self):  #se produit en lançant l'acquisition

        if self.blankDone:  #si la référence a été faite
            global f, fn, fs, fp  #les fichiers seront des variables semi-locales

            self.on_init()  #réinitialise tous les paramètres
            #récupération du jour et de l'heure de l'acquisiton
            Ymd = datetime.datetime.now().strftime("%Y-%m-%d")
            YmdHMS = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S")
            #vérification et/ou création du dossier de l'acquisition
            os.makedirs("Datas", exist_ok=True)
            os.chdir("Datas")
            os.makedirs(Ymd, exist_ok=True)
            os.chdir(Ymd)
            os.chmod(
                '.', 0o777
            )  #changement des droits : tout le monde peut écrire dans le dossier et y supprimer des éléments
            #création des fichiers de sauvegardes
            f = open("data" + YmdHMS + ".txt", "w")
            fn = open("datan" + YmdHMS + ".txt", "w")
            fs = open("stats" + YmdHMS + ".txt", "w")
            fp = open("plotbeam" + YmdHMS + ".txt", "w")
            fs.write("Statistiques de cette acquisiton :\n")
            os.chdir("/home/pi/Desktop/Résultats Capsula"
                     )  #retour au dossier de travail
            #Changement des états
            self.pause = False
            self.start = True
            self.stop = False
            #Lancement de l'acquisition

            if self.actionLive_and_record_video_with_detection.isChecked(
            ) and self.actionRecord_video_with_detection.isChecked():
                #affiche "Choose only one option" si les deux options sont cochées
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Information)
                msg.setText("Choose only one option")
                msg.setWindowTitle("Information")
                msg.setStandardButtons(QMessageBox.Ok)
                msg.exec_()
            elif self.actionLive_and_record_video_with_detection.isChecked():
                #pour l'option Live + record :
                self.pasDeTemps = int(
                    self.lineEditSamplingPeriod.displayText()
                )  #période d'échantillonage modifiée car l'affichage ralentit le programme
                self.timer.setInterval(self.pasDeTemps)
                self.thread3 = thread2.PreviewCam(
                    int(self.lineEditExposureTime.displayText())
                )  #initialise le thread d'affichage de la caméra
                self.thread3.start(
                )  #affiche la caméra (voir thread_detect_with_vid.py
                self.withlVid = True  #état : live + record
                self.actionLive_and_record_video_with_detection.setCheckable(
                    False
                )  #pour ne pas changer l'option en cours d'acquisition
                self.timer.start()  #lance le timer
            elif self.actionRecord_video_with_detection.isChecked():
                #pour l'option record :
                i = 1
                global cam  #variable semi-locale
                self.pasDeTemps = int(self.lineEditSamplingPeriod.displayText(
                ))  #vitesse d'affichage
                self.timer.setInterval(self.pasDeTemps)
                #initialisation de la caméra pour filmer (voir camera.py)
                cam = picamera.PiCamera()
                cam.resolution = (640, 480)
                cam.framerate = float(40)
                cam.shutter_speed = int(
                    self.lineEditExposureTime.displayText())
                #vérification et/ou création du dossier de l'acquisition
                os.makedirs("Datas", exist_ok=True)
                os.chdir("Datas")
                os.makedirs(Ymd, exist_ok=True)
                os.chdir(Ymd)
                cam.start_recording("vdata" + YmdHMS +
                                    '.h264')  #création du fichier
                os.chdir("/home/pi/Desktop/Résultats Capsula"
                         )  #retour au dossier de travail

                self.withrVid = True  #état : record
                self.actionRecord_video_with_detection.setCheckable(
                    False
                )  #pour ne pas changer l'option en cours d'acquisition
                self.timer.start()  #lance le timer

            else:
                #sans option :
                self.pasDeTemps = int(self.lineEditSamplingPeriod.displayText(
                ))  #vitesse d'affichage
                self.timer.setInterval(self.pasDeTemps)
                self.timer.start()  #lance le timer
        else:  #si la référence n'est pas faite, la faire d'abord
            info.makeBlankFirst()

    def update(self):  #met à jour les données en temps réel sur le graphe

        self.ser.write(bytes(b'1'))  #demande une donnée à Arduino
        value = float(
            self.ser.readline().strip().decode('ascii'))  #reçoit la donnée
        self.saveData(value)  #lance saveData
        #self.capsule(value) #lance capsule
        self.labelCurrentValue.setText(str(round(
            value, 5)))  #affiche la current value avec 6 chiffres

    def saveData(
            self,
            value):  #sauve la donnée dans le txt et l'affiche sur le graphe
        global curve, datan, ptr, mini, maxi, n, k, blank, label  #récupère les variables semi-locales
        blank = self.thread2.blank  #récupère la valeur de reference
        mini = min(value,
                   mini)  #récupère le signal min et max pour le fichier stats
        maxi = max(value, maxi)
        #mode affichage segmenté
        if self.segmented:
            if len(datan) < 300:  #tant que le graphe n'est pas rempli
                datan.append(
                    value /
                    blank)  #normalisation de la donnée par rapport au blanc
                f.write(
                    str(round((len(datan) - 1) * self.pasDeTemps / 1000, 8)) +
                    "\t" + str(value) + "\n")  #écriture dans le txt data
                fn.write(
                    str(round(
                        (len(datan) - 1) * self.pasDeTemps / 1000, 8)) + "\t" +
                    str(value / blank) + "\n")  #écriture dans le txt datan
                k += 1
            else:
                if k >= 300:  #lorsque le tableau est rempli, n'affiche que 300 valeurs
                    k = 0
                    self.graphicsViewRealPlot.setXRange(
                        n, n + 300)  #mise à l'échelle X
                    n += 300
                datan[:-1] = datan[1:]  #datan est décalé de 1 vers la gauche
                datan[
                    -1] = value / blank  #ajoute à datan la nouvelle donnée normalisée
                f.write(
                    str(round((ptr + 300) * self.pasDeTemps / 1000, 8)) +
                    "\t" + str(value) + "\n")  #écriture dans le txt data
                fn.write(
                    str(round(
                        (ptr + 300) * self.pasDeTemps / 1000, 8)) + "\t" +
                    str(value / blank) + "\n")  #écriture dans le txt datan
                ptr += 1  #incrémente le pointeur
                k += 1
                curve.setPos(ptr, 0)  #positionne l'origine du graphe
        #mode affichage continu
        else:
            if len(datan) < 300:  #tant que le graphe n'est pas rempli
                datan.append(
                    value /
                    blank)  #normalisation de la donnée par rapport au blanc
                f.write(
                    str(round((len(datan) - 1) * self.pasDeTemps / 1000, 8)) +
                    "\t" + str(value) + "\n")  #écriture dans le txt data
                fn.write(
                    str(round(
                        (len(datan) - 1) * self.pasDeTemps / 1000, 8)) + "\t" +
                    str(value / blank) + "\n")  #écriture dans le txt datan
            else:  #lorsque le graphe est rempli, n'affiche que 300 valeurs
                self.graphicsViewRealPlot.setXRange(ptr, ptr +
                                                    300)  #mise à l'échelle X
                datan[:-1] = datan[1:]  #data est décalé de 1 vers la gauche
                datan[-1] = value / blank  #ajoute à data la nouvelle donnée
                f.write(
                    str(round((ptr + 300) * self.pasDeTemps / 1000, 8)) +
                    "\t" + str(value) + "\n")  #écriture dans le txt data
                fn.write(
                    str(round((ptr + 300) * self.pasDeTemps / 1000, )) + "\t" +
                    str(value / blank) + "\n")  #écriture dans le txt datan
                ptr += 1  #incrémente le pointeur
                curve.setPos(ptr, 0)  #positionne l'origine du graphe
        label += 1  #incrémente le label
        curve.setData(datan)  #mise à jour du graphe

    def capsule(self,
                value):  #définit si ce qui est observé est une capsule ou non
        global datan, d, invabsorption, label, tabCaps, blank
        try:  #si on arrive à récupérer une valeur du seuil de détection
            lineEdit = self.lineEditDetectionThreshold.displayText(
            )  #la récupère
            if lineEdit != self.oldLineEdit:  #si le seuil a été changé
                if lineEdit == "":  #si il n'y a pas de seuil
                    self.noFloatDetected = True  #état : pas de seuil détecté
                else:
                    self.noFloatDetected = False  #état : seuil détecté
            self.oldLineEdit = lineEdit  #le nouveau devient l'ancien
            if not self.inCaps:  #si on est pas déjà dans une capsule
                if datan[-1] < float(
                        self.lineEditDetectionThreshold.displayText(
                        )) and label > 3:  #si on entre dans une capsule
                    self.inCaps = True  #état : on est dans une capsule
                    d = -1  #pour aller chercher la taille de la capsule
                    invabsorption = value / blank  #pour définir l'absorption
            if self.inCaps:  #si on est déjà dans une capsule
                d -= 1  #on décale le début de 1 à gauche
                if invabsorption > value / blank:  #si l'absorption est plus grande
                    invabsorption = value / blank  #nouvelle valeur pour l'inverse de l'absorption
                if datan[-1] > float(self.lineEditDetectionThreshold.
                                     displayText()):  #si on sort d'une capsule
                    self.inCaps = False  #état : on est pas dans une capsule
                    absorption = 1 - invabsorption  #calcul de l'absorption
                    while (
                            1 - datan[d]
                    ) / absorption < 0.5:  #pour trouver la position du début de la capsule
                        d += 1
                    f = d
                    while (
                            1 - datan[f]
                    ) / absorption >= 0.5:  #pour trouver la position de la fin de la capsule
                        f += 1
                    taille = abs(f - d)  #calcul de la taille
                    if taille > float(self.lineEditLength.displayText(
                    )):  #si la taille de la capsule est assez grande
                        self.lcdNumberCapsuleCounter.display(
                            self.lcdNumberCapsuleCounter.value() +
                            1)  #on incrémente le compteur de 1
                        tabCaps.append(
                            capsule.Capsule(taille, label - taille, absorption)
                        )  #on ajoute la capsule au tableau de capsules
                        self.labelConsole.setText(
                            tabCaps[-1].afficher()
                        )  #affiche les données de la capsule dans la mini console
        except ValueError:  #si on ne détecte pas de seuil
            if self.noFloatDetected:  #si on n'était pas déjà dans ce cas précedemment
                print("no float in Detection Threshold")
                self.noFloatDetected = False

    def pauseAcquisition(self):  #gère les pauses d'acquisition
        if self.blankDone:  #si la référence est faite
            if not (self.withlVid or self.withrVid):  #si on peut mettre pause
                if not self.pause:  #si la pause n'est pas active
                    self.timer.stop()  #mise en pause du timer
                    self.pause = True  #la pause est active
                else:  #si la pause est active
                    self.timer.start()  #remise en route du timer
                    self.pause = False  #la pause n'est plus active
        else:  #si la référence n'est pas faite
            self.makeBlankFirst()  #faire la référence d'abord

    def stopAcquisition(self):  #se produit en stoppant l'acquisition
        if self.blankDone:  #si la référence est faite
            if self.start == True:  #si une acquisition est en cours
                if self.withrVid:
                    #pour l'option Record :
                    global cam  #récupère la variable semi-locale cam
                    #Arrête et ferme la  caméra
                    cam.stop_recording()
                    cam.close()
                    self.actionRecord_video_with_detection.setCheckable(
                        True)  #option à nouveau modifiable
                    self.actionRecord_video_with_detection.setChecked(
                        True)  #option cochée
                if self.withlVid:
                    #pour l'option Live + record :
                    self.thread3.stop(
                    )  #arrête la preview (voir thread_detect_with_vid.py)
                    self.actionLive_and_record_video_with_detection.setCheckable(
                        True)  #option à nouveau modifiable
                    self.actionLive_and_record_video_with_detection.setChecked(
                        True)  #option cochée
                self.saveStats()  #sauvegarde les stats
                self.timer.stop()  #arrête le timer
                #fermeture des fichiers
                f.close()
                fn.close()
                os.chdir("/home/pi/Desktop/Résultats Capsula"
                         )  #retour dans le dossier de travail
            #réinitialisation des états
            self.withrVid = False
            self.withlVid = False
            self.start = False
            self.stop = True
            mot.stopM()
        else:  #si la référence n'est pas faite
            self.makeBlankFirst()  #faire la référence d'abord

    def continuousDisplay(self):  #mode d'affichage continu
        self.segmented = False

    def segmentedDisplay(self):  #mode d'affichage segmenté
        global ptr, k, n
        n = ptr + 300
        self.graphicsViewRealPlot.setXRange(n, n + 300)  #mise à l'echelle X
        n += 300
        k = 0
        self.segmented = True

#Onglet Calibration

#Général

    def openDetectionConfiguration(self):
        file = QFileDialog.getOpenFileName()
        file = str(file)[2:-19]
        fodc = open(file, "r")
        detection_threshold = fodc.readline()
        length_threshold = fodc.readline()
        ratio_capsule = fodc.readline()
        sampling_period = fodc.readline()
        self.lineEditDetectionThreshold.setText(detection_threshold)
        self.lineEditLength.setText(length_threshold)
        self.lineEditMinimumSize.setText(ratio_capsule)
        self.lineEditSamplingPeriod.setText(sampling_period)
        fodc.close()
        os.chdir("/home/pi/Desktop/Résultats Capsula")

    def openPumpConfiguration(self):
        file = QFileDialog.getOpenFileName()
        file = str(file)[2:-19]
        fopc = open(file, "r")
        dutycycle = int(fopc.readline())
        self.horizontalSliderDutyCycleP.setValue(dutycycle)
        fopc.close()
        os.chdir("/home/pi/Desktop/Résultats Capsula")

    def openMotorConfiguration(self):
        file = QFileDialog.getOpenFileName()
        file = str(file)[2:-19]
        fomc = open(file, "r")
        dutycycle = int(fomc.readline())
        self.horizontalSliderDutyCycleM.setValue(dutycycle)
        fomc.close()
        os.chdir("/home/pi/Desktop/Résultats Capsula")

    def saveDetectionConfiguration(self):
        file = QFileDialog.getSaveFileName()
        if (str(file)[-23:-19] == ".txt"):
            fsdc = open(str(file)[2:-19], "w")
        else:
            fsdc = open(str(file)[2:-19] + ".txt", "w")
        detection_threshold = self.lineEditDetectionThreshold.text()
        length_threshold = self.lineEditLength.text()
        ratio_capsule = self.lineEditMinimumSize.text()
        sampling_period = self.lineEditSamplingPeriod.text()
        fsdc.write(detection_threshold + "\n")
        fsdc.write(length_threshold + "\n")
        fsdc.write(ratio_capsule + "\n")
        fsdc.write(sampling_period)
        fsdc.close()
        os.chdir("/home/pi/Desktop/Résultats Capsula")

    def savePumpConfiguration(self):
        file = QFileDialog.getSaveFileName()
        if (str(file)[-23:-19] == ".txt"):
            fspc = open(str(file)[2:-19], "w")
        else:
            fspc = open(str(file)[2:-19] + ".txt", "w")
        dutycycle = str(self.horizontalSliderDutyCycleP.value())
        fspc.write(dutycycle)
        fspc.close()
        os.chdir("/home/pi/Desktop/Résultats Capsula")

    def saveMotorConfiguration(self):
        file = QFileDialog.getSaveFileName()
        if (str(file)[-23:-19] == ".txt"):
            fsmc = open(str(file)[2:-19], "w")
        else:
            fsmc = open(str(file)[2:-19] + ".txt", "w")
        dutycycle = str(self.horizontalSliderDutyCycleM.value())
        fsmc.write(dutycycle)
        fsmc.close()
        os.chdir("/home/pi/Desktop/Résultats Capsula")

    def saveStats(self):  #sauve des statistiques de l'acquisition
        global mini, maxi, fs  #récupération de variables semi-locales
        #Ecriture dans le fichier stats et fermeture de celui ci
        fs.write("Nombres de capsules comptées :\t" +
                 str(int(self.lcdNumberCapsuleCounter.value())) + "\n")
        fs.write("Signal maximal mesuré :\t" + str(round(maxi, 2)) + "V\n")
        fs.write("Signal minimal mesuré :\t" + str(round(mini, 2)) + "V\n")
        fs.write("Pas de temps :\t" + str(self.pasDeTemps))
        fs.close()

    def closeEvent(self, event):  #Quitte proprement la GUI
        self.timer.stop()  #arrête le timer
        #réinitialise les GPIO
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(22, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(32, GPIO.OUT, initial=GPIO.LOW)
        GPIO.cleanup()
        self.close()  #ferme la fenêtre
class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.setFixedSize(800, 618)

        MainWindow.setStyleSheet('background:#e8e8e8')

        #here starts widget setup, mostly just assigning locations and various properties
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.topDisplayDivider = QtWidgets.QFrame(self.centralwidget)
        self.topDisplayDivider.setGeometry(QtCore.QRect(0, 90, 801, 16))
        self.topDisplayDivider.setFrameShape(QtWidgets.QFrame.HLine)
        self.topDisplayDivider.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.topDisplayDivider.setObjectName("topDisplayDivider")
        self.menuDivider = QtWidgets.QFrame(self.centralwidget)
        self.menuDivider.setGeometry(QtCore.QRect(110, 100, 16, 501))
        self.menuDivider.setFrameShape(QtWidgets.QFrame.VLine)
        self.menuDivider.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.menuDivider.setObjectName("menuDivider")
        self.pushHistory = QtWidgets.QPushButton(self.centralwidget)
        self.pushHistory.setGeometry(QtCore.QRect(20, 140, 75, 23))
        self.pushHistory.setObjectName("pushHistory")
        self.pushHistory.setStyleSheet("border: 1px solid grey;")
        self.pushAnalytics = QtWidgets.QPushButton(self.centralwidget)
        self.pushAnalytics.setGeometry(QtCore.QRect(20, 210, 75, 23))
        self.pushAnalytics.setObjectName("pushAnalytics")
        self.pushExport = QtWidgets.QPushButton(self.centralwidget)
        self.pushExport.setGeometry(QtCore.QRect(20, 280, 75, 23))
        self.pushExport.setObjectName("pushExport")
        self.pushOptions = QtWidgets.QPushButton(self.centralwidget)
        self.pushOptions.setGeometry(QtCore.QRect(20, 350, 75, 23))
        self.pushOptions.setObjectName("pushOptions")

        self.pushLive = QtWidgets.QPushButton(self.centralwidget)
        self.pushLive.setGeometry(QtCore.QRect(20, 550, 75, 23))
        self.pushLive.setObjectName("pushLive")

        self.pushGraph = QtWidgets.QPushButton(self.centralwidget)
        self.pushGraph.setGeometry(QtCore.QRect(200, 550, 75, 23))
        self.pushGraph.setObjectName("pushGraph")

        self.pushGraph2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushGraph2.setGeometry(QtCore.QRect(300, 550, 75, 23))
        self.pushGraph2.setObjectName("pushGraph2")

        self.liveDisplay_1 = QtWidgets.QLabel(self.centralwidget)
        self.liveDisplay_1.setGeometry(QtCore.QRect(710, 20, 61, 61))
        self.liveDisplay_1.setObjectName("liveDisplay_1")
        self.liveDisplay_1.setStyleSheet("font: 30pt Arial MS")

        self.liveDisplay_2 = QtWidgets.QLabel(self.centralwidget)
        self.liveDisplay_2.setGeometry(QtCore.QRect(570, 20, 61, 61))
        self.liveDisplay_2.setObjectName("liveDisplay_2")
        self.liveDisplay_2.setStyleSheet("font: 30pt Arial MS")

        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(500, 20, 61, 61))
        self.label.setText("")
        self.label.setPixmap(QtGui.QPixmap("heart.png"))
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(640, 20, 61, 61))
        self.label_2.setText("")
        self.label_2.setPixmap(QtGui.QPixmap("o2.png"))
        self.label_2.setScaledContents(True)
        self.label_2.setObjectName("label_2")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(140, 120, 631, 311))
        self.groupBox.setObjectName("groupBox")
        self.label_3 = QtWidgets.QLabel(self.groupBox)
        self.label_3.setGeometry(QtCore.QRect(210, 110, 151, 31))
        self.label_3.setObjectName("label_3")

        self.dateTimeEdit = QtWidgets.QDateEdit(self.centralwidget)
        self.dateTimeEdit.setGeometry(QtCore.QRect(190, 490, 194, 22))
        self.dateTimeEdit.setObjectName("dateTimeEdit")
        self.dateTimeEdit.setDate(QDate.currentDate())

        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(40, 20, 251, 41))
        font = QtGui.QFont()
        font.setPointSize(19)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        #creating graphs
        self.graphWidgetLive = PlotWidget(self.centralwidget)
        self.graphWidgetLive.setGeometry(QtCore.QRect(40, 10, 400, 70))
        self.graphWidgetLive.setObjectName("graphWidgetLive")
        self.graphWidgetLive.getPlotItem().hideAxis('bottom')
        self.graphWidgetLive.setMouseEnabled(x=False, y=False)
        self.graphWidgetLive.setYRange(0, 150, padding=0.2)
        self.graphWidgetLive.getPlotItem().hideAxis('bottom')

        self.graphWidgetMain = PlotWidget(self.centralwidget)
        self.graphWidgetMain.setGeometry(QtCore.QRect(150, 140, 600, 275))
        self.graphWidgetMain.setObjectName("graphWidgetLive")
        self.graphWidgetMain.setMouseEnabled(x=True, y=False)
        self.graphWidgetMain.setYRange(50, 150, padding=0)
        self.graphWidgetMain.getPlotItem().hideAxis('bottom')

        self.graphWidgetLive.setBackground('w')

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)
        time = [1, 2, 3, 4]
        heartRate = [90, 87, 88, 85]
        oxygenLevel = [100, 99, 99, 98]
        self.graphWidgetMain.setBackground('w')
        self.graphWidgetMain.plot(time, heartRate, pen=pen)
        self.graphWidgetMain.plot(time, oxygenLevel, pen=pen2)

        #these two values can be changed in options and are parameters for the windows notifications
        self.notifThresh = [120, 95]
        self.notifCooldown = 25

        self.serialInput = False

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        #connecting buttons
        self.pushAnalytics.clicked.connect(self.show_Analysis)

        self.pushExport.clicked.connect(self.show_export)

        self.pushOptions.clicked.connect(self.show_popOptions)

        self.pushLive.setCheckable(True)
        self.pushLive.clicked.connect(self.show_graphLive)

        self.pushGraph.clicked.connect(self.fromFile)
        self.pushGraph2.clicked.connect(self.fromDate)

    def update_plot_data(self):

        #this is used to update the live graph by reading from serial or the debugging simulator

        self.timeLive = self.timeLive[1:]  # Remove the first y element.
        self.timeLive.append(self.timeLive[-1] +
                             1)  # Add a new value 1 higher than the last.

        if self.serialInput == True:
            serialData = serial_connection.getSerial()
        else:
            serialData = (singleGenerate(79, 3), singleGenerate(97, 1))

        if serialData[0] != 0:
            self.liveHR = self.liveHR[1:]  # Remove the first
            self.liveHR.append(serialData[0])
            self.liveDisplay_2.setText(str(self.liveHR[99]))

        if serialData[1] != 0:
            self.liveO2 = self.liveO2[1:]  # Remove the first
            self.liveO2.append(serialData[1])
            self.liveDisplay_1.setText(str(self.liveO2[99]))

        if not (serialData[0] == 0 & serialData[1] == 0):
            datasystem.data_store(serialData[0], serialData[1])

        a = datetime.datetime.now()
        b = self.startTime
        c = a - b
        print(c.total_seconds())
        if c.total_seconds() > self.notifCooldown:
            if self.notifThresh[0] < serialData[0]:
                windowsalert.sendNotifH()
                self.startTime = datetime.datetime.now()

            if self.notifThresh[1] > serialData[1] & serialData[1] != 0:
                windowsalert.sendNotifO()
                self.startTime = datetime.datetime.now()

        self.data_line_1.setData(self.timeLive,
                                 self.liveHR)  # Update the data.
        self.data_line_2.setData(self.timeLive,
                                 self.liveO2)  # Update the data.

    def show_export(self):
        #used to call the zipping function in datasystem.py, and the file dialog
        options = QFileDialog.Options() | QFileDialog.DontUseNativeDialog
        fileName = QFileDialog.getSaveFileName(self,
                                               "Select an export location",
                                               "",
                                               "Zip Files (*.zip)",
                                               options=options)
        datasystem.data_zip(fileName[0] + '.zip')

    def show_graphLive(self):
        #connects to the button for live, and also controls if the graph/reading is enabled

        self.timeLive = list(range(100))  # 100 time points
        self.liveHR = [0] * 100
        self.liveO2 = [0] * 100
        self.startTime = datetime.datetime.now() - datetime.timedelta(
            seconds=self.notifCooldown)
        print(self.startTime)

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)

        self.liveDisplay_2.setText('0')
        self.liveDisplay_1.setText('0')

        if self.pushLive.isChecked():
            self.data_line_1 = self.graphWidgetLive.plot(self.timeLive,
                                                         self.liveHR,
                                                         pen=pen)
            self.data_line_2 = self.graphWidgetLive.plot(self.timeLive,
                                                         self.liveO2,
                                                         pen=pen2)
            self.timer = QtCore.QTimer()
            self.timer.setInterval(250)
            self.timer.timeout.connect(self.update_plot_data)
            self.timer.start()
            self.pushLive.setText('Stop')
        else:
            self.timer.stop()
            self.graphWidgetLive.clear()
            self.pushLive.setText('Start')

    def fromDate(self):
        #used to connect the date picker to the main graph
        x = self.dateTimeEdit.date().toPyDate()
        date = 'vitals' + str(x)
        directory = os.getcwd()
        foldername = directory + '\\vitalsmouse_userdata'
        self.importfile = foldername + '\\' + date + '.csv'

        self.show_graphMain()

    def fromFile(self):
        #used to connect the file dialog to the main graph
        options = QFileDialog.Options() | QFileDialog.DontUseNativeDialog
        fileName = QFileDialog.getOpenFileName(self,
                                               "Select a file to view",
                                               "",
                                               "CSV Files (*.csv)",
                                               options=options)
        self.importfile = fileName[0]

        self.show_graphMain()

    def show_graphMain(self):
        #loads the data from a file and displays it on the main graph

        print(self.importfile)

        self.graphWidgetMain.clear()

        maindata = datasystem.data_get(self.importfile)

        mainTime = maindata[0]
        mainHR = maindata[1]
        mainO2 = maindata[2]

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)
        self.graphWidgetMain.setBackground('w')
        self.graphWidgetMain.plot(mainTime, mainHR, pen=pen)
        self.graphWidgetMain.plot(mainTime, mainO2, pen=pen2)

    def show_popOptions(self):
        #secondary window for options
        self.Options = QDialog()
        self.Options.resize(200, 250)

        self.input_label = QtWidgets.QLabel(self.Options)
        self.input_label.setGeometry(QtCore.QRect(10, 10, 61, 51))
        self.input_label.setObjectName("input_label")

        self.inputBox = QtWidgets.QComboBox(self.Options)
        self.inputBox.setGeometry(QtCore.QRect(80, 30, 69, 22))
        self.inputBox.setObjectName("inputBox")
        self.inputBox.addItem('Debug')
        self.inputBox.addItem('USB')

        self.notificationsBox = QtWidgets.QGroupBox(self.Options)
        self.notificationsBox.setGeometry(QtCore.QRect(0, 90, 211, 131))
        self.notificationsBox.setObjectName("notificationsBox")
        self.lineEdit = QtWidgets.QLineEdit(self.notificationsBox)
        self.lineEdit.setGeometry(QtCore.QRect(130, 30, 61, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.hr_label = QtWidgets.QLabel(self.notificationsBox)
        self.hr_label.setGeometry(QtCore.QRect(6, 30, 111, 20))
        self.hr_label.setObjectName("hr_label")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.notificationsBox)
        self.lineEdit_2.setGeometry(QtCore.QRect(130, 60, 61, 20))
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.lineEdit_3 = QtWidgets.QLineEdit(self.notificationsBox)
        self.lineEdit_3.setGeometry(QtCore.QRect(130, 90, 61, 20))
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.o2_label = QtWidgets.QLabel(self.notificationsBox)
        self.o2_label.setGeometry(QtCore.QRect(10, 60, 111, 20))
        self.o2_label.setObjectName("o2_label")
        self.cooldown_label = QtWidgets.QLabel(self.notificationsBox)
        self.cooldown_label.setGeometry(QtCore.QRect(10, 90, 111, 20))
        self.cooldown_label.setObjectName("cooldown_label")

        self.input_label.setText("Input mode")
        self.notificationsBox.setTitle(("Notifications"))
        self.lineEdit.setText(("110"))
        self.hr_label.setText(("Heartrate threshold"))
        self.lineEdit_2.setText(("95"))
        self.lineEdit_3.setText(("20"))
        self.o2_label.setText(("Oxygen threshold"))
        self.cooldown_label.setText(("Cooldown(seconds)"))

        self.Options.setWindowTitle("Options")
        self.Options.exec_()

        h = self.inputBox.currentText()

        if h == 'USB':
            self.serialInput = True
        else:
            self.serialInput = False

        heartThresh = self.lineEdit.text()
        o2Thresh = self.lineEdit_2.text()
        cool = self.lineEdit_3.text()

        self.notifThresh = (int(heartThresh), int(o2Thresh))
        self.notifCooldown = int(cool)

    def show_Analysis(self):
        #secondary window for analysis
        self.Analysis = QDialog()
        self.Analysis.resize(400, 400)

        self.dailyLine = QtWidgets.QLineEdit(self.Analysis)
        self.dailyLine.setGeometry(QtCore.QRect(210, 60, 113, 20))
        self.dailyLine.setReadOnly(True)
        self.dailyLine.setObjectName("dailyLine")
        self.yearly_label = QtWidgets.QLabel(self.Analysis)
        self.yearly_label.setGeometry(QtCore.QRect(40, 140, 101, 16))
        self.yearly_label.setObjectName("yearly_label")
        self.monthly_label = QtWidgets.QLabel(self.Analysis)
        self.monthly_label.setGeometry(QtCore.QRect(40, 100, 111, 16))
        self.monthly_label.setObjectName("monthly_label")
        self.monthlyLine = QtWidgets.QLineEdit(self.Analysis)
        self.monthlyLine.setGeometry(QtCore.QRect(210, 100, 113, 20))
        self.monthlyLine.setReadOnly(True)
        self.monthlyLine.setObjectName("monthlyLine")
        self.daily_label = QtWidgets.QLabel(self.Analysis)
        self.daily_label.setGeometry(QtCore.QRect(40, 60, 111, 16))
        self.daily_label.setObjectName("daily_label")
        self.yearlyLine = QtWidgets.QLineEdit(self.Analysis)
        self.yearlyLine.setGeometry(QtCore.QRect(210, 140, 113, 20))
        self.yearlyLine.setReadOnly(True)
        self.yearlyLine.setObjectName("yearlyLine")

        self.legend_label = QtWidgets.QLabel(self.Analysis)
        self.legend_label.setGeometry(QtCore.QRect(220, 20, 113, 20))
        self.legend_label.setObjectName("legend_label")
        self.legend_label.setText("Heartrate, Oxygen")

        self.graphWidgetAnalysis = PlotWidget(self.Analysis)
        self.graphWidgetAnalysis.setGeometry(QtCore.QRect(50, 200, 300, 150))
        self.graphWidgetAnalysis.setObjectName("graphWidgetLive")
        self.graphWidgetAnalysis.setMouseEnabled(x=False, y=False)
        self.graphWidgetAnalysis.setYRange(50, 150, padding=0)
        self.graphWidgetAnalysis.getPlotItem().hideAxis('bottom')

        analysis_data = datasystem.data_analysis()

        pen = pg.mkPen(color=(255, 0, 0), width=2)
        pen2 = pg.mkPen(color=(0, 0, 255), width=2)

        heartRate = analysis_data[3][0]
        oxygenLevel = analysis_data[3][1]

        length = len(heartRate)
        time = [int(z) for z in range(length)]
        self.graphWidgetAnalysis.setBackground('w')
        self.graphWidgetAnalysis.plot(time, heartRate, pen=pen)
        self.graphWidgetAnalysis.plot(time, oxygenLevel, pen=pen2)

        self.dailyLine.setText(
            str(round(analysis_data[0][0], 2)) + ', ' +
            str(round(analysis_data[0][1], 2)))
        self.monthlyLine.setText(
            str(round(analysis_data[1][0], 2)) + ', ' +
            str(round(analysis_data[1][1], 2)))
        self.yearlyLine.setText(
            str(round(analysis_data[2][0], 2)) + ', ' +
            str(round(analysis_data[2][1], 2)))

        self.yearly_label.setText("Yearly Average")
        self.monthly_label.setText("Monthly Average")
        self.daily_label.setText("Daily Average")

        self.Analysis.setWindowTitle("Analysis")

        self.Analysis.exec_()

    def retranslateUi(self, MainWindow):
        #this is a holdover from using pyuic5, not normally used like this
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushHistory.setText(_translate("MainWindow", "History"))
        self.pushAnalytics.setText(_translate("MainWindow", "Analytics"))
        self.pushExport.setText(_translate("MainWindow", "Export"))
        self.pushOptions.setText(_translate("MainWindow", "Options"))
        self.pushLive.setText(_translate("MainWindow", "Start"))
        self.pushGraph.setText(_translate("MainWindow", "From file"))
        self.pushGraph2.setText(_translate("MainWindow", "From date"))
        self.liveDisplay_1.setText("##")
        self.liveDisplay_2.setText("##")
        self.groupBox.setTitle(_translate("MainWindow", "History"))
Example #35
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1200, 850)

        # Main window
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)

        # Plot widget
        self.plotWidget = PlotWidget(self.centralwidget)
        self.plotWidget.setObjectName("PlotWidget")

        # Trails view
        self.trailsScene = QGraphicsScene()
        self.trailsView = QGraphicsView(self.trailsScene, self.centralwidget)
        self.trailsView.setObjectName("trailsView")

        # Heatmap view
        self.heatmapScene = QGraphicsScene()
        self.heatmapView = QGraphicsView(self.heatmapScene, self.centralwidget)
        self.heatmapView.setObjectName("heatmapView")

        # OpenGL widget
        self.openGLWidget = OpenGLWidget()
        self.openGLWidget.setObjectName("openGLView")

        # Stacked widget, combining plot widget and graphics view
        self.stackedWidget = QStackedWidget(self.centralwidget)
        self.stackedWidget.setGeometry(QRect(10, 10, 800, 800))
        self.stackedWidget.setObjectName("stackedWidget")
        self.stackedWidget.addWidget(self.plotWidget)
        self.stackedWidget.addWidget(self.trailsView)
        self.stackedWidget.addWidget(self.heatmapView)
        self.stackedWidget.addWidget(self.openGLWidget)

        # Perturbation title
        self.perturbationSlidersLabel = QLabel(self.centralwidget)
        self.perturbationSlidersLabel.setGeometry(QRect(960, 30, 170, 20))
        font = QFont()
        font.setPointSize(14)
        self.perturbationSlidersLabel.setFont(font)
        self.perturbationSlidersLabel.setObjectName("perturbation_title")

        # Perturbation 1
        self.horizontalSlider1 = QSlider(self.centralwidget)
        self.horizontalSlider1.setGeometry(QRect(920, 80, 270, 20))
        self.horizontalSlider1.setMaximum(100)
        self.horizontalSlider1.setOrientation(Qt.Horizontal)
        self.horizontalSlider1.setInvertedAppearance(False)
        self.horizontalSlider1.setObjectName("horizontal1Slider")
        self.horizontalSlider1.valueChanged.connect(self.slider1Changed)
        self.checkBox1 = QCheckBox(self.centralwidget)
        self.checkBox1.setGeometry(QRect(830, 80, 90, 20))
        self.checkBox1.setTristate(False)
        self.checkBox1.setObjectName("checkBox1")

        # Perturbation 2
        self.horizontalSlider2 = QSlider(self.centralwidget)
        self.horizontalSlider2.setGeometry(QRect(920, 130, 270, 20))
        self.horizontalSlider2.setMaximum(100)
        self.horizontalSlider2.setOrientation(Qt.Horizontal)
        self.horizontalSlider2.setInvertedAppearance(False)
        self.horizontalSlider2.setObjectName("horizontalSlider2")
        self.horizontalSlider2.valueChanged.connect(self.slider2Changed)
        self.checkBox2 = QCheckBox(self.centralwidget)
        self.checkBox2.setGeometry(QRect(830, 130, 90, 20))
        self.checkBox2.setObjectName("checkBox2")

        # Perturbation 3
        self.horizontalSlider3 = QSlider(self.centralwidget)
        self.horizontalSlider3.setGeometry(QRect(920, 180, 270, 20))
        self.horizontalSlider3.setMaximum(100)
        self.horizontalSlider3.setOrientation(Qt.Horizontal)
        self.horizontalSlider3.setInvertedAppearance(False)
        self.horizontalSlider3.setObjectName("horizontalSlider3")
        self.horizontalSlider3.valueChanged.connect(self.slider3Changed)
        self.checkBox3 = QCheckBox(self.centralwidget)
        self.checkBox3.setGeometry(QRect(830, 180, 90, 20))
        self.checkBox3.setObjectName("checkBox3")

        # Perturbation 4
        self.horizontalSlider4 = QSlider(self.centralwidget)
        self.horizontalSlider4.setGeometry(QRect(920, 230, 270, 20))
        self.horizontalSlider4.setMaximum(100)
        self.horizontalSlider4.setOrientation(Qt.Horizontal)
        self.horizontalSlider4.setInvertedAppearance(False)
        self.horizontalSlider4.setObjectName("horizontalSlider4")
        self.horizontalSlider4.valueChanged.connect(self.slider4Changed)
        self.checkBox4 = QCheckBox(self.centralwidget)
        self.checkBox4.setGeometry(QRect(830, 230, 90, 20))
        self.checkBox4.setObjectName("checkBox4")

        # Random perturbation button
        self.perturbSelectedButton = QPushButton(self.centralwidget)
        self.perturbSelectedButton.setGeometry(QRect(830, 300, 150, 50))
        self.perturbSelectedButton.setObjectName("perturbSelectedButton")
        self.perturbSelectedButton.setToolTip(
            "Randomly set all checked perturbations")
        self.perturbSelectedButton.clicked.connect(self.randChangeSelected)

        self.reset = QPushButton(self.centralwidget)
        self.reset.setGeometry(QRect(1000, 300, 110, 50))
        self.reset.setObjectName("reset_button")
        self.reset.setToolTip("Set all checked perturbations back to 0")
        self.reset.clicked.connect(self.resetSelected)

        # Menubar items
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setGeometry(QRect(0, 0, 1285, 21))
        self.menubar.setObjectName("menubar")
        self.menuFile = QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        self.menuViews = QMenu(self.menubar)
        self.menuViews.setObjectName("menuViews")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.viewsBasic = QAction(MainWindow)
        self.viewsBasic.setObjectName("viewsBasic")
        self.viewsBasic.triggered.connect(lambda: self.switchWidget(0))
        self.viewsTrail = QAction(MainWindow)
        self.viewsTrail.setObjectName("viewsTrail")
        self.viewsTrail.triggered.connect(lambda: self.switchWidget(1))
        self.viewsHeatmap = QAction(MainWindow)
        self.viewsHeatmap.setObjectName("viewsHeatmap")
        self.viewsHeatmap.triggered.connect(lambda: self.switchWidget(2))
        self.viewsOpenGL = QAction(MainWindow)
        self.viewsOpenGL.setObjectName("viewsOpenGL")
        self.viewsOpenGL.triggered.connect(lambda: self.switchWidget(3))

        self.fileReset = QAction(MainWindow)
        self.fileReset.setObjectName("fileReset")
        # self.fileReset.action.connect(self.reset)
        self.fileSave = QAction(MainWindow)
        self.fileSave.setObjectName("fileSave")
        self.menuFile.addAction(self.fileReset)
        self.menuFile.addAction(self.fileSave)
        self.menuViews.addAction(self.viewsBasic)
        self.menuViews.addAction(self.viewsTrail)
        self.menuViews.addAction(self.viewsHeatmap)
        self.menuViews.addAction(self.viewsOpenGL)

        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuViews.menuAction())

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.checkBox1.setText(_translate("MainWindow", "Add constant"))
        self.checkBox2.setText(_translate("MainWindow", "Dim. removal"))
        self.checkBox3.setText(_translate("MainWindow", "Perturbation3"))
        self.checkBox4.setText(_translate("MainWindow", "Perturbation4"))
        self.perturbSelectedButton.setText(
            _translate("MainWindow", "Randomize selected"))
        self.reset.setText(_translate("MainWindow", "Reset"))
        self.perturbationSlidersLabel.setText(
            _translate("MainWindow", "Perturbation sliders"))

        self.menuFile.setTitle(_translate("MainWindow", "File"))
        self.menuViews.setTitle(_translate("MainWindow", "Views"))

        self.viewsBasic.setText(_translate("MainWindow", "Basic interface"))
        self.viewsBasic.setShortcut(_translate("MainWindow", "Ctrl+1"))
        self.viewsTrail.setText(_translate("MainWindow", "Trail interface"))
        self.viewsTrail.setShortcut(_translate("MainWindow", "Ctrl+2"))
        self.viewsHeatmap.setText(
            _translate("MainWindow", "Heat map interface"))
        self.viewsHeatmap.setShortcut(_translate("MainWindow", "Ctrl+3"))
        self.viewsOpenGL.setText(_translate("MainWindow", "OpenGL interface"))
        self.viewsOpenGL.setShortcut(_translate("MainWindow", "Ctrl+4"))

        self.fileReset.setText(_translate("MainWindow", "Reset"))
        self.fileReset.setShortcut(_translate("MainWindow", "Ctrl+R"))
        self.fileSave.setText(_translate("MainWindow", "Save"))
        self.fileSave.setShortcut(_translate("MainWindow", "Ctrl+S"))

    def switchWidget(self, index):
        self.stackedWidget.setCurrentIndex(index)
        print("Going to stacked widget index: " + str(index))
        # TODO: only compute intermediateDatasets if not already done so
        if index == 1:
            self.statusbar.showMessage(
                "Computing and predicting intermediate datasets per increment..."
            )
            self.computeIntermediateDatasets()
            self.statusbar.showMessage("Drawing trail map...")
            self.projectTrailMap()
            self.statusbar.showMessage("Trail map projected.")
        if index == 2:
            self.statusbar.showMessage(
                "Computing and predicting intermediate datasets per increment..."
            )
            self.computeIntermediateDatasets()
            self.statusbar.showMessage("Drawing heat map...")
            self.projectHeatMap()
            self.statusbar.showMessage("Heat map projected.")
        if index == 3:
            self.statusbar.showMessage(
                "Computing and predicting intermediate datasets per increment..."
            )
            self.computeIntermediateDatasets()
            self.statusbar.showMessage("Drawing trail map...")
            if self.predList:
                self.openGLWidget.paintTrailMapGL(self.predList, self.y_test,
                                                  self.class_colors)
            else:
                print("No data to create trail map with.")
                self.statusbar.showMessage("No data to create trail map with.")

    def computeIntermediateDatasets(self):
        # If no checkbox is checked
        if not self.checkBox1.isChecked() and not self.checkBox2.isChecked() and \
                not self.checkBox3.isChecked() and not self.checkBox4.isChecked():
            self.statusbar.showMessage(
                "No perturbation is selected. Please choose one of them.")
            return

        print("Computing intermediate datasets")
        # Perturb using the checked perturbation
        if self.checkBox1.isChecked():
            max_value = self.horizontalSlider1.value()
            self.dataset.interDataOfPerturb(1, max_value)
        if self.checkBox2.isChecked():
            max_value = self.horizontalSlider2.value()
            self.dataset.interDataOfPerturb(2, max_value)

        # Predict every dataset and save to predList
        self.predList = []
        for i in range(0, len(self.dataset.interDataset)):
            self.predList.append(
                self.model.predict(self.dataset.interDataset[i]))

    # Project a trail map using the data in predList
    def projectTrailMap(self):
        for j in range(len(self.predList[0])):
            pen = pg.mkPen(color=self.y_test[j], width=1)
            for i in range(len(self.predList) - 1):
                x1 = self.predList[i][j][0]
                y1 = self.predList[i][j][1]
                x2 = self.predList[i + 1][j][0]
                y2 = self.predList[i + 1][j][1]
                self.trailsScene.addLine(x1, y1, x2, y2, pen)

        # Fit trail map to screen
        # self.trailsScene.itemsBoundingRect()
        self.trailsView.fitInView(0, 0, 1, 1, Qt.KeepAspectRatio)

    def projectHeatMap(selfs):
        pass

    def replot(self):
        pred = self.model.predict(self.dataset.perturbed)
        items = pg.ScatterPlotItem(x=pred[:, 0],
                                   y=pred[:, 1],
                                   data=np.arange(len(self.dataset.perturbed)),
                                   pen='w',
                                   brush=self.brushes,
                                   size=10,
                                   hoverable=True,
                                   hoverPen=pg.mkPen(0, 0, 0, 255))
        self.plotWidget.clear()
        self.plotWidget.addItem(items)
        # Disable range adjustments
        self.plotWidget.setRange(None, (0, 1), (0, 1))

        self.plotWidget.setXRange(0, 1)

    def slider1Changed(self):
        new_value = self.horizontalSlider1.value()
        self.statusbar.showMessage(
            "Changed value of perturbation slider 1 to " + str(new_value))
        self.dataset.addConstantNoise(new_value)
        self.replot()

    def slider2Changed(self):
        new_value = self.horizontalSlider2.value()
        self.statusbar.showMessage(
            "Changed value of perturbation slider 2 to " + str(new_value))
        self.dataset.removeRandomDimensions(new_value)
        self.replot()

    def slider3Changed(self):
        new_value = self.horizontalSlider3.value()
        self.statusbar.showMessage(
            "Changed value of perturbation slider 3 to " + str(new_value))

    def slider4Changed(self):
        new_value = self.horizontalSlider4.value()
        self.statusbar.showMessage(
            "Changed value of perturbation slider 4 to " + str(new_value))

    def randChangeSelected(self):
        if self.checkBox1.isChecked():
            self.horizontalSlider1.setValue(
                randint(1, self.horizontalSlider2.maximum()))
        if self.checkBox2.isChecked():
            self.horizontalSlider2.setValue(
                randint(1, self.horizontalSlider2.maximum()))
        if self.checkBox3.isChecked():
            self.horizontalSlider3.setValue(
                randint(1, self.horizontalSlider3.maximum()))
        if self.checkBox4.isChecked():
            self.horizontalSlider4.setValue(
                randint(1, self.horizontalSlider4.maximum()))

    def resetSelected(self):
        if self.checkBox1.isChecked():
            self.horizontalSlider1.setValue(0)
        if self.checkBox2.isChecked():
            self.horizontalSlider2.setValue(0)
        if self.checkBox3.isChecked():
            self.horizontalSlider3.setValue(0)
        if self.checkBox4.isChecked():
            self.horizontalSlider4.setValue(0)

    def loadTestData(self, MainWindow):
        print("Loading dummy data...")
        x = np.random.normal(size=1000)
        y = np.random.normal(size=1000)

        brush = pg.mkBrush(50, 200, 50, 120)
        hoverBrush = pg.mkBrush(200, 50, 50, 200)
        items = pg.ScatterPlotItem(x=x,
                                   y=y,
                                   pen='w',
                                   brush=brush,
                                   size=15,
                                   hoverable=True,
                                   hoverBrush=hoverBrush)
        self.plotWidget.addItem(items)

    def loadData(self, MainWindow):
        print("Loading datasets...")
        X = np.load('data/X_mnist.npy')
        y = np.load('data/y_mnist.npy')
        label = "mnist-full"

        X_train, X_test, y_train, y_test = train_test_split(X,
                                                            y,
                                                            train_size=10000,
                                                            test_size=300,
                                                            random_state=420,
                                                            stratify=y)
        self.y_test = y_test

        # Class colors
        self.class_colors = [(0.890, 0.102, 0.110), (0.122, 0.471, 0.706),
                             (0.698, 0.875, 0.541), (0.200, 0.627, 0.173),
                             (0.984, 0.604, 0.600), (0.651, 0.808, 0.890),
                             (0.992, 0.749, 0.435), (1.000, 0.498, 0.000),
                             (0.792, 0.698, 0.839), (0.416, 0.239, 0.604),
                             (1.000, 1.000, 0.600), (0.694, 0.349, 0.147)]

        self.dataset = Dataset(X_test)

        print("Loading NNP model...")
        self.model = keras.models.load_model("NNP_model_" + label)

        pred = self.model.predict(X_test)
        self.brushes = []
        for label in y_test:
            color = self.class_colors[label]
            self.brushes.append(
                QBrush(QColor.fromRgbF(color[0], color[1], color[2])))

        items = pg.ScatterPlotItem(x=pred[:, 0],
                                   y=pred[:, 1],
                                   data=np.arange(len(X_test)),
                                   pen='w',
                                   brush=self.brushes,
                                   size=10,
                                   hoverable=True,
                                   hoverPen=pg.mkPen(0, 0, 0, 255))

        self.plotWidget.addItem(items)