Exemple #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)
Exemple #2
0
class SensirionSBPlot(QWidget):
    def __init__(self, plot_title, color, bufferSize):
        super().__init__()
        masterLayout = QVBoxLayout()
        self.pen = mkPen(color, width=1.25)

        layout = QVBoxLayout()
        self.group = QGroupBox(plot_title)
        self.plot = PlotWidget()
        self.plot.getPlotItem().showGrid(x=True, y=True, alpha=1)
        if "qdarkstyle" in sys.modules:
            self.plot.setBackground((25, 35, 45))
        self.buffer = RingBuffer(capacity=bufferSize, dtype=float)

        self.group.setLayout(layout)
        layout.addWidget(self.plot)
        masterLayout.addWidget(self.group)

        self.setLayout(masterLayout)

    def change_capacity(self, value):
        if value > len(self.buffer):
            newBuf = RingBuffer(capacity=value, dtype=float)
            newBuf.extend(self.buffer)
            self.buffer = newBuf

        elif value < len(self.buffer):
            newBuf = RingBuffer(capacity=value, dtype=float)
            newBuf.extend(self.buffer[:-value])
            self.buffer = newBuf

    def update_plot(self, sample):
        self.plot.clear()
        self.buffer.append(sample)
        self.plot.plot(self.buffer, pen=self.pen, symbolPen=self.pen, symbol='o', symbolSize=5, name="symbol ='o'")
class PyQtGraphDataPlot(QWidget):
    _colors = [
        Qt.red, Qt.blue, Qt.magenta, Qt.cyan, Qt.green, Qt.darkYellow,
        Qt.black, Qt.darkRed, Qt.gray, Qt.darkCyan
    ]

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

        self._color_index = 0
        self._curves = {}

    def add_curve(self, curve_id, curve_name, data_x, data_y):
        color = QColor(self._colors[self._color_index % len(self._colors)])
        self._color_index += 1
        pen = mkPen(color, width=1)
        plot = self._plot_widget.plot(name=curve_name, pen=pen)
        data_x = numpy.array(data_x)
        data_y = numpy.array(data_y)
        self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot}
        self._update_legend()

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

    def _update_legend(self):
        # TODO Figure this out
        pass

    @Slot(str, list, list)
    def update_values(self, curve_id, x, y):
        curve = self._curves[curve_id]
        curve['x'] = numpy.append(curve['x'], x)
        curve['y'] = numpy.append(curve['y'], y)

    def redraw(self):
        # Set axis bounds
        x_range, _ = self._plot_widget.viewRange()
        x_delta = x_range[1] - x_range[0]
        x_max = 0
        for curve in self._curves.values():
            if len(curve['x']) == 0:
                continue

            x_max = max(x_max, curve['x'][-1])
            curve['plot'].setData(curve['x'], curve['y'])

        self._plot_widget.setXRange(x_max - x_delta, x_max, padding=0)
Exemple #4
0
class RealtimePlotWidget(QWidget):
    COLORS = [
        Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan, Qt.darkRed,
        Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray
    ]

    def __init__(self, parent=None):
        super(RealtimePlotWidget, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.setBackground((0, 0, 0))
        self._plot_widget.addLegend()
        self._plot_widget.showButtons()
        self._plot_widget.enableAutoRange()
        self._plot_widget.showGrid(x=True, y=True, alpha=0.2)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)

        self._color_index = 0
        self._curves = {}

    def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]):
        color = QColor(self.COLORS[self._color_index % len(self.COLORS)])
        self._color_index += 1
        pen = mkPen(color, width=1)
        plot = self._plot_widget.plot(name=curve_name, pen=pen)
        data_x = numpy.array(data_x)
        data_y = numpy.array(data_y)
        self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot}

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

    def set_x_range(self, left, right):
        self._plot_widget.setRange(xRange=(left, right))

    def update_values(self, curve_id, x, y):
        curve = self._curves[curve_id]
        curve['x'] = numpy.append(curve['x'], x)
        curve['y'] = numpy.append(curve['y'], y)

    def redraw(self):
        for curve in self._curves.values():
            if len(curve['x']):
                curve['plot'].setData(curve['x'], curve['y'])

    def lazy_redraw(self, period):
        timestamp = time.time()
        if not hasattr(self, '_prev_lazy_redraw'):
            self._prev_lazy_redraw = 0.0
        if timestamp - self._prev_lazy_redraw > period:
            self._prev_lazy_redraw = timestamp
            self.redraw()
Exemple #5
0
class RealtimePlotWidget(QWidget):
    COLORS = [Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan,
              Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray]

    def __init__(self, parent=None):
        super(RealtimePlotWidget, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.setBackground((0, 0, 0))
        self._plot_widget.addLegend()
        self._plot_widget.showButtons()
        self._plot_widget.enableAutoRange()
        self._plot_widget.showGrid(x=True, y=True, alpha=0.2)
        vbox = QVBoxLayout()
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)

        self._color_index = 0
        self._curves = {}

    def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]):
        color = QColor(self.COLORS[self._color_index % len(self.COLORS)])
        self._color_index += 1
        pen = mkPen(color, width=1)
        plot = self._plot_widget.plot(name=curve_name, pen=pen)
        data_x = numpy.array(data_x)
        data_y = numpy.array(data_y)
        self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot}

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

    def set_x_range(self, left, right):
        self._plot_widget.setRange(xRange=(left, right))

    def update_values(self, curve_id, x, y):
        curve = self._curves[curve_id]
        curve['x'] = numpy.append(curve['x'], x)
        curve['y'] = numpy.append(curve['y'], y)

    def redraw(self):
        for curve in self._curves.values():
            if len(curve['x']):
                curve['plot'].setData(curve['x'], curve['y'])

    def lazy_redraw(self, period):
        timestamp = time.time()
        if not hasattr(self, '_prev_lazy_redraw'):
            self._prev_lazy_redraw = 0.0
        if timestamp - self._prev_lazy_redraw > period:
            self._prev_lazy_redraw = timestamp
            self.redraw()
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()
Exemple #7
0
class SimpleTestResultsDialog(QMainWindow):
    def __init__(self, parent=None, methods=None):
        super(SimpleTestResultsDialog, self).__init__(parent)
        self.setWindowTitle("Grismo - Wyniki dla prostego testu")
        self.setMinimumWidth(500)
        self.results_count = 0
        self.all_results = []
        self.methods = methods

        central = QWidget()
        self.setCentralWidget(central)

        result_dialog_layout = QVBoxLayout()
        central.setLayout(result_dialog_layout)

        self.results_table = QTableWidget()
        result_dialog_layout.addWidget(self.results_table)
        self.results_table.setRowCount(len(methods))
        self.results_table.setColumnCount(3)
        self.results_table.setColumnWidth(2, 200)
        self.results_table.setHorizontalHeaderLabels(["Metoda", "Wynik", "Czas [s]"])

        for i in range(len(methods)):
            self.results_table.setItem(i, 0, QTableWidgetItem(methods[i]))

        # plot box
        x_axis_dict = dict(enumerate(methods))
        x_axis = AxisItem(orientation='bottom')
        x_axis.setTicks([x_axis_dict.items()])
        self.results_plot = PlotWidget(axisItems={'bottom': x_axis})
        self.results_plot.setBackground('w')
        self.results_plot.setTitle("Porównanie metod dla wskazanych grafów")
        self.results_plot.setLabel('left', 'Czas obliczeń [s]', color='k', size=10)
        self.results_plot.setLabel('bottom', 'Metody ', color='k', size=10)
        self.results_plot.setMaximumWidth(600)
        self.results_plot.showGrid(y=True)
        result_dialog_layout.addWidget(self.results_plot)

        # prepare plot data
        pen = mkPen(color='k', width=2)
        self.plot_data = self.results_plot.plot([], [], pen=pen, symbol='+', symbolSize=10, symbolBrush='k')

    def add_result(self, result):
        for i in range(len(result)):
            self.results_table.setItem(self.results_count, i, QTableWidgetItem(str(result[i])))
        self.results_count = self.results_count + 1
        self.all_results.append(result[-1])
        self.plot_data.setData(range(len(self.all_results)), self.all_results)
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("Signal Viewer")
        MainWindow.resize(900, 700)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        #The Graph Area
        self.graphicsView = PlotWidget(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(20, 30, 761, 500))
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView.setBackground('#e1f5f3')

        MainWindow.setCentralWidget(self.centralwidget)

        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
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()
Exemple #10
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1326, 755)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.layoutWidget.setGeometry(QtCore.QRect(0, 0, 1290, 702))
        self.layoutWidget.setObjectName("layoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.formLayout = QtWidgets.QFormLayout()
        self.formLayout.setObjectName("formLayout")
        self.label = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole,
                                  self.label)
        self.doubleSpinBoxR = QtWidgets.QDoubleSpinBox(self.layoutWidget)
        self.doubleSpinBoxR.setMinimumSize(QtCore.QSize(100, 30))
        self.doubleSpinBoxR.setObjectName("doubleSpinBoxR")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole,
                                  self.doubleSpinBoxR)
        self.label_2 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole,
                                  self.label_2)
        self.doubleSpinBoxk = QtWidgets.QDoubleSpinBox(self.layoutWidget)
        self.doubleSpinBoxk.setMinimumSize(QtCore.QSize(100, 30))
        self.doubleSpinBoxk.setObjectName("doubleSpinBoxk")
        self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole,
                                  self.doubleSpinBoxk)
        self.label_3 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole,
                                  self.label_3)
        self.doubleSpinBoxC = QtWidgets.QDoubleSpinBox(self.layoutWidget)
        self.doubleSpinBoxC.setMinimumSize(QtCore.QSize(100, 30))
        self.doubleSpinBoxC.setObjectName("doubleSpinBoxC")
        self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole,
                                  self.doubleSpinBoxC)
        self.label_4 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole,
                                  self.label_4)
        self.doubleSpinBoxT = QtWidgets.QDoubleSpinBox(self.layoutWidget)
        self.doubleSpinBoxT.setMinimumSize(QtCore.QSize(100, 30))
        self.doubleSpinBoxT.setMaximum(10.0)
        self.doubleSpinBoxT.setObjectName("doubleSpinBoxT")
        self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole,
                                  self.doubleSpinBoxT)
        self.label_5 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole,
                                  self.label_5)
        self.spinBoxI = QtWidgets.QSpinBox(self.layoutWidget)
        self.spinBoxI.setMinimumSize(QtCore.QSize(100, 30))
        self.spinBoxI.setMaximum(10000)
        self.spinBoxI.setObjectName("spinBoxI")
        self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole,
                                  self.spinBoxI)
        self.label_6 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole,
                                  self.label_6)
        self.spinBoxK = QtWidgets.QSpinBox(self.layoutWidget)
        self.spinBoxK.setMinimumSize(QtCore.QSize(100, 30))
        self.spinBoxK.setMaximum(10000)
        self.spinBoxK.setObjectName("spinBoxK")
        self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole,
                                  self.spinBoxK)
        self.label_7 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole,
                                  self.label_7)
        self.label_8 = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_8.setFont(font)
        self.label_8.setObjectName("label_8")
        self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole,
                                  self.label_8)
        self.resultch = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.resultch.setFont(font)
        self.resultch.setText("")
        self.resultch.setObjectName("resultch")
        self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole,
                                  self.resultch)
        self.resultanal = QtWidgets.QLabel(self.layoutWidget)
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.resultanal.setFont(font)
        self.resultanal.setText("")
        self.resultanal.setObjectName("resultanal")
        self.formLayout.setWidget(8, QtWidgets.QFormLayout.FieldRole,
                                  self.resultanal)
        self.verticalLayout.addLayout(self.formLayout)
        self.result = QtWidgets.QLabel(self.layoutWidget)
        self.result.setText("")
        self.result.setObjectName("result")
        self.verticalLayout.addWidget(self.result)
        self.pushButton = QtWidgets.QPushButton(self.layoutWidget)
        self.pushButton.setMinimumSize(QtCore.QSize(200, 30))
        self.pushButton.setMaximumSize(QtCore.QSize(200, 30))
        self.pushButton.setSizeIncrement(QtCore.QSize(10, 10))
        self.pushButton.setBaseSize(QtCore.QSize(10, 10))
        self.pushButton.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.pushButton.setObjectName("pushButton")
        self.verticalLayout.addWidget(self.pushButton, 0,
                                      QtCore.Qt.AlignHCenter)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.graphicsView = PlotWidget(self.layoutWidget)
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView.setBackground('w')
        self.horizontalLayout.addWidget(self.graphicsView)
        self.graphicsView.plotItem.setLabel(axis='left', text="u(θ,t)")
        self.graphicsView.plotItem.showGrid(x=True, y=True, alpha=1.0)
        self.graphicsView.plotItem.setLabel(axis='bottom', text="θ")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1326, 26))
        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", "Радиус, R "))
        self.label_2.setText(
            _translate("MainWindow", "Коэффициент теплопроводности, k"))
        self.label_3.setText(
            _translate("MainWindow", "Коэффициент объёмной теплоёмкости, с"))
        self.label_4.setText(
            _translate("MainWindow", "Временной промежуток 0 < t < T, t"))
        self.label_5.setText(_translate("MainWindow",
                                        "Параметр сетки по θ, I"))
        self.label_6.setText(_translate("MainWindow",
                                        "Параметр сетки по t, K"))
        self.label_7.setText(_translate("MainWindow", "Численое решение"))
        self.label_8.setText(_translate("MainWindow", "Аналитическое решение"))
        self.pushButton.setText(_translate("MainWindow", "Построить график"))
Exemple #11
0
class PyQtGraphDataPlot(QWidget):
    _colors = [
        Qt.red, Qt.blue, Qt.magenta, Qt.cyan, Qt.green, Qt.darkYellow,
        Qt.black, Qt.darkRed, Qt.gray, Qt.darkCyan
    ]

    def __init__(self, parent=None):
        super(PyQtGraphDataPlot, self).__init__(parent)
        self._plot_widget = PlotWidget()
        self._plot_widget.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._autoscroll = False
        self._color_index = 0
        self._curves = {}

    def add_curve(self, curve_id, curve_name, data_x, data_y):
        color = QColor(self._colors[self._color_index % len(self._colors)])
        self._color_index += 1
        pen = mkPen(color, width=2)
        # this adds the item to the plot and legend
        plot = self._plot_widget.plot(name=curve_name, pen=pen)
        data_x = numpy.array(data_x)
        data_y = numpy.array(data_y)
        self._curves[curve_id] = {'x': data_x, 'y': data_y, 'plot': plot}

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self._curves:
            self._plot_widget.getPlotItem().removeItem(
                self._curves[curve_id]['plot'])
            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.getPlotItem().clear()
        self._plot_widget.getPlotItem().legend.items = []
        for curve in self._curves.values():
            self._plot_widget.getPlotItem().addItem(curve['plot'])

    @Slot(str, list, list)
    def update_values(self, curve_id, x, y):
        curve = self._curves[curve_id]
        curve['x'] = numpy.append(curve['x'], x)
        curve['y'] = numpy.append(curve['y'], y)

    def autoscroll(self, enabled=True):
        self._autoscroll = enabled

    def redraw(self):
        for curve in self._curves.values():
            curve['plot'].setData(curve['x'], curve['y'])

        if self._autoscroll:
            # Set axis bounds
            x_range, _ = self._plot_widget.viewRange()
            x_delta = x_range[1] - x_range[0]
            x_max = 0

            for curve in self._curves.values():
                if len(curve['x']) == 0:
                    continue
                x_max = max(x_max, curve['x'][-1])

            self._plot_widget.setXRange(x_max - x_delta, x_max, padding=0)
Exemple #12
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)
Exemple #13
0
class MesCourbes():
    def __init__(self):
        self.plot_widget = PlotWidget()
        self.plot_widget.showGrid(x=True, y=True)
        # self.plot_widget.getPlotItem().addLegend()
        self.plot_widget.setBackground((0, 0, 0))
        #  dictionary with all the curve and their data
        # curve 0 is dedicated to the live/acquisition plot
        self.curves = {}

    def add_curve(self, curve_id, curve_color, markers_on=False):
        curve_name = curve_id
        pen = pg.mkPen(curve_color, width=3)
        symbol = "o"
        symbolPen = pg.mkPen(0, 0, 0)
        symbolBrush = curve_color
        symbolSize = 8
        # 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=symbolSize)
        else:
            plot = self.plot_widget.plot(name=curve_name, pen=pen)
        self.curves[curve_id] = {
            'plot': plot,
            'data': {
                'X': [],
                'Y': [],
                'R': [],
                'Phi': []
            }
        }

    def clear_data(self, curve_id):
        for k in ['Time', 'X', 'Y', 'R', 'Phi']:
            self.curves[curve_id]['data'][k] = []

    # def display(self,curve_id,what):
    #     X = self.curves[curve_id]['data']['Freq']
    #     Y = self.curves[curve_id]['data'][what]
    #     # during acquisition freq is longer than the others datas
    #     # so it is useful to reduce it
    #     if len(X) != len(Y):
    #         X = self.curves[curve_id]['data']['Freq'][0:len(Y)]
    #     self.set_values(curve_id,X,Y)

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self.curves:
            self.plot_widget.removeItem(self.curves[curve_id]['plot'])
            del self.curves[curve_id]

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

    def update_X_Y_R_Phi(self, curve_id, A):
        self.curves[curve_id]['data']['X'] = np.append(
            self.curves[curve_id]['data']['X'], A[0])
        self.curves[curve_id]['data']['Y'] = np.append(
            self.curves[curve_id]['data']['Y'], A[1])
        self.curves[curve_id]['data']['R'] = np.append(
            self.curves[curve_id]['data']['R'], A[2])
        self.curves[curve_id]['data']['Phi'] = np.append(
            self.curves[curve_id]['data']['Phi'], A[3])
Exemple #14
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        self.resize(1920, 1080)
        self.status = False
        self.setAutoFillBackground(False)
        self.setDocumentMode(False)

        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))

        self.exitAct = QAction(QIcon('exit.png'), '&Exit', self)
        self.exitAct.setShortcut('Ctrl+Q')
        self.exitAct.setStatusTip('Exit application')
        self.exitAct.triggered.connect(qApp.quit)

        self.loadAct = QAction(QIcon('exit.png'), '&Import Unfolding', self)
        self.loadAct.setShortcut('Ctrl+L')
        self.loadAct.setStatusTip('Import Unfolding')
        self.loadAct.triggered.connect(self.openFileNameDialog)

        self.exportAct = QAction(QIcon('exit.png'), '&Export Unfolding', self)
        self.exportAct.setShortcut('Ctrl+E')
        self.exportAct.setStatusTip('Export Unfolding')
        self.exportAct.triggered.connect(self.exportUnfolding)

        self.writeNPAct = QAction(QIcon('exit.png'),
                                  '&Write coordinates as np file', self)
        self.writeNPAct.setShortcut('Ctrl+W')
        self.writeNPAct.setStatusTip('Write coordinates')
        self.writeNPAct.triggered.connect(self.writeNP_file)

        self.loadGeometryAct = QAction(QIcon('exit.png'),
                                       '&Load geometry from .log file', self)
        #self.loadGeometry.setShortcut('Ctrl+W')
        self.loadGeometryAct.setStatusTip('Load geometry')
        self.loadGeometryAct.triggered.connect(self.loadGeometry)

        self.select_directoryAct = QAction(
            QIcon('exit.png'),
            '&Select a directory to generate hdf5 files from', self)
        self.select_directoryAct.setStatusTip('Select directory')
        self.select_directoryAct.triggered.connect(self.select_directory)

        self.load_HDF5Act = QAction(QIcon('exit.png'),
                                    '&Select a hdf5 files for the DFT data',
                                    self)
        self.load_HDF5Act.setStatusTip('Select HDF5')
        self.load_HDF5Act.triggered.connect(self.load_hdf5_scan)

        self.statusBar()

        self.menubar = self.menuBar()
        self.fileMenu = self.menubar.addMenu('&File')
        self.fileMenu.addAction(self.exitAct)
        self.fileMenu.addAction(self.loadAct)
        self.fileMenu.addAction(self.exportAct)
        self.fileMenu.addAction(self.writeNPAct)
        self.fileMenu.addAction(self.loadGeometryAct)
        self.fileMenu.addAction(self.select_directoryAct)
        self.fileMenu.addAction(self.load_HDF5Act)

        self.horizontalLayout = QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setSpacing(10)

        self.verticalLayout = QVBoxLayout()

        ### Containing the integration buttons
        self.horizontalLayout_2 = QHBoxLayout()

        ### Containing the inital/final position show
        self.finalPositionLayout = QHBoxLayout()

        self.gl_widget = gl.GLViewWidget()
        self.gl_widget.setCameraPosition(distance=20, elevation=40)
        self.gl_widget.setGeometry(0, 110, 1920, 1080)

        self.energy_Plot = PlotWidget()
        self.energy_Plot.setObjectName(_fromUtf8("energyPlot"))
        self.energy_Plot.setBackground('k')
        # set properties of the label for y axis
        self.energy_Plot.setLabel('left', 'E(B3LYP)', units='H')

        # set properties of the label for x axis
        self.energy_Plot.setLabel('bottom', 'CC-distance', units='A')

        # adding legend
        self.energy_Plot.addLegend()

        self.horizontalLayout.addWidget(self.gl_widget, 4)

        ### Push button for sinle integration
        self.btnUp = QPushButton()
        self.btnUp.setObjectName(_fromUtf8("btnUp"))

        ### Check box for continous integration
        self.chkIntegrate = QCheckBox()
        self.chkIntegrate.setObjectName(_fromUtf8("chkIntegrate"))

        ### SpinBox to set the size of the integration step
        self.spinStep = QSpinBox()
        self.spinStep.setMinimum(0)
        self.spinStep.setMaximum(10000)
        self.spinStep.setObjectName(_fromUtf8("spinStep"))

        ### final position button
        self.btnFin = QPushButton()
        self.btnFin.setObjectName(_fromUtf8("btnFin"))

        ### initial position button
        self.btnInit = QPushButton()
        self.btnInit.setObjectName(_fromUtf8("btnPos"))

        ### select hinges button
        self.btnSelHinge = QPushButton()
        self.btnSelHinge.setObjectName(_fromUtf8("btnSelHinge"))

        ### close unfolding button
        self.btnClose = QPushButton()
        self.btnClose.setObjectName(_fromUtf8("btnClose"))

        ### add the buttons to the integration layout
        self.horizontalLayout_2.addWidget(self.spinStep)
        self.horizontalLayout_2.addWidget(self.btnUp)
        self.horizontalLayout_2.addWidget(self.chkIntegrate)

        ## add final position button to layout
        self.finalPositionLayout.addWidget(self.btnInit)
        self.finalPositionLayout.addWidget(self.btnFin)
        self.finalPositionLayout.addWidget(self.btnSelHinge)
        self.finalPositionLayout.addWidget(self.btnClose)

        ### add integration and final position layout and plot widget to right side layout
        self.verticalLayout.addLayout(self.horizontalLayout_2, 1)
        self.verticalLayout.addLayout(self.finalPositionLayout, 1)
        self.verticalLayout.addWidget(self.energy_Plot, 6)

        self.horizontalLayout.addLayout(self.verticalLayout, 1)

        self.widget = QWidget()
        self.widget.setLayout(self.horizontalLayout)
        self.setCentralWidget(self.widget)

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

        self.setWindowTitle('Fullerene Unfolding')

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.btnUp.setText("Integrate")
        self.chkIntegrate.setText("Keep integrating")
        self.btnFin.setText("Final position")
        self.btnInit.setText("Initial position")
        self.btnClose.setText("Close unfolding")
        self.btnSelHinge.setText("Select Hinges")
class 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 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>"
                ),
            )
Exemple #17
0
class widget_mfi_lin_plot(QWidget):

    #-----------------------------------------------------------------------
    # DEFINE THE INITIALIZATION FUNCTION.
    #-----------------------------------------------------------------------

    def __init__(self, core):

        # Inherit all attributes of an instance of "QWidget".

        super(widget_mfi_lin_plot, self).__init__()

        # Store the Janus core.

        self.core = core

        # Prepare to respond to signals received from the core.

        self.connect(self.core, SIGNAL('janus_rset'), self.resp_rset)
        self.connect(self.core, SIGNAL('janus_chng_mfi'), self.resp_chng_mfi)

        # Initialize this widget's instance of "PlotWidget", which will
        # contain the plot of MFI magnetic field data.

        # Note.  The "QGridLayout" object given to this widget as its
        #        layout is essentially a dummy.  I could have just had
        #        this class inherit "PlotWidget", but I think that this
        #        gives me a bit more control (and a similar structure
        #        "janus_widget_fc_cup").

        self.setLayout(QGridLayout())

        self.plt = PlotWidget()
        self.layout().addWidget(self.plt)

        self.layout().setContentsMargins(0, 0, 0, 0)

        # Extract the individual elements of the "PlotWidget" object
        # (e.g., it's axes) for more convenient access later.

        self.vbx = self.plt.getViewBox()

        self.axs_x = self.plt.getAxis('bottom')
        self.axs_y = self.plt.getAxis('left')

        self.ptm = self.plt.getPlotItem()

        # Initialize and store the pens and fonts.

        self.pen_vbx = mkPen(color='k')
        self.pen_crv_m = mkPen(color='k')
        self.pen_crv_n = mkPen(color='k')
        self.pen_crv_x = mkPen(color='r')
        self.pen_crv_y = mkPen(color='g')
        self.pen_crv_z = mkPen(color='b')

        self.fnt = self.core.app.font()

        # Configure the plot: disable automatic adjustments and
        # adjustments made by the user, change the background and
        # foreground colors, enable grid lines for both axes, label the
        # axes, adjust the tick font size, adjust the "AxisItem" sizes,
        # and add a margin around the entire plot.

        self.plt.disableAutoRange()
        self.plt.setMouseEnabled(False, False)
        self.plt.setMenuEnabled(False)
        self.plt.hideButtons()

        self.plt.setBackground('w')
        setConfigOption('foreground', 'k')

        #####self.plt.showGrid( True, True )

        labelStyle = {'color': 'k'}
        self.axs_x.setLabel('Time [s]', **labelStyle)
        self.axs_y.setLabel('Magnetic Field [nT]', **labelStyle)

        self.axs_x.label.setFont(self.fnt)
        self.axs_y.label.setFont(self.fnt)

        self.axs_x.setTickFont(self.fnt)
        self.axs_y.setTickFont(self.fnt)

        self.axs_x.setHeight(35)
        self.axs_y.setWidth(40)

        self.vbx.border = self.pen_vbx

        self.ptm.setContentsMargins(5, 5, 5, 5)

        # Initialize the curves that will be added to this plot.

        self.crv_m = None
        self.crv_n = None
        self.crv_x = None
        self.crv_y = None
        self.crv_z = None
        self.pl = []

        # Populate this plot and adjust it's settings.

        self.make_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR POPULATING THE PLOT.
    #-----------------------------------------------------------------------

    def make_plt(self):

        # Reset the plot (i.e., remove all plot elements).

        self.rset_plt()

        # Establish the ranges of its time and magnetic field values.
        # If the core contains no data or only a single datum,
        # improvise (for the purpose of later establishing axis limits).

        if (self.core.n_mfi >= 1):

            # Establish the domain of the plot.

            t_min = min(amin(self.core.mfi_s), 0.)
            t_max = max(amax(self.core.mfi_s), self.core.fc_spec['dur'])

            # Establish the range of the plot.  As part of this,
            # ensure that the range satisfies a minimum size and has
            # sufficient padding.

            b_max = amax(self.core.mfi_b)
            b_min = -b_max

            d_t_0 = t_max - t_min
            d_b_0 = b_max - b_min

            d_t = max(1.5 + d_t_0, 3.)
            d_b = max(1.2 * d_b_0, 5.)

            t_max = t_min + d_t

            b_min = b_min - (d_b - d_b_0) / 2.
            b_max = b_max + (d_b - d_b_0) / 2.

        else:

            t_min = 0.001
            t_max = 3.500

            b_min = -2.5
            b_max = 2.5

        # Set the range of the axis of each plot.

        self.plt.setXRange(t_min, t_max, padding=0.0)
        self.plt.setYRange(b_min, b_max, padding=0.0)

        # Set the PESA-L pen with a width corresponding to one rotation
        # Note: For some reason, the lines are not wide enough unless 5
        #       is added to the scaled width of the rotation time

        rot = 3.05 * self.axs_x.width() / (t_max - t_min) + 5

        self.pen_pl = mkPen(color=(245, 245, 245), width=rot)

        # If the core contains no Wind/MFI magnetic field data, return.

        if (self.core.n_mfi <= 0):
            return

        # Generate and display each curve for the plot.

        self.crv_m = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b,
                                  pen=self.pen_crv_m)
        self.crv_n = PlotDataItem(self.core.mfi_s,
                                  [-b for b in self.core.mfi_b],
                                  pen=self.pen_crv_n)
        self.crv_x = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_x,
                                  pen=self.pen_crv_x)
        self.crv_y = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_y,
                                  pen=self.pen_crv_y)
        self.crv_z = PlotDataItem(self.core.mfi_s,
                                  self.core.mfi_b_z,
                                  pen=self.pen_crv_z)

        # If PESA-L spectra were loaded, add the vertical indicators
        # showing their time relative to the start of the FC spectrum

        for n in range(len(self.core.pl_spec_arr)):

            time = self.core.pl_spec_arr[n]['time'][0]

            t_0 = self.core.fc_spec['time']

            delta_t = (time - t_0).total_seconds()

            self.pl += [
                InfiniteLine(delta_t + self.core.fc_spec['rot'] / 2.,
                             pen=self.pen_pl)
            ]

        for i in range(len(self.pl)):

            self.plt.addItem(self.pl[i])

        self.plt.addItem(self.crv_m)
        self.plt.addItem(self.crv_n)
        self.plt.addItem(self.crv_x)
        self.plt.addItem(self.crv_y)
        self.plt.addItem(self.crv_z)

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESETTING THIS PLOT (CLEARING ALL ELEMENTS).
    #-----------------------------------------------------------------------

    def rset_plt(self):

        # Hide and remove each of this plot's elements.

        if (self.crv_m is not None):
            self.plt.removeItem(self.crv_m)

        if (self.crv_n is not None):
            self.plt.removeItem(self.crv_n)

        if (self.crv_x is not None):
            self.plt.removeItem(self.crv_x)

        if (self.crv_y is not None):
            self.plt.removeItem(self.crv_y)

        if (self.crv_z is not None):
            self.plt.removeItem(self.crv_z)

        if (self.pl != []):

            for i in range(len(self.pl)):

                self.plt.removeItem(self.pl[i])

        # if ( self.crv_colat is not None ) :
        # 	self.plt.removeItem( self.crv_colat )

        # if ( self.crv_lon is not None ) :
        # 	self.plt.removeItem( self.crv_lon )

        # Permanently delete this plot's elements by setting each of the
        # variables that store them to "None".

        self.crv_m = None
        self.crv_n = None
        self.crv_x = None
        self.crv_y = None
        self.crv_z = None
        self.pl = []

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "rset" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_rset(self):

        # Reset the plot.

        self.rset_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "chng_mfi" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_chng_mfi(self):

        # Regenerate the plot.

        self.make_plt()
Exemple #18
0
class DirectDriveWindow(QWidget):
    virtual_controller = None  # will hold an instance of the VirtualController-class
    motor_controller = None  # will hold an instance of the MotorController-class
    game_interfacer = None  # will hold an instance of the GameInterfacer-class

    # Variables that will be shared between multiple processes
    raw_force_signal_global = Value(
        'f', 0.0)  # raw force-feedback value coming from the game
    game_status_playing_global = Value(
        'b', False)  # game status (playing/not-playing)
    motor_pause_mode = Value(
        'b', False)  # if the motor should be idle when game is paused

    data_reconstruction = Value(
        'b', False)  # if the data-reconstruction feature should be used
    data_smoothing_level = Value(
        'i', 0)  # if the temproal smoothing feature should be used

    friction_global = Value('f', 0.0)  # strength of the friction effect
    damping_global = Value('f', 0.0)  # strength of the damping effect
    inertia_global = Value('f', 0.0)  # strength of the inertia effect

    encoder_pos_global = Value(
        'f', 0.0)  # holds the wheel position in encoder counts
    wheel_position_deg_global = Value(
        'f', 0.0)  # holds the wheel position in degrees
    lock_to_lock_global = Value(
        'f', 900.0
    )  # holds the digital limit of the wheel (used by the virtual controller)
    bump_to_bump_global = Value(
        'f', 900.0
    )  # holds the physical limit of the wheel (used by the motor controller)

    motor_current_global = Value(
        'f', 0.0
    )  # holds the current(Ampere) that is applied to the motor at any moment

    actual_max_force_global = Value(
        'f', 0.0
    )  # sets the actual maximum torque(Nm) the motor should be limited to
    invert_force_global = Value(
        'b', False)  # if the raw force-feedback value should be inverted

    motor_connected_global = Value(
        'b', False)  # motor status (connected/not-connected)
    motor_controller_due_for_restart_global = Value(
        'b', False)  # is set to true when connection to odrive board is lost

    motor_control_rate = Value(
        'f', 0.0)  # target refresh rate for the motor-control process

    profiles = []  # holds all loaded and newly created profiles
    selected_profile_index = 0  # holds the index of the currently selected profile

    graph_sample_rate = 60  # update-rate(Hz) for the motor-current graph
    graph_history_time_sec = 2  # time-window of the motor-current graph

    def __init__(self):
        super().__init__()
        self.setGeometry(100, 100, 1700, 575)
        self.setWindowTitle('DIY Direct Drive Wheel')

        #self.updater = LiveGuiUpdater()
        #self.updater.ticked.connect(self.LiveGuiTick)
        #self.updater.start()

        self.timer = QTimer()
        self.timer.timeout.connect(self.graph_update)
        self.timer.setInterval(int(1000 / self.graph_sample_rate))
        self.timer.start()

        self.gui_timer = QTimer()
        self.gui_timer.timeout.connect(self.LiveGuiTick)
        self.gui_timer.setInterval(int(1000 / 60))
        self.gui_timer.start()

        self.virtual_controller = VirtualController()
        self.virtual_controller.set_frequency(180)
        self.virtual_controller.steering_value_deg = self.wheel_position_deg_global
        self.virtual_controller.lock_to_lock = self.lock_to_lock_global
        self.virtual_controller.start()

        self.game_interfacer = GameInterfacer()
        self.game_interfacer.set_frequency(180)
        self.game_interfacer.wheel_force = self.raw_force_signal_global
        self.game_interfacer.invert_force = self.invert_force_global
        self.game_interfacer.game_status_playing = self.game_status_playing_global

        self.motor_controller = MotorController()
        self.motor_controller.set_frequency(360)
        self.motor_controller.signal_in = self.raw_force_signal_global
        self.motor_controller.game_status_playing = self.game_status_playing_global
        self.motor_controller.motor_pause_mode = self.motor_pause_mode
        self.motor_controller.data_reconstruction = self.data_reconstruction
        self.motor_controller.data_smoothing_level = self.data_smoothing_level
        self.motor_controller.friction = self.friction_global
        self.motor_controller.damping = self.damping_global
        self.motor_controller.inertia = self.inertia_global
        self.motor_controller.encoder_pos = self.encoder_pos_global
        self.motor_controller.wheel_pos_deg = self.wheel_position_deg_global
        self.motor_controller.bump_to_bump = self.bump_to_bump_global
        self.motor_controller.motor_current = self.motor_current_global
        self.motor_controller.actual_max_force = self.actual_max_force_global
        self.motor_controller.motor_connected = self.motor_connected_global
        self.motor_controller.due_for_restart = self.motor_controller_due_for_restart_global
        self.motor_controller.achieved_freq = self.motor_control_rate
        self.motor_controller.start()

        self.lblMotorRate = QLabel('motor control rate:', self)
        self.lblMotorRate.setFont(QFont("Times", 24, QFont.Normal))
        self.lblMotorRate.move(675, 25)

        self.lblMotorRateHz = QLabel('0.00 Hz', self)
        self.lblMotorRateHz.setFont(QFont("Times", 24, QFont.Normal))
        self.lblMotorRateHz.adjustSize()
        self.lblMotorRateHz.move(1125 - self.lblMotorRateHz.width(), 25)

        self.force_graph = PlotWidget(self)
        self.force_graph.move(675, 75)
        self.force_graph.resize(1000, 475)
        self.force_graph.setYRange(-15.0, 15.0)
        self.force_graph.setBackground((255, 255, 255))
        self.force_graph.showGrid(x=False, y=True)
        self.force_graph.addLegend()

        pen_ffb = pg.mkPen(color=(0, 0, 255))
        self.ffb_curve = self.force_graph.getPlotItem().plot(
            pen=pen_ffb, name='Game FFB (Nm)')
        pen_current = pg.mkPen(color=(0, 255, 0))
        self.current_curve = self.force_graph.getPlotItem().plot(
            pen=pen_current, name='Motor Torque (Nm)')
        self.ffb_history = [
            0
        ] * self.graph_sample_rate * self.graph_history_time_sec
        self.current_history = [
            0
        ] * self.graph_sample_rate * self.graph_history_time_sec

        self.load_profiles_from_file()
        self.build_gui()
        self.select_profile(0)

    # updates the graph showing the raw ffb and the motor torque
    def graph_update(self):
        # adding the latest raw game-ffb value(scaled to the actual torque value) to a list storing a history of this value
        self.ffb_history.append(self.raw_force_signal_global.value /
                                self.actual_max_force_global.value)
        if len(self.ffb_history
               ) >= self.graph_history_time_sec * self.graph_sample_rate:
            self.ffb_history.pop(0)
        self.ffb_curve.setData(self.ffb_history)

        # adding the latest final motor torque value to a list storing a history of this value
        self.current_history.append(
            self.motor_current_global.value /
            (self.actual_max_force_global.value * 2.75))
        if len(self.current_history
               ) >= self.graph_history_time_sec * self.graph_sample_rate:
            self.current_history.pop(0)
        self.current_curve.setData(self.current_history)

        # displaying the actually achieved refresh rate of the motor-control process
        self.lblMotorRateHz.setText(
            str(int(self.motor_control_rate.value * 100) / 100) + ' Hz')
        if self.motor_control_rate.value >= 360.0:
            self.lblMotorRateHz.setStyleSheet(
                'QLabel { color: rgb(0,155,0); }')
        else:
            self.lblMotorRateHz.setStyleSheet(
                'QLabel { color: rgb(155,0,0); }')

    # initializes and configures all the GUI-elements
    def build_gui(self):
        # WHEEL POSITION DATA AND SETTINGS

        # current bar
        self.lblCurrent = QLabel(self)
        self.lblCurrent.move(25 + 128, 25)
        self.lblCurrent.resize(0, 25)
        self.lblCurrent.setAutoFillBackground(True)
        self.lblCurrent.setStyleSheet(
            'QLabel { background-color: rgb(0,255,0); }')

        self.lblCurrentDivider = QLabel(self)
        self.lblCurrentDivider.move(25 + 128 - 1, 20)
        self.lblCurrentDivider.resize(2, 35)
        self.lblCurrentDivider.setAutoFillBackground(True)
        self.lblCurrentDivider.setStyleSheet(
            'QLabel { background-color: rgb(0,0,0); }')

        # wheel image
        self.lblWheelImage = QLabel(self)
        self.wheel_image = QImage('wheel_image.png')
        self.wheel_image_discon = QImage('wheel_image_disconnect.png')
        self.wheel_pixmap = QPixmap.fromImage(self.wheel_image)
        self.lblWheelImage.setPixmap(self.wheel_pixmap)
        self.lblWheelImage.resize(self.wheel_pixmap.width(),
                                  self.wheel_pixmap.height())
        self.lblWheelImage.move(25, 75)

        # motor status label
        self.lblMotorStatus_1 = QLabel('Motor Status:', self)
        self.lblMotorStatus_1.move(15, 60)
        self.lblMotorStatus_2 = QLabel('Not Connected', self)
        self.lblMotorStatus_2.move(15, 75)
        self.lblMotorStatus_2.setStyleSheet('QLabel { color: rgb(155,0,0); }')

        # wheel position
        self.lblWheelPos = QLabel('0.0°', self)
        self.lblWheelPos.move(25 + 150 + 25, 75 + 256 + 10)
        self.lblWheelPos.resize(200, 50)
        self.lblWheelPos.setFont(QFont("Times", 24, QFont.Normal))

        # center button
        center_pos = [25, 75 + 256 + 22, 150, 30]
        self.btnCenter = QPushButton('center Wheel', self)
        self.btnCenter.move(center_pos[0], center_pos[1])
        self.btnCenter.resize(center_pos[2], center_pos[3])
        self.btnCenter.clicked.connect(self.center_wheel)

        # lock-to-lock slider
        self.locklock_pos = [25, 425, 250, 0]
        self.lblLock = QLabel('Lock to Lock:', self)
        self.lblLock.move(self.locklock_pos[0], self.locklock_pos[1])
        self.sliLock = QSlider(Qt.Horizontal, self)
        self.sliLock.setTickPosition(QSlider.TicksAbove)
        self.sliLock.setTickInterval(10)
        self.sliLock.setMinimum(10)
        self.sliLock.setMaximum(120)
        self.sliLock.setValue(90)
        self.sliLock.setSingleStep(1)
        self.sliLock.move(self.locklock_pos[0], self.locklock_pos[1] + 20)
        self.sliLock.resize(self.locklock_pos[2], 25)
        self.sliLock.valueChanged.connect(self.change_lock)
        self.lblLockVal = QLabel('900°', self)
        self.lblLockVal.adjustSize()
        self.lblLockVal.move(
            self.locklock_pos[0] + self.locklock_pos[2] -
            self.lblLockVal.width(), self.locklock_pos[1])

        # bump_to_bump slider
        self.bumpbump_pos = [25, 500, 250, 0]
        self.lblBump = QLabel('Bump to Bump:', self)
        self.lblBump.move(self.bumpbump_pos[0], self.bumpbump_pos[1])
        self.sliBump = QSlider(Qt.Horizontal, self)
        self.sliBump.setTickPosition(QSlider.TicksAbove)
        self.sliBump.setTickInterval(10)
        self.sliBump.setMinimum(10)
        self.sliBump.setMaximum(120)
        self.sliBump.setValue(90)
        self.sliBump.setSingleStep(1)
        self.sliBump.move(self.bumpbump_pos[0], self.bumpbump_pos[1] + 20)
        self.sliBump.resize(self.bumpbump_pos[2], 25)
        self.sliBump.valueChanged.connect(self.change_bump)
        self.lblBumpVal = QLabel('900°', self)
        self.lblBumpVal.adjustSize()
        self.lblBumpVal.move(
            self.bumpbump_pos[0] + self.bumpbump_pos[2] -
            self.lblBumpVal.width(), self.bumpbump_pos[1])

        # WHEEL FORCE AND BEHAVIOR SETTINGS

        # game select combobox
        gameselect_pos = [325, 25, 250, 25]
        self.cbxGame = QComboBox(self)
        self.cbxGame.move(gameselect_pos[0], gameselect_pos[1])
        self.cbxGame.resize(gameselect_pos[2], gameselect_pos[3])
        for game in self.game_interfacer.games_available:
            self.cbxGame.addItem(game)
        self.cbxGame.activated.connect(self.select_game)

        # invert force checkbox
        invert_pos = [325, 55]
        self.cbInvert = QCheckBox('Invert Force Feedback', self)
        self.cbInvert.move(invert_pos[0], invert_pos[1])
        self.cbInvert.stateChanged.connect(self.toggle_invert)

        # motor pause mode checkbox
        motorpause_pos = [325, 85]
        self.cbMotorPause = QCheckBox('pause motor when game is paused', self)
        self.cbMotorPause.move(motorpause_pos[0], motorpause_pos[1])
        self.cbMotorPause.stateChanged.connect(self.toggle_motor_pause_mode)
        self.cbMotorPause.toggle()

        # maximum force slider
        self.max_force_pos = [325, 125, 250, 0]
        self.lblMaxForce = QLabel('Maximum Force in Nm:', self)
        self.lblMaxForce.move(self.max_force_pos[0], self.max_force_pos[1])
        self.sliMaxForce = QSlider(Qt.Horizontal, self)
        self.sliMaxForce.setTickPosition(QSlider.TicksAbove)
        self.sliMaxForce.setTickInterval(10)
        self.sliMaxForce.setMinimum(1)
        self.sliMaxForce.setMaximum(150)
        self.sliMaxForce.setValue(0)
        self.sliMaxForce.setSingleStep(1)
        self.sliMaxForce.move(self.max_force_pos[0],
                              self.max_force_pos[1] + 20)
        self.sliMaxForce.resize(self.max_force_pos[2], 25)
        self.sliMaxForce.valueChanged.connect(self.change_max_force)
        self.lblMaxForceVal = QLabel('0.0 Nm - (0.0 Amp)', self)
        self.lblMaxForceVal.adjustSize()
        self.lblMaxForceVal.move(
            self.max_force_pos[0] + self.max_force_pos[2] -
            self.lblMaxForceVal.width(), self.max_force_pos[1])

        # reconstruction checkbox
        reconst_pos = [325, 175 + 3]
        self.cbReconst = QCheckBox('Use Data Reconstruction', self)
        self.cbReconst.move(reconst_pos[0], reconst_pos[1])
        self.cbReconst.stateChanged.connect(self.toggle_reconstruction)
        self.cbReconst.setEnabled(False)

        # smoothing level combobox
        smoothing_pos = [475, 175, 100, 25]
        self.cbxSmoothing = QComboBox(self)
        self.cbxSmoothing.move(smoothing_pos[0], smoothing_pos[1])
        self.cbxSmoothing.resize(smoothing_pos[2], smoothing_pos[3])
        self.cbxSmoothing.addItem('no Smoothing')
        self.cbxSmoothing.addItem('1')
        self.cbxSmoothing.addItem('2')
        self.cbxSmoothing.addItem('3')
        self.cbxSmoothing.addItem('4')
        self.cbxSmoothing.addItem('5')
        self.cbxSmoothing.addItem('6')
        self.cbxSmoothing.addItem('7')
        self.cbxSmoothing.addItem('8')
        self.cbxSmoothing.addItem('9')
        self.cbxSmoothing.activated.connect(self.change_smoothing)
        self.cbxSmoothing.setEnabled(False)

        # friction slider
        self.friction_pos = [325, 215, 250, 0]
        self.lblFriction = QLabel('Friction:', self)
        self.lblFriction.move(self.friction_pos[0], self.friction_pos[1])
        self.sliFriction = QSlider(Qt.Horizontal, self)
        self.sliFriction.setTickPosition(QSlider.TicksAbove)
        self.sliFriction.setTickInterval(10)
        self.sliFriction.setMinimum(0)
        self.sliFriction.setMaximum(100)
        self.sliFriction.setValue(0)
        self.sliFriction.setSingleStep(1)
        self.sliFriction.move(self.friction_pos[0], self.friction_pos[1] + 20)
        self.sliFriction.resize(self.friction_pos[2], 25)
        self.sliFriction.valueChanged.connect(self.change_friction)
        self.lblFrictionVal = QLabel('0 %', self)
        self.lblFrictionVal.adjustSize()
        self.lblFrictionVal.move(
            self.friction_pos[0] + self.friction_pos[2] -
            self.lblFrictionVal.width(), self.friction_pos[1])

        # damping slider
        self.damping_pos = [325, 275, 250, 0]
        self.lblDamping = QLabel('Damping:', self)
        self.lblDamping.move(self.damping_pos[0], self.damping_pos[1])
        self.sliDamping = QSlider(Qt.Horizontal, self)
        self.sliDamping.setTickPosition(QSlider.TicksAbove)
        self.sliDamping.setTickInterval(10)
        self.sliDamping.setMinimum(0)
        self.sliDamping.setMaximum(100)
        self.sliDamping.setValue(0)
        self.sliDamping.setSingleStep(1)
        self.sliDamping.move(self.damping_pos[0], self.damping_pos[1] + 20)
        self.sliDamping.resize(self.damping_pos[2], 25)
        self.sliDamping.valueChanged.connect(self.change_damping)
        self.lblDampingVal = QLabel('0 %', self)
        self.lblDampingVal.adjustSize()
        self.lblDampingVal.move(
            self.damping_pos[0] + self.damping_pos[2] -
            self.lblDampingVal.width(), self.damping_pos[1])

        # inertia slider
        self.inertia_pos = [325, 335, 250, 0]
        self.lblInertia = QLabel('Inertia:', self)
        self.lblInertia.move(self.inertia_pos[0], self.inertia_pos[1])
        self.sliInertia = QSlider(Qt.Horizontal, self)
        self.sliInertia.setTickPosition(QSlider.TicksAbove)
        self.sliInertia.setTickInterval(10)
        self.sliInertia.setMinimum(0)
        self.sliInertia.setMaximum(100)
        self.sliInertia.setValue(0)
        self.sliInertia.setSingleStep(1)
        self.sliInertia.move(self.inertia_pos[0], self.inertia_pos[1] + 20)
        self.sliInertia.resize(self.inertia_pos[2], 25)
        self.sliInertia.valueChanged.connect(self.change_inertia)
        self.lblInertiaVal = QLabel('0 %', self)
        self.lblInertiaVal.adjustSize()
        self.lblInertiaVal.move(
            self.inertia_pos[0] + self.inertia_pos[2] -
            self.lblInertiaVal.width(), self.inertia_pos[1])

        # profile select combobox
        profileselect_pos = [325, 430, 250, 25]
        self.cbxProfiles = QComboBox(self)
        self.cbxProfiles.move(profileselect_pos[0], profileselect_pos[1])
        self.cbxProfiles.resize(profileselect_pos[2], profileselect_pos[3])
        for profile in self.profiles:
            self.cbxProfiles.addItem(profile.name)
        self.cbxProfiles.activated.connect(self.select_profile)

        # create profile button
        profilecreate_pos = [325, 460, 250, 25]
        self.btnCreate = QPushButton('create new profile', self)
        self.btnCreate.move(profilecreate_pos[0], profilecreate_pos[1])
        self.btnCreate.resize(profilecreate_pos[2], profilecreate_pos[3])
        self.btnCreate.clicked.connect(self.create_profile)

        # rename profile button
        profilerename_pos = [325, 490, 250, 25]
        self.btnRename = QPushButton('rename profile', self)
        self.btnRename.move(profilerename_pos[0], profilerename_pos[1])
        self.btnRename.resize(profilerename_pos[2], profilerename_pos[3])
        self.btnRename.clicked.connect(self.rename_profile)

        # cancel rename button
        cancelrename_pos = [325 + 200, 490, 50, 25]
        self.btnCancelRename = QPushButton('cancel', self)
        self.btnCancelRename.move(cancelrename_pos[0], cancelrename_pos[1])
        self.btnCancelRename.resize(cancelrename_pos[2], cancelrename_pos[3])
        self.btnCancelRename.clicked.connect(self.cancel_rename)
        self.btnCancelRename.setVisible(False)

        # rename textbox
        self.txtRename = QLineEdit(self)
        self.txtRename.move(profilerename_pos[0], profilerename_pos[1])
        self.txtRename.resize(profilerename_pos[2] - 35 - 55,
                              profilerename_pos[3])
        self.txtRename.setVisible(False)
        self.txtRename.textChanged.connect(self.check_name_validity)

        # save profile button
        profilesave_pos = [325, 520, 120, 25]
        self.btnSave = QPushButton('save profile', self)
        self.btnSave.move(profilesave_pos[0], profilesave_pos[1])
        self.btnSave.resize(profilesave_pos[2], profilesave_pos[3])
        self.btnSave.clicked.connect(self.save_current_profile_internally)

        # delete profile button
        profiledelete_pos = [325 + 130, 520, 120, 25]
        self.btnDelete = QPushButton('delete profile', self)
        self.btnDelete.move(profiledelete_pos[0], profiledelete_pos[1])
        self.btnDelete.resize(profiledelete_pos[2], profiledelete_pos[3])
        self.btnDelete.clicked.connect(self.delete_current_profile)

    # updates the GUI-elements that indicate the status of the motor (connected/not-connected)
    def LiveGuiTick(self):
        self.lblWheelPos.setText(
            str(int(self.wheel_position_deg_global.value * 10) / 10) + '°')

        self.lblCurrent.resize(
            int(
                np.abs(self.motor_current_global.value /
                       (self.actual_max_force_global.value * 2.75) * 128)), 25)
        if self.motor_current_global.value < 0.0:
            self.lblCurrent.move(
                25 + 128 -
                np.abs(self.motor_current_global.value /
                       (self.actual_max_force_global.value * 2.75) * 128), 25)

        tf = QTransform()
        tf.rotate(self.wheel_position_deg_global.value)

        if self.motor_connected_global.value:
            self.lblMotorStatus_2.setText('Connected')
            self.lblMotorStatus_2.setStyleSheet(
                'QLabel { color: rgb(0,155,0); }')
            img_rot = self.wheel_image.transformed(tf)
            self.btnCenter.setEnabled(True)
            self.lblWheelPos.setStyleSheet('QLabel { color: rgb(0,0,0); }')
        else:
            self.lblMotorStatus_2.setText('Not Connected')
            self.lblMotorStatus_2.setStyleSheet(
                'QLabel { color: rgb(155,0,0); }')
            img_rot = self.wheel_image_discon.transformed(tf)
            self.btnCenter.setEnabled(False)
            self.lblWheelPos.setStyleSheet(
                'QLabel { color: rgb(155,155,155); }')

        diagonal_overlength = (np.sqrt(np.square(256) * 2) - 256) / 2
        shift = int(
            np.abs(
                np.sin(np.deg2rad(self.wheel_position_deg_global.value * 2)) *
                diagonal_overlength))
        crop_rect = QRect(shift, shift, 256, 256)
        self.wheel_pixmap = QPixmap.fromImage(img_rot).copy(crop_rect)
        self.lblWheelImage.setPixmap(self.wheel_pixmap)

        if self.motor_controller_due_for_restart_global.value:
            self.motor_controller_due_for_restart_global.value = False
            print('restarting motor...')
            try:
                self.motor_controller.motor_control_process.terminate()
            except:
                pass
            self.motor_controller.start()

    # helper function to get the index of a profile with a certain name from the profile-list
    def get_profile_index(self, name):
        for i in range(len(self.profiles)):
            if self.profiles[i].name == name:
                return i

    # WHEEL POSITION SETTING FUNCTIONS
    def center_wheel(self):
        print('centering wheel')
        self.motor_controller.set_encoder_offset()

    def change_lock(self):
        val = int(self.sender().value() * 10)
        self.lblLockVal.setText(str(val) + '°')
        self.lock_to_lock_global.value = val
        self.lblLockVal.adjustSize()
        self.lblLockVal.move(
            self.locklock_pos[0] + self.locklock_pos[2] -
            self.lblLockVal.width(), self.locklock_pos[1])

    def change_bump(self):
        val = int(self.sender().value() * 10)
        self.lblBumpVal.setText(str(val) + '°')
        self.bump_to_bump_global.value = val
        self.lblBumpVal.adjustSize()
        self.lblBumpVal.move(
            self.bumpbump_pos[0] + self.bumpbump_pos[2] -
            self.lblBumpVal.width(), self.bumpbump_pos[1])

    # WHEEL FORCE SETTING FUNCTIONS
    def select_game(self, item_index):
        print('selecting', item_index)
        self.game_interfacer.terminate()
        time.sleep(1)
        self.game_interfacer.start(item_index)

    def toggle_invert(self, state):
        if state == Qt.Checked:
            self.invert_force_global.value = True
        else:
            self.invert_force_global.value = False

    def toggle_motor_pause_mode(self, state):
        if state == Qt.Checked:
            self.motor_pause_mode.value = True
        else:
            self.motor_pause_mode.value = False

    def change_max_force(self):
        val = self.sender().value() / 10
        self.lblMaxForceVal.setText(
            str(val) + ' Nm - (' + str(int(val * 2.75 * 100) / 100) + ' Amp)')
        self.actual_max_force_global.value = val
        self.lblMaxForceVal.adjustSize()
        self.lblMaxForceVal.move(
            self.max_force_pos[0] + self.max_force_pos[2] -
            self.lblMaxForceVal.width(), self.max_force_pos[1])
        self.force_graph.setYRange(-val, val)

    def change_friction(self):
        val = self.sender().value() / 100
        self.lblFrictionVal.setText(str(int(val * 100)) + ' %')
        self.friction_global.value = val
        self.lblFrictionVal.adjustSize()
        self.lblFrictionVal.move(
            self.friction_pos[0] + self.friction_pos[2] -
            self.lblFrictionVal.width(), self.friction_pos[1])

    def change_damping(self):
        val = self.sender().value() / 100
        self.lblDampingVal.setText(str(int(val * 100)) + ' %')
        self.damping_global.value = val
        self.lblDampingVal.adjustSize()
        self.lblDampingVal.move(
            self.damping_pos[0] + self.damping_pos[2] -
            self.lblDampingVal.width(), self.damping_pos[1])

    def change_inertia(self):
        val = self.sender().value() / 100
        self.lblInertiaVal.setText(str(int(val * 100)) + ' %')
        self.inertia_global.value = val
        self.lblInertiaVal.adjustSize()
        self.lblInertiaVal.move(
            self.inertia_pos[0] + self.inertia_pos[2] -
            self.lblInertiaVal.width(), self.inertia_pos[1])

    def toggle_reconstruction(self, state):
        if state == Qt.Checked:
            self.data_reconstruction.value = True
        else:
            self.data_reconstruction.value = False

    def change_smoothing(self, item_index):
        self.data_smoothing_level.value = item_index

    def select_profile(self, selected_profile):
        self.sliLock.setValue(
            int(self.profiles[selected_profile].lock_to_lock / 10))
        self.sliBump.setValue(
            int(self.profiles[selected_profile].bump_to_bump / 10))
        self.cbInvert.setChecked(
            bool(self.profiles[selected_profile].invert_force))
        self.sliMaxForce.setValue(
            int(self.profiles[selected_profile].max_force * 10))
        self.cbReconst.setChecked(
            bool(self.profiles[selected_profile].use_reconstruction))
        self.cbxSmoothing.setCurrentIndex(
            int(self.profiles[selected_profile].smoothing_level))
        self.sliFriction.setValue(
            int(self.profiles[selected_profile].friction * 100))
        self.sliDamping.setValue(
            int(self.profiles[selected_profile].damping * 100))
        self.sliInertia.setValue(
            int(self.profiles[selected_profile].inertia * 100))

    def save_current_profile_internally(self):
        current_index = self.cbxProfiles.currentIndex()
        self.profiles[
            current_index].lock_to_lock = self.lock_to_lock_global.value
        self.profiles[
            current_index].bump_to_bump = self.bump_to_bump_global.value
        self.profiles[
            current_index].invert_force = self.invert_force_global.value
        self.profiles[
            current_index].max_force = self.actual_max_force_global.value
        self.profiles[
            current_index].use_reconstruction = self.data_reconstruction.value
        self.profiles[
            current_index].smoothing_level = self.data_smoothing_level.value
        self.profiles[current_index].friction = self.friction_global.value
        self.profiles[current_index].damping = self.damping_global.value
        self.profiles[current_index].inertia = self.inertia_global.value
        self.save_profiles_to_file()

    def save_profiles_to_file(self):
        root = ET.Element('profiles')
        for profile in self.profiles:
            prof_elem = ET.SubElement(root, 'profile', name=profile.name)

            ET.SubElement(prof_elem,
                          'lock_to_lock').text = str(profile.lock_to_lock)
            ET.SubElement(prof_elem,
                          'bump_to_bump').text = str(profile.bump_to_bump)

            ET.SubElement(prof_elem, 'invert_force').text = str(
                bool(profile.invert_force))

            ET.SubElement(prof_elem, 'max_force').text = str(profile.max_force)

            ET.SubElement(prof_elem, 'use_reconstruction').text = str(
                bool(profile.use_reconstruction))
            ET.SubElement(prof_elem, 'smoothing_level').text = str(
                profile.smoothing_level)

            ET.SubElement(prof_elem, 'friction').text = str(profile.friction)
            ET.SubElement(prof_elem, 'damping').text = str(profile.damping)
            ET.SubElement(prof_elem, 'inertia').text = str(profile.inertia)

        tree = ET.ElementTree(root)
        tree.write("profiles.xml")

    def load_profiles_from_file(self):
        self.profiles.clear()
        tree = ET.parse('profiles.xml')
        root = tree.getroot()
        for prof in root:
            profile = Profile(prof.attrib['name'])
            profile.lock_to_lock = float(prof[0].text)
            profile.bump_to_bump = float(prof[1].text)
            profile.invert_force = bool(prof[2].text == 'True')
            profile.max_force = float(prof[3].text)
            profile.use_reconstruction = bool(prof[4].text == 'True')
            profile.smoothing_level = int(prof[5].text)
            profile.friction = float(prof[6].text)
            profile.damping = float(prof[7].text)
            profile.inertia = float(prof[8].text)
            self.profiles.append(profile)

    def delete_current_profile(self):
        current_index = self.cbxProfiles.currentIndex()
        print('deleting profile at index:', current_index)
        self.profiles.pop(current_index)
        self.cbxProfiles.clear()
        for profile in self.profiles:
            self.cbxProfiles.addItem(profile.name)
        self.cbxProfiles.setCurrentIndex(0)
        self.select_profile(0)
        self.save_current_profile_internally()
        if len(self.profiles) == 1:
            self.btnDelete.setEnabled(False)

    def create_profile(self):
        new_profile = Profile('profile #' + str(len(self.profiles) + 1))
        current_index = self.cbxProfiles.currentIndex()

        new_profile.lock_to_lock = self.profiles[current_index].lock_to_lock
        new_profile.bump_to_bump = self.profiles[current_index].bump_to_bump
        new_profile.invert_force = self.profiles[current_index].invert_force
        new_profile.max_force = self.profiles[current_index].max_force
        new_profile.use_reconstruction = self.profiles[
            current_index].use_reconstruction
        new_profile.smoothing_level = self.profiles[
            current_index].smoothing_level
        new_profile.friction = self.profiles[current_index].friction
        new_profile.damping = self.profiles[current_index].damping
        new_profile.inertia = self.profiles[current_index].inertia
        self.profiles.append(new_profile)

        self.cbxProfiles.clear()
        for profile in self.profiles:
            self.cbxProfiles.addItem(profile.name)
        self.cbxProfiles.setCurrentIndex(len(self.profiles) - 1)
        self.select_profile(len(self.profiles) - 1)
        self.save_current_profile_internally()
        if len(self.profiles) > 1:
            self.btnDelete.setEnabled(True)

    def rename_profile(self):
        rename_pos = [325, 490, 250, 25]
        if self.sender().text() == 'rename profile':
            self.sender().setText('OK')
            self.sender().move(rename_pos[0] + 220 - 55, rename_pos[1])
            self.sender().resize(rename_pos[2] - 220, rename_pos[3])
            self.cbxProfiles.setEnabled(False)
            self.btnCreate.setEnabled(False)
            self.btnSave.setEnabled(False)
            self.btnDelete.setEnabled(False)
            self.btnCancelRename.setVisible(True)
            self.txtRename.setVisible(True)
            current_index = self.cbxProfiles.currentIndex()
            self.txtRename.setText(self.profiles[current_index].name)
        else:
            self.sender().setText('rename profile')
            self.sender().move(rename_pos[0], rename_pos[1])
            self.sender().resize(rename_pos[2], rename_pos[3])
            self.cbxProfiles.setEnabled(True)
            self.btnCreate.setEnabled(True)
            self.btnSave.setEnabled(True)
            self.btnDelete.setEnabled(True)
            self.btnCancelRename.setVisible(False)
            self.txtRename.setVisible(False)
            current_index = self.cbxProfiles.currentIndex()
            self.profiles[current_index].name = self.txtRename.text()

            self.cbxProfiles.clear()
            for profile in self.profiles:
                self.cbxProfiles.addItem(profile.name)
            self.cbxProfiles.setCurrentIndex(current_index)
            self.select_profile(current_index)
            self.save_current_profile_internally()

    def cancel_rename(self):
        rename_pos = [325, 490, 250, 25]
        self.btnRename.setText('rename profile')
        self.btnRename.move(rename_pos[0], rename_pos[1])
        self.btnRename.resize(rename_pos[2], rename_pos[3])
        self.cbxProfiles.setEnabled(True)
        self.btnCreate.setEnabled(True)
        self.btnSave.setEnabled(True)
        self.btnDelete.setEnabled(True)
        self.btnCancelRename.setVisible(False)
        self.txtRename.setVisible(False)

    def check_name_validity(self, text):
        if text == '':
            self.btnRename.setEnabled(False)
        else:
            self.btnRename.setEnabled(True)
Exemple #19
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)
Exemple #20
0
    def __init__(self):
        super(MainWindow, self).__init__()
        self.resize(1080, 600)
        self.setMinimumSize(QSize(1080, 600))
        self.setMaximumSize(QSize(1366, 745))
        self.setWindowTitle("GPCO - General Power Converter Optimizer")

        main_widget = QWidget()
        self.component_selection_buttons = {}

        main_layout = QHBoxLayout()
        main_splitter = QSplitter(Qt.Horizontal, self)
        left_frame = QFrame(main_splitter)
        left_frame.setFrameShape(QFrame.Box)
        left_frame.setMaximumWidth(250)
        left_frame.setMinimumWidth(220)
        right_frame = QFrame(main_splitter)
        right_frame.setFrameShape(QFrame.Box)
        main_splitter.addWidget(left_frame)
        main_splitter.addWidget(right_frame)

        converter_config_layout = QVBoxLayout()

        visualize_information_layout = QVBoxLayout()
        right_splitter = QSplitter(Qt.Vertical)
        visualize_information_layout.addWidget(right_splitter)
        top_right_frame = QFrame(right_splitter)
        bottom_right_frame = QFrame(right_splitter)
        right_splitter.addWidget(top_right_frame)
        right_splitter.addWidget(bottom_right_frame)

        top_right_layout = QHBoxLayout()
        self.converter_result_edit = QTextBrowser()
        self.optimizer_graph = PlotWidget()
        self.optimizer_graph.setBackground('w')
        aux_frame = QFrame()
        aux_frame.setMaximumWidth(450)
        aux_layout = QHBoxLayout()
        aux_layout.addWidget(self.optimizer_graph)
        aux_frame.setLayout(aux_layout)
        top_right_layout.addWidget(self.converter_result_edit)
        top_right_layout.addWidget(aux_frame)

        bottom_right_layout = QHBoxLayout()
        analysis_graph_1 = QTextBrowser()
        analysis_graph_2 = PlotWidget()
        analysis_graph_2.setBackground('w')
        aux_frame2 = QFrame()
        aux_frame2.setMaximumWidth(450)
        aux_layout2 = QHBoxLayout()
        aux_layout2.addWidget(analysis_graph_2)
        aux_frame2.setLayout(aux_layout2)
        bottom_right_layout.addWidget(analysis_graph_1)
        bottom_right_layout.addWidget(aux_frame2)

        top_right_frame.setLayout(top_right_layout)
        bottom_right_frame.setLayout(bottom_right_layout)

        # Adiciona tudo que vai no Layout do Conversor
        configuration_label = QLabel(
            "<html><head/><body><p><span style=\" font-size:12pt;\">Configuração do Conversor</span></p></body></html>"
        )
        configuration_label.setSizePolicy(QSizePolicy.Expanding,
                                          QSizePolicy.Minimum)
        configuration_label.setAlignment(Qt.AlignCenter)
        converter_config_layout.addWidget(configuration_label)
        topology_label = QLabel(
            "<html><head/><body><p><span style=\" font-size:10pt;\">Topologia</span></p></body></html>"
        )
        topology_label.setSizePolicy(QSizePolicy.Expanding,
                                     QSizePolicy.Minimum)
        topology_label.setAlignment(Qt.AlignCenter)
        converter_config_layout.addItem(
            QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Minimum))
        converter_config_layout.addWidget(topology_label)
        converter_config_layout.addItem(
            QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Minimum))
        converter_selector = QComboBox()
        converter_selector.setSizePolicy(QSizePolicy.Fixed,
                                         QSizePolicy.Minimum)
        converter_selector.addItem("Boost Half Bridge")
        converter_config_layout.addLayout(CenteredWidget(converter_selector))
        parameters_label = QLabel(
            "<html><head/><body><p><span style=\" font-size:10pt;\">Parâmetros de Projeto</span></p></body></html>"
        )
        parameters_label.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Minimum)
        parameters_label.setAlignment(Qt.AlignCenter)
        converter_config_layout.addItem(
            QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Fixed))
        converter_config_layout.addWidget(parameters_label)
        converter_config_layout.addItem(
            QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Fixed))

        self.design_features_inputs = {
            'Vi': LabeledInput('Tensão de Entrada (V)'),
            'Vo': LabeledInput('Tensão de Saída (V)'),
            'Po': LabeledInput('Potência de Saída (W)'),
            'dIin_max': LabeledInput('DeltaIinMax (%)'),
            'dVo_max': LabeledInput('DeltaVoMax (%)'),
        }
        for key in self.design_features_inputs:
            converter_config_layout.addLayout(self.design_features_inputs[key])

        converter_config_layout.addItem(
            QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Fixed))
        select_components_label = QLabel(
            "<html><head/><body><p><span style=\" font-size:10pt;\">Selecione os Componentes</span></p></body></html>"
        )
        select_components_label.setSizePolicy(QSizePolicy.Expanding,
                                              QSizePolicy.Minimum)
        select_components_label.setAlignment(Qt.AlignCenter)
        converter_config_layout.addWidget(select_components_label)

        self.select_components_tab = QTabWidget()
        complete_optimization_components_tab = QFrame()
        continuous_optimization_components_tab = QFrame()
        complete_optimization_components_tab.setSizePolicy(
            QSizePolicy.Minimum, QSizePolicy.Expanding)
        continuous_optimization_components_tab.setSizePolicy(
            QSizePolicy.Minimum, QSizePolicy.Expanding)

        continuous_optimization_components_layout = QVBoxLayout()
        complete_optimization_components_layout = QVBoxLayout()

        self.complete_component_selection_buttons = {}
        self.continuous_component_selection_buttons = {}

        for component in COMPLETE:
            self.complete_component_selection_buttons[component] = QPushButton(
                component)
        for component in CONTINUOUS:
            self.continuous_component_selection_buttons[
                component] = QPushButton(component)

        complete_optimization_components_layout.addLayout(
            SpacedWidget(
                [self.complete_component_selection_buttons['Capacitors']]))
        complete_optimization_components_layout.addLayout(
            SpacedWidget([
                self.complete_component_selection_buttons['Diodes'],
                self.complete_component_selection_buttons['Switches']
            ]))
        complete_optimization_components_layout.addLayout(
            SpacedWidget([
                self.complete_component_selection_buttons['Cores'],
                self.complete_component_selection_buttons['Cables']
            ]))
        complete_optimization_components_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding))
        complete_optimization_components_tab.setLayout(
            complete_optimization_components_layout)

        continuous_optimization_components_layout.addLayout(
            SpacedWidget([
                self.continuous_component_selection_buttons['C1'],
                self.continuous_component_selection_buttons['C2']
            ]))
        continuous_optimization_components_layout.addLayout(
            SpacedWidget([
                self.continuous_component_selection_buttons['C3'],
                self.continuous_component_selection_buttons['C4']
            ]))
        continuous_optimization_components_layout.addLayout(
            SpacedWidget([
                self.continuous_component_selection_buttons['S1'],
                self.continuous_component_selection_buttons['S2']
            ]))
        continuous_optimization_components_layout.addLayout(
            SpacedWidget([
                self.continuous_component_selection_buttons['D3'],
                self.continuous_component_selection_buttons['D4']
            ]))
        continuous_optimization_components_layout.addLayout(
            SpacedWidget([
                self.continuous_component_selection_buttons['Li'],
                self.continuous_component_selection_buttons['Lk']
            ]))
        continuous_optimization_components_layout.addLayout(
            SpacedWidget([self.continuous_component_selection_buttons['Tr']]))
        continuous_optimization_components_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding))
        continuous_optimization_components_tab.setLayout(
            continuous_optimization_components_layout)

        self.select_components_tab.addTab(complete_optimization_components_tab,
                                          "Completa")
        self.select_components_tab.addTab(
            continuous_optimization_components_tab, "Contínua")
        converter_config_layout.addWidget(self.select_components_tab)

        left_frame.setLayout(converter_config_layout)
        right_frame.setLayout(visualize_information_layout)
        main_layout.addWidget(main_splitter)

        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

        # Create all action menus.
        self.menu_bar = QMenuBar(self)
        self.file_menu = QMenu(self.menu_bar)
        self.run_menu = QMenu(self.menu_bar)
        self.components_menu = QMenu(self.menu_bar)
        self.add_component_menu = QMenu(self.components_menu)
        self.settings_menu = QMenu(self.menu_bar)
        self.help_menu = QMenu(self.menu_bar)
        self.setMenuBar(self.menu_bar)
        self.status_bar = QStatusBar(self)
        self.setStatusBar(self.status_bar)
        self.optimization_progress_bar = QProgressBar(self)
        self.optimization_progress_bar.setMaximumWidth(250)
        self.status_bar_text_edit = QLabel("")
        self.status_bar.addPermanentWidget(self.optimization_progress_bar, 1)
        self.status_bar.addPermanentWidget(self.status_bar_text_edit, 1)

        self.actionNew = QAction(self)
        self.actionNew.setIcon(QIcon("GUI/Icons/document--add.svg"))
        self.actionOpen = QAction(self)
        self.actionOpen.setIcon(QIcon("GUI/Icons/folder.svg"))
        self.actionSave = QAction(self)
        self.actionSave.setIcon(QIcon("GUI/Icons/save.svg"))
        self.actionSaveAs = QAction(self)
        self.actionSaveAs.setIcon(QIcon("GUI/Icons/save.svg"))
        self.actionSwitch = QAction(self)
        self.actionDiode = QAction(self)
        self.actionCapacitor = QAction(self)
        self.actionCable = QAction(self)
        self.actionCore = QAction(self)
        self.actionConfigOptimizer = QAction(self)
        self.actionConfigSecurity = QAction(self)
        self.actionTransformer = QAction(self)
        self.actionInductor = QAction(self)
        self.actionHowItWorks = QAction(self)
        self.actionHowToUse = QAction(self)
        self.actionLoadFile = QAction(self)
        self.action_run_optimizer = QAction(self)
        self.action_run_optimizer.setIcon(
            QIcon("GUI/Icons/play--filled--alt.svg"))
        self.action_stop_optimizer = QAction(self)
        self.action_stop_optimizer.setIcon(
            QIcon("GUI/Icons/stop--filled--alt.svg"))
        self.actionComponents = QAction(self)
        self.file_menu.addAction(self.actionNew)
        self.file_menu.addAction(self.actionOpen)
        self.file_menu.addAction(self.actionSave)
        self.file_menu.addAction(self.actionSaveAs)
        self.add_component_menu.addAction(self.actionSwitch)
        self.add_component_menu.addAction(self.actionDiode)
        self.add_component_menu.addAction(self.actionCapacitor)
        self.add_component_menu.addAction(self.actionCable)
        self.add_component_menu.addAction(self.actionCore)
        self.add_component_menu.addAction(self.actionTransformer)
        self.add_component_menu.addAction(self.actionInductor)
        self.run_menu.addAction(self.action_run_optimizer)
        self.run_menu.addAction(self.action_stop_optimizer)
        self.components_menu.addAction(self.add_component_menu.menuAction())
        self.components_menu.addAction(self.actionLoadFile)
        self.settings_menu.addAction(self.actionConfigOptimizer)
        self.settings_menu.addAction(self.actionConfigSecurity)
        self.help_menu.addAction(self.actionHowItWorks)
        self.help_menu.addAction(self.actionHowToUse)
        self.menu_bar.addAction(self.file_menu.menuAction())
        self.menu_bar.addAction(self.run_menu.menuAction())
        self.menu_bar.addAction(self.components_menu.menuAction())
        self.menu_bar.addAction(self.settings_menu.menuAction())
        self.menu_bar.addAction(self.help_menu.menuAction())

        _translate = QCoreApplication.translate
        self.file_menu.setTitle(_translate("MainWindow", "Arquivo"))
        self.components_menu.setTitle(_translate("MainWindow", "Biblioteca"))
        self.help_menu.setTitle(_translate("MainWindow", "Ajuda"))
        self.settings_menu.setTitle(_translate("MainWindow", "Configurações"))
        self.run_menu.setTitle(_translate("MainWindow", "Rodar"))
        self.add_component_menu.setTitle(
            _translate("MainWindow", "Adicionar Componente"))
        self.actionNew.setText(_translate("MainWindow", "Novo Arquivo"))
        self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N"))
        self.actionOpen.setText(_translate("MainWindow", "Carregar Arquivo"))
        self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
        self.actionSave.setText(_translate("MainWindow", "Salvar"))
        self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
        self.actionSaveAs.setText(_translate("MainWindow", "Salvar Como"))
        self.actionSaveAs.setShortcut(_translate("MainWindow", "Ctrl+Shift+S"))
        self.actionSwitch.setText(_translate("MainWindow", "Chave"))
        self.actionDiode.setText(_translate("MainWindow", "Diodo"))
        self.actionCapacitor.setText(_translate("MainWindow", "Capacitor"))
        self.actionCable.setText(_translate("MainWindow", "Fio"))
        self.actionCore.setText(_translate("MainWindow", "Núcleo Magnético"))
        self.actionConfigOptimizer.setText(
            _translate("MainWindow", "Otimizador"))
        self.actionConfigSecurity.setText(
            _translate("MainWindow", "Fatores de Segurança"))
        self.actionTransformer.setText(
            _translate("MainWindow", "Transformador"))
        self.actionInductor.setText(_translate("MainWindow", "Indutor"))
        self.actionHowItWorks.setText(
            _translate("MainWindow", "Como funciona o otimizador?"))
        self.actionHowToUse.setText(
            _translate("MainWindow", "Como utilizar o otimizador?"))
        self.actionLoadFile.setText(
            _translate("MainWindow", "Carregar Arquivo"))
        self.actionComponents.setText(_translate("MainWindow", "Componentes"))
        self.action_run_optimizer.setText(
            _translate("MainWindow", "Rodar Otimizador"))
        self.action_run_optimizer.setShortcut(_translate("MainWindow", "F5"))
        self.action_stop_optimizer.setText(
            _translate("MainWindow", "Parar Otimizador"))
        self.action_stop_optimizer.setShortcut(_translate("MainWindow", "F9"))

        # Execution Toolbar
        execution_toolbar = QToolBar("Run", self)
        execution_toolbar.addAction(self.actionNew)
        execution_toolbar.addAction(self.actionSave)
        execution_toolbar.addAction(self.actionOpen)
        execution_toolbar.addAction(self.action_run_optimizer)
        execution_toolbar.addAction(self.action_stop_optimizer)
        execution_toolbar.setFixedHeight(36)
        execution_toolbar.setIconSize(QSize(12, 12))
        self.addToolBar(execution_toolbar)
Exemple #21
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(882, 605)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.labelHKLS = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelHKLS.setFont(font)
        self.labelHKLS.setObjectName("labelHKLS")
        self.gridLayout.addWidget(self.labelHKLS, 13, 0, 1, 4)
        self.label_19 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_19.setFont(font)
        self.label_19.setObjectName("label_19")
        self.gridLayout.addWidget(self.label_19, 15, 6, 1, 1)
        self.labelSimpara = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelSimpara.setFont(font)
        self.labelSimpara.setObjectName("labelSimpara")
        self.gridLayout.addWidget(self.labelSimpara, 0, 0, 1, 2)
        self.labelHKLS_2 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelHKLS_2.setFont(font)
        self.labelHKLS_2.setObjectName("labelHKLS_2")
        self.gridLayout.addWidget(self.labelHKLS_2, 13, 4, 1, 3)
        self.label_17 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_17.setFont(font)
        self.label_17.setObjectName("label_17")
        self.gridLayout.addWidget(self.label_17, 14, 4, 1, 1)
        self.idealLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.idealLueftenInput.setFont(font)
        self.idealLueftenInput.setObjectName("idealLueftenInput")
        self.gridLayout.addWidget(self.idealLueftenInput, 14, 1, 1, 2)
        self.textEditCalcInfo = QtWidgets.QTextEdit(self.centralwidget)
        self.textEditCalcInfo.setMaximumSize(QtCore.QSize(16777215, 61))
        self.textEditCalcInfo.setObjectName("textEditCalcInfo")
        self.gridLayout.addWidget(self.textEditCalcInfo, 21, 0, 1, 7)
        self.CustomLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.CustomLueftenInput.setFont(font)
        self.CustomLueftenInput.setObjectName("CustomLueftenInput")
        self.gridLayout.addWidget(self.CustomLueftenInput, 14, 5, 1, 1)
        self.CustomInnereLastenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.CustomInnereLastenInput.setFont(font)
        self.CustomInnereLastenInput.setObjectName("CustomInnereLastenInput")
        self.gridLayout.addWidget(self.CustomInnereLastenInput, 16, 5, 1, 1)
        self.NatLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.NatLueftenInput.setFont(font)
        self.NatLueftenInput.setObjectName("NatLueftenInput")
        self.gridLayout.addWidget(self.NatLueftenInput, 18, 1, 1, 2)
        self.label_20 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_20.setFont(font)
        self.label_20.setObjectName("label_20")
        self.gridLayout.addWidget(self.label_20, 15, 4, 1, 1)
        self.NachtlueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.NachtlueftenInput.setFont(font)
        self.NachtlueftenInput.setObjectName("NachtlueftenInput")
        self.gridLayout.addWidget(self.NachtlueftenInput, 15, 1, 1, 2)
        self.TaglueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.TaglueftenInput.setFont(font)
        self.TaglueftenInput.setObjectName("TaglueftenInput")
        self.gridLayout.addWidget(self.TaglueftenInput, 16, 1, 1, 2)
        self.label_14 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_14.setFont(font)
        self.label_14.setObjectName("label_14")
        self.gridLayout.addWidget(self.label_14, 19, 3, 1, 1)
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.gridLayout.addWidget(self.label_4, 14, 3, 1, 1)
        self.label_23 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_23.setFont(font)
        self.label_23.setObjectName("label_23")
        self.gridLayout.addWidget(self.label_23, 16, 4, 1, 1)
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setMaximumSize(QtCore.QSize(14, 22))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 1, 2, 1, 1)
        self.label_8 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_8.setFont(font)
        self.label_8.setObjectName("label_8")
        self.gridLayout.addWidget(self.label_8, 17, 0, 1, 1)
        self.label_12 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_12.setFont(font)
        self.label_12.setObjectName("label_12")
        self.gridLayout.addWidget(self.label_12, 18, 0, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setMinimumSize(QtCore.QSize(121, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.gridLayout.addWidget(self.label_3, 14, 0, 1, 1)
        self.label_18 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_18.setFont(font)
        self.label_18.setObjectName("label_18")
        self.gridLayout.addWidget(self.label_18, 14, 6, 1, 1)
        self.SonnenschutzInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.SonnenschutzInput.setFont(font)
        self.SonnenschutzInput.setObjectName("SonnenschutzInput")
        self.gridLayout.addWidget(self.SonnenschutzInput, 17, 1, 1, 2)
        self.startTempInput = QtWidgets.QLineEdit(self.centralwidget)
        self.startTempInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.startTempInput.setFont(font)
        self.startTempInput.setObjectName("startTempInput")
        self.gridLayout.addWidget(self.startTempInput, 3, 1, 1, 1)
        self.MechLueftenInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.MechLueftenInput.setFont(font)
        self.MechLueftenInput.setObjectName("MechLueftenInput")
        self.gridLayout.addWidget(self.MechLueftenInput, 19, 1, 1, 2)
        self.startSimulation = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.startSimulation.setFont(font)
        self.startSimulation.setObjectName("startSimulation")
        self.gridLayout.addWidget(self.startSimulation, 20, 4, 1, 2)
        self.label_16 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_16.setFont(font)
        self.label_16.setObjectName("label_16")
        self.gridLayout.addWidget(self.label_16, 16, 0, 1, 1)
        self.label_11 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_11.setFont(font)
        self.label_11.setObjectName("label_11")
        self.gridLayout.addWidget(self.label_11, 18, 3, 1, 1)
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.gridLayout.addWidget(self.label_6, 15, 0, 1, 1)
        self.CustomSonnenschutzInput = QtWidgets.QLineEdit(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.CustomSonnenschutzInput.setFont(font)
        self.CustomSonnenschutzInput.setObjectName("CustomSonnenschutzInput")
        self.gridLayout.addWidget(self.CustomSonnenschutzInput, 15, 5, 1, 1)
        self.label_13 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_13.setFont(font)
        self.label_13.setObjectName("label_13")
        self.gridLayout.addWidget(self.label_13, 19, 0, 1, 1)
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setMinimumSize(QtCore.QSize(0, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.progressBar.setFont(font)
        self.progressBar.setProperty("value", 24)
        self.progressBar.setObjectName("progressBar")
        self.gridLayout.addWidget(self.progressBar, 20, 0, 1, 4)
        self.label_10 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_10.setFont(font)
        self.label_10.setObjectName("label_10")
        self.gridLayout.addWidget(self.label_10, 11, 0, 1, 1)
        self.label_15 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_15.setFont(font)
        self.label_15.setObjectName("label_15")
        self.gridLayout.addWidget(self.label_15, 16, 3, 1, 1)
        self.labelStandort = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.labelStandort.setFont(font)
        self.labelStandort.setObjectName("labelStandort")
        self.gridLayout.addWidget(self.labelStandort, 10, 0, 1, 2)
        self.label_24 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_24.setFont(font)
        self.label_24.setObjectName("label_24")
        self.gridLayout.addWidget(self.label_24, 16, 6, 1, 1)
        self.zeitschrittInput = QtWidgets.QLineEdit(self.centralwidget)
        self.zeitschrittInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.zeitschrittInput.setFont(font)
        self.zeitschrittInput.setObjectName("zeitschrittInput")
        self.gridLayout.addWidget(self.zeitschrittInput, 1, 1, 1, 1)
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.gridLayout.addWidget(self.label_5, 15, 3, 1, 1)
        self.label_21 = QtWidgets.QLabel(self.centralwidget)
        self.label_21.setText("")
        self.label_21.setObjectName("label_21")
        self.gridLayout.addWidget(self.label_21, 6, 1, 1, 1)
        self.label_7 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.gridLayout.addWidget(self.label_7, 17, 3, 1, 1)
        self.stopSimulation = QtWidgets.QPushButton(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.stopSimulation.setFont(font)
        self.stopSimulation.setObjectName("stopSimulation")
        self.gridLayout.addWidget(self.stopSimulation, 20, 6, 1, 1)
        self.label_22 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_22.setFont(font)
        self.label_22.setObjectName("label_22")
        self.gridLayout.addWidget(self.label_22, 2, 0, 1, 1)
        self.genauigkeitInput = QtWidgets.QLineEdit(self.centralwidget)
        self.genauigkeitInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.genauigkeitInput.setFont(font)
        self.genauigkeitInput.setObjectName("genauigkeitInput")
        self.gridLayout.addWidget(self.genauigkeitInput, 2, 1, 1, 1)
        self.label_26 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_26.setFont(font)
        self.label_26.setObjectName("label_26")
        self.gridLayout.addWidget(self.label_26, 3, 0, 1, 1)
        self.label_25 = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_25.setFont(font)
        self.label_25.setObjectName("label_25")
        self.gridLayout.addWidget(self.label_25, 3, 2, 1, 1)
        self.label_9 = QtWidgets.QLabel(self.centralwidget)
        self.label_9.setMaximumSize(QtCore.QSize(14, 22))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.gridLayout.addWidget(self.label_9, 11, 2, 1, 1)
        self.SeehoeheInput = QtWidgets.QLineEdit(self.centralwidget)
        self.SeehoeheInput.setMaximumSize(QtCore.QSize(100, 16777215))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.SeehoeheInput.setFont(font)
        self.SeehoeheInput.setObjectName("SeehoeheInput")
        self.gridLayout.addWidget(self.SeehoeheInput, 11, 1, 1, 1)
        self.graphWidget = PlotWidget(self.centralwidget)
        self.graphWidget.setMinimumSize(QtCore.QSize(0, 0))
        self.graphWidget.setObjectName("graphWidget")
        self.gridLayout.addWidget(self.graphWidget, 1, 3, 11, 4)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
# to here

        '-------------------Multithreading------------------------'
        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())

        '-------------------Events--------------------------------'
        #Hier werden alle Events von Buttons verwaltet
        self.startSimulation.clicked.connect(self.Simulation)
        self.stopSimulation.clicked.connect(self.Stop)

        self.x = list(range(96))  # initializing plot x axis
        self.y = [float(self.startTempInput.text())] * 96  # initializing plot y axis

        self.graphWidget.setBackground('w')

        pen = pg.mkPen(color=(51, 51, 255))
        self.data_line =  self.graphWidget.plot(self.x, self.y, pen=pen)
        self.graphWidget.getPlotItem().hideAxis('bottom')
        self.timer = QtCore.QTimer()
        self.timer.setInterval(200)
        self.timer.timeout.connect(self.update_plot_data)
        self.timer.start()
        self.line = 0
        self.progress = 0
        self.progressLimit = 100

    def update_plot_data(self):
        abbruchTxt = open('Abbruch.txt', 'r')
        if abbruchTxt.read() == 'False' and self.progress < self.progressLimit: #Umrechnung des Simulationsfortschrittes in Prozent
            indexTxt = open('index.txt', 'r')
            indexTxtLines = indexTxt.readlines()
            for i in range(len(indexTxtLines)):
                indexTxtLines[i] = indexTxtLines[i].replace('\n', '')
            self.progress = float(indexTxtLines[len(indexTxtLines) - 1]) * float(self.zeitschrittInput.text()) / 86400 * 100
            self.progressBar.setProperty("value", self.progress)
            self.textEditCalcInfo.setText(open('time.txt', 'r').read())
            
                
        else:
            self.progressBar.setProperty("value", 0)
            self.progress = 0

        #Dynamic graph plot update for Qtimer
        filename = 'graphTop.txt'
        if os.stat(filename).st_size != 0:
            if self.line == 0:
                time.sleep(0.2)

            file = open(filename)
            fileLines = file.readlines()
            for i in range(len(fileLines)):
                fileLines[i] = fileLines[i].replace('\n', '')
            self.x = self.x[1:]  # Remove the first y element.
            self.x.append(self.x[-1] + 1)  # Add a new value 1 higher than the last.
            self.y = self.y[1:]  # Remove the first 
            self.y.append(float(fileLines[self.line]))  # Add a new value.
            self.data_line.setData(self.x, self.y)  # Update the data.
            file.close()
            self.line += 1
            #self.counter += 1
            if self.line == len(fileLines):
                self.line = 0

        else:
            print('No Data')
            self.x = self.x[1:]  # Remove the first x element. 
            self.x.append(self.x[-1] + 1)  # Add a new value 1 higher than the last.
            self.y = self.y[1:]  # Remove the first 
            self.y.append(float(self.startTempInput.text()))  # Add a new value.
            self.data_line.setData(self.x, self.y)


#here the functions for the workers are defined
    def SUe3_fn_worker(self, progress_callback):
        open('graphTop.txt', 'w').close()
        SUe3(float(self.zeitschrittInput.text()), float(self.genauigkeitInput.text()), float(self.startTempInput.text()), bool(int(self.idealLueftenInput.text())), bool(int(self.NachtlueftenInput.text())), 
            bool(int(self.TaglueftenInput.text())), bool(int(self.SonnenschutzInput.text())), bool(int(self.NatLueftenInput.text())), bool(int(self.MechLueftenInput.text())), 
            float(self.SeehoeheInput.text()), bool(int(self.CustomLueftenInput.text())), bool(int(self.CustomSonnenschutzInput.text())), bool(int(self.CustomInnereLastenInput.text())))


        '------------------Functions by PyQt5--------------------'
#copy after changes in .ui by Designer from here 
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "SUe-Thermischer Komfort"))
        self.labelHKLS.setText(_translate("MainWindow", "HKLS-Steuerung (automatisch)"))
        self.label_19.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.labelSimpara.setText(_translate("MainWindow", "Simulationsparameter"))
        self.labelHKLS_2.setText(_translate("MainWindow", "HKLS-Steuerung (aus Input Datei)"))
        self.label_17.setText(_translate("MainWindow", "Lüften"))
        self.idealLueftenInput.setText(_translate("MainWindow", "1"))
        self.textEditCalcInfo.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:8.25pt; 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;\"><br /></p></body></html>"))
        self.CustomLueftenInput.setText(_translate("MainWindow", "0"))
        self.CustomInnereLastenInput.setText(_translate("MainWindow", "1"))
        self.NatLueftenInput.setText(_translate("MainWindow", "1"))
        self.label_20.setText(_translate("MainWindow", "Sonnenschutz"))
        self.NachtlueftenInput.setText(_translate("MainWindow", "0"))
        self.TaglueftenInput.setText(_translate("MainWindow", "1"))
        self.label_14.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_4.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_23.setText(_translate("MainWindow", "Innere Lasten"))
        self.label_2.setText(_translate("MainWindow", "s"))
        self.label_8.setText(_translate("MainWindow", "Sonnenschutz"))
        self.label_12.setText(_translate("MainWindow", "Nat. Lüftung"))
        self.label.setText(_translate("MainWindow", "Zeitschritt"))
        self.label_3.setText(_translate("MainWindow", "ideal Lüften"))
        self.label_18.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.SonnenschutzInput.setText(_translate("MainWindow", "0"))
        self.startTempInput.setText(_translate("MainWindow", "30"))
        self.MechLueftenInput.setText(_translate("MainWindow", "0"))
        self.startSimulation.setText(_translate("MainWindow", "Start"))
        self.label_16.setText(_translate("MainWindow", "Taglüften"))
        self.label_11.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_6.setText(_translate("MainWindow", "Nachtlüften"))
        self.CustomSonnenschutzInput.setText(_translate("MainWindow", "0"))
        self.label_13.setText(_translate("MainWindow", "Mech. Lüftung"))
        self.label_10.setText(_translate("MainWindow", "Seehöhe"))
        self.SeehoeheInput.setText(_translate("MainWindow", "172"))
        self.label_15.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.labelStandort.setText(_translate("MainWindow", "Standort"))
        self.label_24.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.zeitschrittInput.setText(_translate("MainWindow", "10"))
        self.label_5.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.label_7.setText(_translate("MainWindow", "1 = Ja //  0 = Nein"))
        self.stopSimulation.setText(_translate("MainWindow", "Stop"))
        self.label_22.setText(_translate("MainWindow", "Genauigkeit"))
        self.genauigkeitInput.setText(_translate("MainWindow", "1e-3"))
        self.label_26.setText(_translate("MainWindow", "Starttemperatur"))
        self.label_25.setText(_translate("MainWindow", "°C"))
        self.label_9.setText(_translate("MainWindow", "m"))
        
#to here

    '----------------------Funktionen----------------------------' 
    #Hier finden sich alle selbst geschriebenen Funktionen zu den Events

    
    def Simulation(self):        
        file = open('Abbruch.txt', 'w')
        file.write('False')
        self.line = 0
        open('graphTop.txt', 'w').close()
        open('time.txt', 'w').close()
        
        

        #SUe3(float(self.zeitschrittInput.text()), float(self.genauigkeitInput.text()), float(self.startTempInput.text()), bool(int(self.idealLueftenInput.text())), bool(int(self.NachtlueftenInput.text())), 
        #    bool(int(self.TaglueftenInput.text())), bool(int(self.SonnenschutzInput.text())), bool(int(self.NatLueftenInput.text())), bool(int(self.MechLueftenInput.text())), 
        #    float(self.SeehoeheInput.text()), bool(int(self.CustomLueftenInput.text())), bool(int(self.CustomSonnenschutzInput.text())), bool(int(self.CustomInnereLastenInput.text())))

        worker1 = Worker(self.SUe3_fn_worker) # any other args, kwargs are passed to the run function
        # execute
        self.threadpool.start(worker1)

        

   
    def Stop(self):
        file = open('Abbruch.txt', 'w')
        file.write('True')
        self.line = 0
        open('graphTop.txt', 'w').close()
        open('time.txt', 'w').close()
Exemple #22
0
class MesCourbes():
    def __init__(self):
        self.plot_widget = PlotWidget()
        self.plot_widget.showGrid(x=True,y=True)
        # self.plot_widget.getPlotItem().addLegend()
        self.plot_widget.setBackground((0, 0, 0))
        #  dictionary with all the curve and their data 
        # curve 0 is dedicated to the live/acquisition plot
        self.curves = {}

    def add_curve(self, curve_id, curve_color, markers_on=False):
        curve_name = curve_id
        pen = pg.mkPen(curve_color, width=3)
        symbol = "o"
        symbolPen = pg.mkPen(0,0,0)
        symbolBrush = curve_color
        symbolSize = 8
        # 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=symbolSize
            )
        else:
            plot = self.plot_widget.plot(name=curve_name, pen=pen)
        self.curves[curve_id] = {
                    'plot':plot,
                    'data':{'Current':[],'X':[],'Y':[],'R':[],'Phi':[]}
                        }

    def average(self,curve_id,param_tree):
        current_min = param_tree.give('Laser Driver','current min')
        current_max = param_tree.give('Laser Driver','current max')
        nbr_pts = param_tree.give('Laser Driver','nbr pts')
        nbr_seqs = param_tree.give('Laser Driver','nbr seqs')
        current_list = np.linspace(current_min,current_max,nbr_pts)
        self.curves[curve_id]['data']['Current'] = current_list
        for k in ['X','Y','R','Phi']:
            temp = self.curves[curve_id]['data'][k]
            self.curves[curve_id]['data'][k] = toolbox.function.average(temp,nbr_seqs)

    def clear_data(self,curve_id):
        for k in ['Current','X','Y','R','Phi']:
            self.curves[curve_id]['data'][k] = []       

    def create_current_list(self,curve_id,param_tree):
        '''
        Create a array with all the frequency use for the frequency sweep
        It take into account if many sequences have been asked
        '''
        current_min = param_tree.give('Laser Driver','current min')
        current_max = param_tree.give('Laser Driver','current max')
        nbr_pts = param_tree.give('Laser Driver','nbr pts')
        nbr_seqs = param_tree.give('Laser Driver','nbr seqs')
        current_list = np.linspace(current_min,current_max,nbr_pts)
        if nbr_seqs > 1:
            temp = current_list
            i=0
            while i < int(nbr_seqs)-1:
                i+=1
                current_list = np.append(current_list,temp[::(-1)**i])
        self.curves[curve_id]['data']['Current'] = current_list

    def display(self,curve_id,what):
        X = self.curves[curve_id]['data']['Current']
        Y = self.curves[curve_id]['data'][what]
        # during acquisition freq is longer than the others datas
        # so it is useful to reduce it
        if len(X) != len(Y):
            X = self.curves[curve_id]['data']['Current'][0:len(Y)]
        self.set_values(curve_id,X,Y)

    def remove_curve(self, curve_id):
        curve_id = str(curve_id)
        if curve_id in self.curves:
            self.plot_widget.removeItem(self.curves[curve_id]['plot'])
            del self.curves[curve_id]

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

    def update_X_Y_R_Phi(self,curve_id,A):
        self.curves[curve_id]['data']['X'] = np.append(self.curves[curve_id]['data']['X'],A[0])
        self.curves[curve_id]['data']['Y'] = np.append(self.curves[curve_id]['data']['Y'],A[1])
        self.curves[curve_id]['data']['R'] = np.append(self.curves[curve_id]['data']['R'],A[2])
        self.curves[curve_id]['data']['Phi'] = np.append(self.curves[curve_id]['data']['Phi'],A[3]) 
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
Exemple #24
0
class FindPeak(QWidget):
    def __init__(self, parent, x_data, y_data):
        super(FindPeak, self).__init__()
        self.parent = parent
        self.x = x_data
        self.y = y_data
        self.lower = np.min(x_data)
        self.upper = np.max(x_data)
        self.range = self.upper - self.lower
        self.renderWindow()
        self.initPlotView()
        self.drawCurve()
        self.setUpProcessUI()
        self.bindEvents()
        self.integral(x_data, y_data, self.lower, self.upper)

    def bindEvents(self):
        self.bindBoundEvent()
        self.bindAlgorithmEvent()
        self.bindFindEvent()

    def bindBoundEvent(self):
        def leftBoundEvent(x):
            self.lower = x
            upper = self.upper
            self.plotRegion.setRegion([x, upper])
            self.rightBound.setMinimum(x)
            self.peakCenter.setMinimum(x)
            self.peakCenter.setValue((x + upper) / 2)
            self.integral(self.x, self.y, x, upper)

        def rightBoundEvent(x):
            self.upper = x
            lower = self.lower
            self.plotRegion.setRegion([lower, x])
            self.leftBound.setMaximum(x)
            self.peakCenter.setMaximum(x)
            self.peakCenter.setValue((x + lower) / 2)
            self.integral(self.x, self.y, lower, x)

        def regionChangeEvent():
            lower, upper = self.plotRegion.getRegion()
            self.lower = lower
            self.upper = upper
            self.leftBound.setValue(lower)
            self.leftBound.setMaximum(upper)
            self.rightBound.setValue(upper)
            self.rightBound.setMinimum(lower)
            self.peakCenter.setMinimum(lower)
            self.peakCenter.setMaximum(upper)
            self.peakCenter.setValue((lower + upper) / 2)
            self.integral(self.x, self.y, lower, upper)

        self.leftBound.valueChanged.connect(leftBoundEvent)
        self.rightBound.valueChanged.connect(rightBoundEvent)
        self.plotRegion.sigRegionChanged.connect(regionChangeEvent)

    def bindAlgorithmEvent(self):
        def updateInput(a, b, c, d, e, f):
            self.peakWidth.setEnabled(a)
            self.detectDis.setEnabled(b)
            self.noisePrt.setEnabled(c)
            self.amplitude.setEnabled(d)
            self.threshold.setEnabled(e)
            self.findBtn.setEnabled(f)

        def changeAlgorithm(algorithm):
            if algorithm == "Extremum":
                updateInput(False, False, False, False, False, True)
                pass
            elif algorithm == "Matlab Like":
                updateInput(True, True, False, True, True, True)
                pass
            elif algorithm == "Gaussian":
                updateInput(False, False, False, False, False, False)
                pass
            elif algorithm == "Lorentzian":
                updateInput(False, False, False, False, False, False)
                pass
            elif algorithm == "Pseudo-Voigt":
                updateInput(False, False, False, False, False, False)
                pass
            elif algorithm == "Wavelet Transform":
                updateInput(True, True, True, False, False, False)
                pass

        self.algorithm.currentTextChanged.connect(changeAlgorithm)
        updateInput(False, False, False, False, False, True)

    def integral(self, x_data, y_data, lower, upper):
        idx = np.where((x_data >= lower) & (x_data <= upper))
        x = x_data[idx]
        y = y_data[idx]
        self.integralArea.setValue(simps(y, x))

    def bindFindEvent(self):
        x_data = self.x
        y_data = self.y

        def findPeak():
            region = np.where((x_data >= self.lower) & (x_data <= self.upper))
            sub_data = y_data[region]
            sub_region = x_data[region]
            algorithm = self.algorithm.currentText()
            shape = self.shape.currentText()
            if shape == "Peak":
                const = 1
            else:
                const = -1
            sub_data = sub_data * const
            if algorithm == "Extremum":
                peak = np.max(sub_data)
                idx = np.where(sub_data == peak)
                x = sub_region[idx][0]
                y = sub_data[idx][0] * const
                self.peakCenter.setValue(x)
                return self.renderPeakPoint([x, y])
            elif algorithm == "Matlab Like":
                indexes = find_peaks(
                    sub_data,
                    height=self.amplitude.value(),  #低于指定高度忽略
                    threshold=self.threshold.value(),  #相邻两点高度差
                    distance=self.detectDis.value(),  #两峰间距
                    width=self.peakWidth.value()  #峰宽
                )[0]
                if np.size(indexes) == 0:
                    return
                idx = np.where(sub_data == np.max(sub_data[indexes]))
                x = sub_region[idx][0]
                y = sub_data[idx][0] * const
                self.peakCenter.setValue(x)
                return self.renderPeakPoint([x, y])
            elif algorithm == "Wavelet Transform":
                indexes = find_peaks_cwt(
                    sub_data,
                    widths=self.peakWidth.value(),  #峰宽
                    max_distances=self.detectDis.value(),  #两峰间距
                    noise_perc=self.noisePrt.value())[0]
                if np.size(indexes) == 0:
                    return
                idx = np.where(sub_data == np.max(sub_data[indexes]))
                x = sub_region[idx][0]
                y = sub_data[idx][0] * const
                self.peakCenter.setValue(x)
                return self.renderPeakPoint([x, y])
                self.noisePrt
            pass

        self.findBtn.clicked.connect(findPeak)

    def renderPeakPoint(self, pos):
        self.peakPoint.clear()
        self.peakPoint.addPoints([{'pos': pos, 'data': 1}])

    def renderWindow(self):
        #边框结构
        self.setGeometry(80, 80, 800, 420)
        size = self.geometry()
        screen = QDesktopWidget().screenGeometry()
        posX = (screen.width() - size.width()) / 2
        posY = (screen.height() - size.height()) / 2
        self.move(posX, posY)
        #标题
        self.setWindowTitle('Find Peak')
        self.setWindowIcon(QIcon('resource/curve.ico'))
        #布局
        layout = QGridLayout()
        self.graphicsView = QGridLayout()
        layout.addLayout(self.graphicsView, 0, 0, 1, 1)

        self.Process_Box = QGroupBox()
        self.Process_Box.setMinimumSize(200, 420)
        self.Process_Box.setFlat(True)
        layout.addWidget(self.Process_Box, 0, 1, 1, 1)

        self.setLayout(layout)

    def setUpProcessUI(self):
        layout = QGridLayout()
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(10)
        self.Process_Box.setLayout(layout)

        layout.addWidget(QLabel(self.translate('Left Boundary')), 0, 0, 1, 1)
        layout.addWidget(QLabel(self.translate('Right Boundary')), 1, 0, 1, 1)
        layout.addWidget(QLabel(self.translate("Integral Area")), 2, 0, 1, 1)
        layout.addWidget(QLabel(self.translate('Peak Center')), 3, 0, 1, 1)
        layout.addWidget(QLabel(self.translate('Peak Shape')), 4, 0, 1, 1)
        layout.addWidget(QLabel(self.translate('Find Peak Algorithm')), 5, 0,
                         1, 1)
        layout.addWidget(QLabel(self.translate('Minimum Peak Width')), 6, 0, 1,
                         1)
        layout.addWidget(QLabel(self.translate('Minimum Detect Distance')), 7,
                         0, 1, 1)
        layout.addWidget(QLabel(self.translate('Noise Percent')), 8, 0, 1, 1)
        layout.addWidget(QLabel(self.translate("Minimum Amplitude")), 9, 0, 1,
                         1)
        layout.addWidget(QLabel(self.translate("Relative Threshold")), 10, 0,
                         1, 1)

        self.leftBound = SpinBox(lower=self.lower, dec=4, val=self.lower)
        self.rightBound = SpinBox(upper=self.upper, dec=4, val=self.upper)
        self.peakCenter = SpinBox(lower=self.lower, upper=self.upper, dec=4)
        self.peakWidth = SpinBox(lower=1, upper=10000, val=5)
        self.noisePrt = SpinBox(lower=0, upper=100, step=1, val=10)
        self.detectDis = SpinBox(lower=1, val=3)
        self.amplitude = SpinBox(lower=-1E5, upper=1E5, dec=4, val=-1)
        self.threshold = SpinBox(lower=0, upper=100, dec=4, val=0.001)
        self.integralArea = SpinBox(upper=1E8, dec=4)
        self.integralArea.setReadOnly(True)
        self.integralArea.setButtonSymbols(QAbstractSpinBox.NoButtons)

        self.shape = QComboBox()
        self.shape.addItems(["Peak", "Valley"])
        #self.shape.currentTextChanged.connect()

        self.algorithm = QComboBox()
        self.algorithm.addItems([
            'Extremum', 'Matlab Like', 'Wavelet Transform', 'Gaussian',
            'Lorentzian', 'Pseudo-Voigt'
        ])
        #self.algorithm.currentTextChanged.connect()
        #https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks_cwt.html
        layout.addWidget(self.leftBound, 0, 1, 1, 1)
        layout.addWidget(self.rightBound, 1, 1, 1, 1)
        layout.addWidget(self.integralArea, 2, 1, 1, 1)
        layout.addWidget(self.peakCenter, 3, 1, 1, 1)
        layout.addWidget(self.shape, 4, 1, 1, 1)
        layout.addWidget(self.algorithm, 5, 1, 1, 1)
        layout.addWidget(self.peakWidth, 6, 1, 1, 1)
        layout.addWidget(self.detectDis, 7, 1, 1, 1)
        layout.addWidget(self.noisePrt, 8, 1, 1, 1)
        layout.addWidget(self.amplitude, 9, 1, 1, 1)
        layout.addWidget(self.threshold, 10, 1, 1, 1)

        self.findBtn = QPushButton(self.translate('Find Peak'))
        layout.addWidget(self.findBtn, 11, 0, 1, 2)
        pass

    def initPlotView(self):
        self.plot = PlotWidget(enableAutoRange=True)
        self.plot.setXRange(self.lower - self.range * 0.05,
                            self.upper + self.range * 0.05)
        self.plotLegand = self.plot.addLegend()
        self.graphicsView.addWidget(self.plot)
        self.plotRegion = LinearRegionItem()
        self.plotRegion.setZValue(10)
        self.peakPoint = ScatterPlotItem(size=8,
                                         pen=mkPen(color='0000FF', width=2),
                                         symbol="+",
                                         brush=mkBrush(255, 255, 255, 240))
        self.plot.addItem(self.plotRegion, ignoreBounds=True)
        self.plot.addItem(self.peakPoint)
        self.setGraphViewStyle()

    def setGraphViewStyle(self):
        self.plot.setAutoVisible(y=True)
        self.plot.setBackground('#ffffff')
        self.plot.showGrid(x=True, y=True, alpha=0.25)
        self.plot.getAxis('bottom').setPen(color='#000000', width=1.5)
        self.plot.getAxis('left').setPen(color='#000000', width=1.5)
        self.plotRegion.setRegion([self.lower, self.upper])
        self.plotRegion.setBounds([self.lower, self.upper])

    def drawCurve(self):
        pen = mkPen(color='FF0000', width=2)
        self.plot.plot(self.x, self.y, pen=pen)
        self.plot.show()

    def translate(self, text):
        if self.parent:
            self.langText = self.parent.langText
        else:
            self.langText = load(open('SCN.translation', encoding='utf-8'))
        if text in self.langText:
            return self.langText[text]
        return text
Exemple #25
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_()
Exemple #26
0
class ControllerGUITab(QWidget):
    LEFT_COLUMN_MAX_WIDTH = 400

    # This signal tells the global tab if is not possible to start dosing for this tab
    # False is sent out when the dosing vectors are incorrect or when the process is already started
    dosingSignal = pyqtSignal(bool)

    # This just signals if saving was enabled/disabled by the user in the tab, so the global tab can update itself
    savingSignal = pyqtSignal(bool)

    # Signal when a sample is ready for the combined plot
    sampleReady = pyqtSignal(int, np.float16)

    def __init__(self, controller: Controller):
        super().__init__()
        # Create the master layout
        outerLayout = QHBoxLayout()
        self.graph = None
        self.controller = controller
        self.temperatureController = None
        self.tempControllerGroup = None
        self.sensor1 = None
        self.sensor2 = None
        self.sensor1Group = None
        self.sensor2Group = None

        self.vorNormalButton = None
        self.vorClosedButton = None
        self.vorOpenButton = None

        self.gasFactorEdit = None
        self.pvFullScaleEdit = None
        self.pvSigtypeDropdown = None
        self.spFullScaleEdit = None
        self.spSigtypeDropdown = None
        self.spSourceDropdown = None
        self.decimalDropdown = None
        self.measureUnitsDropdown = None
        self.timebaseDropdown = None

        self.bufferSizeEdit = None
        self.intervalEdit = None
        self.setpointEdit = None
        self.setpointUnitsLabel = None
        self.saveCsvButton = None

        self.sensor1Timer = None
        self.sensor1SampleIntervalEdit = None
        self.sensor1BufferSizeEdit = None

        self.sensor2Timer = None
        self.sensor2SampleIntervalEdit = None
        self.sensor2BufferSizeEdit = None

        self.temperatureSlider = None
        self.temperatureLabel = None
        self.tempReadoutLabel = None
        self.rangeLowEdit = None
        self.rangeHighEdit = None
        self.rampingCheckbox = None
        self.gradientEdit = None
        self.tempControlButton = None

        self.dosingTimesEdit = None
        self.dosingTimes = None
        self.dosingValuesEdit = None
        self.dosingValues = None
        self.dosingUnitsLabel = None
        self.dosingLabel = None
        self.dosingVorStateLabel = None
        self.dosingControlButton = None
        self.dosingEnabled = False

        # Data buffers
        self.sampleBufferSize = 64
        self.samplesPV = RingBuffer(capacity=self.sampleBufferSize,
                                    dtype=np.float16)
        self.samplesTotalizer = RingBuffer(capacity=self.sampleBufferSize,
                                           dtype=np.float32)
        self.sampleTimestamps = RingBuffer(capacity=self.sampleBufferSize,
                                           dtype=datetime)

        # Nest the inner layouts into the outer layout
        outerLayout.addLayout(self.create_left_column())
        outerLayout.addLayout(self.create_right_column())
        # Set the window's main layout
        self.setLayout(outerLayout)

        # Generic timer that calls generic_update every second
        # Used to update a few labels
        self.genericTimer = QTimer()
        self.genericTimer.timeout.connect(self.update_generic)
        self.genericTimer.start(1000)

        self.graphTimer = QTimer()
        self.graphTimer.timeout.connect(self.update_plot)
        self.graphTimer.start(int(60 * 1000 * float(self.intervalEdit.text())))

        self.dosingValue = None
        self.dosingTimer = QTimer()
        self.dosingTimer.timeout.connect(self.dosing_process)

        self.csvFile = None
        self.csvIterator = 1

        self.defaultStyleSheet = QLineEdit().styleSheet()

        # Current dosing value, used to set the setpoint edit
        # text correctly after a process shutdown
        self.spValue = 1.0

        # Get initial dosing values from the text inside
        self.dosingValues = [
            float(x) for x in self.dosingValuesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingTimes = [
            float(x) * 60 * 1000
            for x in self.dosingTimesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingValues.reverse()
        self.dosingTimes.reverse()

    def get_measurement(self):
        # Proper implementation that gets the data from the device over serial
        current, total, timestamp = self.controller.get_measurements()
        if total is not None:
            self.samplesTotalizer.append(total)
            self.samplesPV.append(current)
            self.sampleTimestamps.append(timestamp)
            self.sampleReady.emit(self.controller.channel, current)

    # Save samples to a csv file, named after the current time and controller number it is coming from
    # After this function saving is continued by update_plot function, which calls append_to_csv
    def save_to_csv_start(self):
        # If saving is invoked from global tab while it is already enabled, close the old file,
        # so no sensor data will be lost and it will be closed properly
        if self.csvFile is not None:
            self.save_to_csv_stop()
        filename = datetime.now().strftime(
            f"controller{self.controller.channel}_%Y-%m-%d_%H-%M-%S.csv")

        self.csvFile = open(filename, 'w')
        self.csvFile.write(
            f"Gas factor:{self.controller.get_gas()}\tDecimal point:{self.controller.get_decimal_point()},\tUnits:{self.controller.get_measurement_units()}/{self.controller.get_time_base()}\n"
        )
        self.csvFile.write("{:<15} {:^18} {:>19}\n".format(
            "Measurement", "Totalizer", "Time of measurement"))
        for i in range(0, len(self.samplesPV) - 1):
            self.csvFile.write("{:<15},{:^18},{:>19}\n".format(
                self.samplesPV[len(self.samplesPV) - 1],
                self.samplesTotalizer[len(self.samplesPV) - 1],
                self.sampleTimestamps[len(self.samplesPV) -
                                      1].strftime("%Y/%m/%d,%H:%M:%S")))

        self.saveCsvButton.clicked.disconnect()
        self.saveCsvButton.clicked.connect(self.save_to_csv_stop)
        self.saveCsvButton.setText("Stop saving to CSV")
        self.savingSignal.emit(True)

    def append_to_csv(self):
        # check if file is bigger than ~8MB
        if self.csvFile.tell() > 8192000:
            name = re.sub(
                r"(|_[0-9]+).csv", f"_{self.csvIterator}.csv",
                self.csvFile.name.split("\\")[
                    len(self.csvFile.name.split("\\")) - 1])
            self.csvIterator += 1
            self.append_sensor()
            self.csvFile.close()
            self.csvFile = open(name, 'w')
        self.csvFile.write("{:<15},{:^18},{:>19}\n".format(
            self.samplesPV[len(self.samplesPV) - 1],
            self.samplesTotalizer[len(self.samplesPV) - 1],
            self.sampleTimestamps[len(self.samplesPV) -
                                  1].strftime("%Y/%m/%d,%H:%M:%S")))

    def save_to_csv_stop(self):
        self.append_sensor()
        self.csvFile.close()
        self.csvFile = None
        self.saveCsvButton.clicked.disconnect()
        self.saveCsvButton.clicked.connect(self.save_to_csv_start)
        self.saveCsvButton.setText("Start saving to CSV")
        self.csvIterator = 1
        self.savingSignal.emit(False)

    def append_sensor(self):
        # if available, append data from sensors
        if self.sensor1 is not None and len(self.sensor1.buffer) > 0:
            self.csvFile.write(f"Sensor 1 header: {self.sensor1.header}\n")
            for i in range(0, len(self.sensor1.buffer)):
                self.csvFile.write(str(self.sensor1.buffer[i]))
            self.sensor1.buffer.clear()
            self.csvFile.write('\n')

        if self.sensor2 is not None and len(self.sensor2.buffer) > 0:
            self.csvFile.write(f"Sensor 2 header: {self.sensor2.header}\n")
            for i in range(0, len(self.sensor2.buffer)):
                self.csvFile.write(str(self.sensor2.buffer[i]))
            self.sensor2.buffer.clear()

    # Handler functions for UI elements
    # TODO: react to returned value from functions
    def update_vor_normal(self):
        if self.vorNormalButton.isChecked():
            # disable other buttons to clarify which VOR state is active
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
            self.controller.set_valve_override(Controller.VOR_OPTION_NORMAL)
            self.dosingVorStateLabel.setText("VOR is normal")
            self.dosingVorStateLabel.setStyleSheet("color: green;")

    def update_vor_closed(self):
        if self.vorClosedButton.isChecked():
            self.vorNormalButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
            self.controller.set_valve_override(Controller.VOR_OPTION_CLOSED)
            self.dosingVorStateLabel.setText("VOR is closed")
            self.dosingVorStateLabel.setStyleSheet("color: red;")

    def update_vor_open(self):
        if self.vorOpenButton.isChecked():
            self.vorClosedButton.setChecked(False)
            self.vorNormalButton.setChecked(False)
            self.controller.set_valve_override(Controller.VOR_OPTION_OPEN)
            self.dosingVorStateLabel.setText("VOR is open")
            self.dosingVorStateLabel.setStyleSheet("color: red;")

    def update_gas_factor(self):
        self.controller.set_gas_factor(float(self.gasFactorEdit.text()))

    def update_pv_full_scale(self):
        self.controller.set_pv_full_scale(float(self.pvFullScaleEdit.text()))

    def update_pv_signal_type(self):
        self.controller.set_pv_signal_type(
            self.pvSigtypeDropdown.currentText())

    def update_sp_full_scale(self):
        self.controller.set_sp_full_scale(float(self.spFullScaleEdit.text()))

    def update_sp_signal_type(self):
        self.controller.set_sp_signal_type(
            self.spSigtypeDropdown.currentText())

    def update_source(self):
        self.controller.set_source(self.spSourceDropdown.currentText())

    def update_decimal_point(self):
        self.controller.set_decimal_point(self.decimalDropdown.currentText())

    def update_measure_units(self):
        if self.dosingUnitsLabel is not None:
            self.dosingUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        if self.setpointUnitsLabel is not None:
            self.setpointUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        self.controller.set_measurement_units(
            self.measureUnitsDropdown.currentText())

    def update_time_base(self):
        if self.dosingUnitsLabel is not None:
            self.dosingUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        if self.setpointUnitsLabel is not None:
            self.setpointUnitsLabel.setText(
                f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
            )
        self.controller.set_time_base(self.timebaseDropdown.currentText())

    def update_buffer_size(self):
        self.change_buffer_size(int(self.bufferSizeEdit.text()))
        self.sampleBufferSize = int(self.bufferSizeEdit.text())

    def update_graph_timer(self):
        self.graphTimer.setInterval(
            float(self.intervalEdit.text()) * 60 * 1000)

    def update_setpoint(self):
        value = float(self.setpointEdit.text())
        self.controller.set_setpoint(value)

    def update_sensor1_timer(self):
        self.sensor1Timer.setInterval(
            float(self.sensor1SampleIntervalEdit.text()) * 60 * 1000)

    def update_sensor1_buffer(self):
        self.sensor1.change_buffer_size(int(self.sensor1BufferSizeEdit.text()))

    def update_sensor2_timer(self):
        self.sensor2Timer.setInterval(
            float(self.sensor2SampleIntervalEdit.text()) * 60 * 1000)

    def update_sensor2_buffer(self):
        self.sensor2.change_buffer_size(int(self.sensor2BufferSizeEdit.text()))

    def update_temperature(self):
        self.temperatureController.set_temperature(
            float(self.temperatureSlider.value()))
        self.temperatureLabel.setText(self.temperatureSlider.value())

    def update_range_low(self):
        newTemp = self.temperatureController.set_range_low(
            float(self.rangeLowEdit.text()))
        self.temperatureSlider.setMinimum(float(self.rangeLowEdit.text()))
        self.temperatureSlider.setValue(newTemp)

    def update_range_high(self):
        newTemp = self.temperatureController.set_range_high(
            float(self.rangeHighEdit.text()))
        self.temperatureSlider.setMaximum(float(self.rangeHighEdit.text()))
        self.temperatureSlider.setValue(newTemp)

    def update_ramping_enable(self):
        if self.rampingCheckbox.isChecked():
            self.temperatureController.ramping_on()
        else:
            self.temperatureController.ramping_off()

    def update_gradient(self):
        self.temperatureController.set_gradient(float())

    def update_temp_control_enable(self):
        if self.tempControlButton.isChecked():
            self.temperatureController.ramping_on()
            self.tempControlButton.setText("Disable output")
        else:
            self.temperatureController.ramping_off()
            self.tempControlButton.setText("Enable output")

    def update_dosing_vectors(self):
        self.dosingValues = [
            float(x) for x in self.dosingValuesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingTimes = [
            float(x) * 1000 * 60
            for x in self.dosingTimesEdit.text().split(sep=',')
            if x.strip() != ''
        ]

        # Since we will be using pop() to get the next values, we reverse the arrays
        self.dosingValues.reverse()
        self.dosingTimes.reverse()

        if len(self.dosingTimes) != len(self.dosingValues) or len(
                self.dosingTimes) * len(self.dosingValues) == 0:
            self.dosingTimesEdit.setStyleSheet("color: red;")
            self.dosingValuesEdit.setStyleSheet("color: red;")
            self.dosingControlButton.setEnabled(False)
            self.dosingSignal.emit(True)
        else:
            self.dosingTimesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingValuesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingControlButton.setEnabled(True)
            self.dosingSignal.emit(False)

    def update_dosing_state(self):
        if self.dosingControlButton.isChecked():
            self.dosingValuesEdit.setEnabled(False)
            self.dosingValuesEdit.setStyleSheet("color: grey")
            self.dosingTimesEdit.setEnabled(False)
            self.dosingTimesEdit.setStyleSheet("color: grey")
            self.dosingControlButton.setText("Disable dosing")
            self.setpointEdit.setEnabled(False)
            self.dosingEnabled = True
            self.dosingSignal.emit(True)
            # Set VOR to normal for dosing
            self.vorNormalButton.setChecked(True)
            self.update_vor_normal()
            self.dosing_process()
        else:
            self.dosingValuesEdit.setEnabled(True)
            self.dosingValuesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingTimesEdit.setEnabled(True)
            self.dosingTimesEdit.setStyleSheet(self.defaultStyleSheet)
            self.dosingControlButton.setText("Enable dosing")
            self.setpointEdit.setEnabled(True)
            self.dosingEnabled = False
            self.end_dosing_process()

    # This function sets the setpoint to those values that were set when "Enable dosing" was pressed
    # and iterates over them
    def dosing_process(self):
        self.spValue = self.dosingValues.pop()
        spTime = self.dosingTimes.pop()

        self.setpointEdit.setText(f"{str(self.spValue)} - dosing is enabled")
        self.controller.set_setpoint(self.spValue)

        if len(self.dosingTimes) == 0:
            self.dosingTimer.timeout.disconnect()
            self.dosingTimer.singleShot(spTime, self.end_dosing_process)

        self.dosingTimer.setInterval(spTime)
        self.dosingTimer.start()

    def update_generic(self):
        if self.dosingTimer.isActive() and len(self.dosingValues) > 0:
            if self.dosingTimer.remainingTime() / 1000 > 60:
                self.dosingLabel.setText(
                    f"{int(self.dosingTimer.remainingTime() / (1000 * 60))} minutes {int(self.dosingTimer.remainingTime() / 1000) % 60} seconds until next dosing value: {self.dosingValues[-1]}"
                )
            else:
                self.dosingLabel.setText(
                    f"{int(self.dosingTimer.remainingTime() / 1000)} seconds until next dosing value: {self.dosingValues[-1]}"
                )
        elif self.dosingTimer.isActive() and len(self.dosingValues) == 0:
            self.dosingLabel.setText(
                f"{int(self.dosingTimer.remainingTime() / 1000)} seconds until end of process"
            )
        else:
            self.dosingLabel.setText("Dosing disabled")

        if self.temperatureController is not None:
            self.tempReadoutLabel.setText(
                f"Readout: {self.temperatureController.read_temperature()} ℃")
        else:
            self.tempReadoutLabel.setText("Readout: None ℃")

    def end_dosing_process(self):
        self.dosingControlButton.setChecked(False)
        self.dosingControlButton.setText("Enable dosing")
        self.dosingLabel.setText("Dosing disabled")
        self.dosingTimer.stop()

        # Since all the values have been popped and the text is unchanged, we fill the vectors again
        self.dosingValues = [
            float(x) for x in self.dosingValuesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingTimes = [
            float(x) * 60 * 1000
            for x in self.dosingTimesEdit.text().split(sep=',')
            if x.strip() != ''
        ]
        self.dosingValues.reverse()
        self.dosingTimes.reverse()

        # Remove the string portion from setpoint field
        self.setpointEdit.setText(str(self.spValue))

        # Unlock the setpoint and dosing values/times fields
        self.setpointEdit.setEnabled(True)
        self.dosingValuesEdit.setEnabled(True)
        self.dosingTimesEdit.setEnabled(True)

        # Return to normal stylesheet
        self.dosingValuesEdit.setStyleSheet(self.defaultStyleSheet)
        self.dosingTimesEdit.setStyleSheet(self.defaultStyleSheet)

        # reconnect the dosing_process function to the timer
        self.dosingTimer.timeout.connect(self.dosing_process)

        # Set the setpoint to 0 and close valve at the end
        self.controller.set_setpoint(0)
        self.setpointEdit.setText("0")

        self.vorClosedButton.setChecked(True)
        self.dosingSignal.emit(False)
        self.update_vor_closed()

    def update_plot(self):
        self.graph.clear()
        self.get_measurement()
        self.graph.plot(self.samplesPV,
                        pen=pyqtgraph.mkPen((255, 127, 0), width=1.25),
                        symbolBrush=(255, 127, 0),
                        symbolPen=pyqtgraph.mkPen((255, 127, 0)),
                        symbol='o',
                        symbolSize=5,
                        name="symbol ='o'")
        if self.csvFile is not None:
            self.append_to_csv()

    def update_sensor1_group(self):
        if self.sensor1Group.isChecked():
            dg = SensorConfigDialog()
            dg.accepted.connect(self.connect_sensor1)
            # if unsuccessful, disable the temperature controller group
            if dg.exec_() == 0:
                self.sensor1Group.setChecked(False)
        else:
            self.sensor1.close()
            self.sensor1Timer.stop()
            self.sensor1 = None

    # connect to sensor instance 1 using values returned by the dialog
    def connect_sensor1(self, values):
        self.sensor1 = Sensor(comport=values['port'],
                              baudrate=values['baudrate'],
                              databits=values['databits'],
                              parity=values['paritybits'],
                              stopbits=values['stopbits'],
                              dataHeader=values['header'])
        self.sensor1Timer = QTimer()
        self.sensor1Timer.setInterval(
            float(self.sensor1SampleIntervalEdit.text()) * 1000 * 60)
        self.sensor1Timer.timeout.connect(self.sensor1_get_data)
        self.sensor1Timer.start()

    # Wrapper function to handle exceptions from GUI level
    def sensor1_get_data(self):
        try:
            self.sensor1.getData()
        except SerialException as se:
            dg = QErrorMessage()
            dg.setWindowIcon(QIcon(':/icon.png'))
            dg.setWindowTitle("Sensor 1 Exception")

            filename = datetime.now().strftime("sensor1_%Y-%m-%d_%H-%M-%S.csv")
            dumpFile = open(filename, 'w')

            dumpFile.write(f"Sensor 1 header: {self.sensor1.header}\n")
            for i in range(0, len(self.sensor1.buffer)):
                self.csvFile.write(str(self.sensor1.buffer[i]))
            dumpFile.close()

            self.sensor1Group.setChecked(False)
            self.update_sensor1_group()
            dg.showMessage(f"Sensor 1 has encountered an exception: {se}")
            dg.exec_()

    def update_sensor2_group(self):
        if self.sensor2Group.isChecked():
            dg = SensorConfigDialog()
            dg.accepted.connect(self.connect_sensor2)
            # if unsuccessful, disable the temperature controller group
            if dg.exec_() == 0:
                self.sensor2Group.setChecked(False)
        else:
            self.sensor2.close()
            self.sensor2Timer.stop()
            self.sensor2 = None

    # connect to sensor instance 2 using values returned by the dialog
    def connect_sensor2(self, values):
        self.sensor2 = Sensor(comport=values['port'],
                              baudrate=values['baudrate'],
                              databits=values['databits'],
                              parity=values['paritybits'],
                              stopbits=values['stopbits'],
                              dataHeader=values['header'])
        self.sensor2Timer = QTimer()
        self.sensor2Timer.setInterval(
            float(self.sensor2SampleIntervalEdit.text()) * 1000 * 60)
        self.sensor2Timer.timeout.connect(self.sensor2_get_data)
        self.sensor2Timer.start()

    # Wrapper function to handle exceptions from GUI level
    def sensor2_get_data(self):
        try:
            self.sensor2.getData()
        except SerialException as se:
            dg = QErrorMessage()
            dg.setWindowIcon(QIcon(':/icon.png'))
            dg.setWindowTitle("Sensor 2 Exception")

            filename = datetime.now().strftime("sensor2_%Y-%m-%d_%H-%M-%S.csv")
            dumpFile = open(filename, 'w')

            dumpFile.write(f"Sensor 2 header: {self.sensor2.header}\n")
            for i in range(0, len(self.sensor2.buffer)):
                self.csvFile.write(str(self.sensor2.buffer[i]))
            dumpFile.close()

            self.sensor2Group.setChecked(False)
            self.update_sensor2_group()
            dg.showMessage(f"Sensor 2 has encountered an exception: {se}")
            dg.exec_()

    def update_temperature_group(self):
        if self.tempControllerGroup.isChecked():
            dg = AR6X2ConfigDialog()
            dg.accepted.connect(self.connect_temp_controller)
            # if unsuccessful, disable the temperature controller group
            if dg.exec_() == 0:
                self.tempControllerGroup.setChecked(False)
        else:
            self.temperatureController = None
            self.tempControlButton.setText("Enable output")

    # Connect to the AR6X2 controller using given parameters
    def connect_temp_controller(self, values):
        self.temperatureController = AR6X2(port=values['port'],
                                           address=values['address'])

    def create_left_column(self):
        # Create a vertical layout for the left column
        leftColumnLayout = QVBoxLayout()

        # Valve override group
        vorGroup = QGroupBox("Valve override")
        vorLayout = QHBoxLayout()

        self.vorNormalButton = QPushButton("Normal")
        self.vorNormalButton.setMinimumWidth(50)
        self.vorNormalButton.setFixedHeight(75)
        self.vorNormalButton.setCheckable(True)
        self.vorNormalButton.clicked.connect(self.update_vor_normal)

        self.vorClosedButton = QPushButton("Closed")
        self.vorClosedButton.setMinimumWidth(50)
        self.vorClosedButton.setFixedHeight(75)
        self.vorClosedButton.setCheckable(True)
        self.vorClosedButton.clicked.connect(self.update_vor_closed)

        self.vorOpenButton = QPushButton("Open")
        self.vorOpenButton.setMinimumWidth(50)
        self.vorOpenButton.setFixedHeight(75)
        self.vorOpenButton.setCheckable(True)
        self.vorOpenButton.clicked.connect(self.update_vor_open)

        vorState = self.controller.get_valve_override()
        if vorState == "Normal":
            self.vorNormalButton.setChecked(True)
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(False)
        elif vorState == "Closed":
            self.vorNormalButton.setChecked(False)
            self.vorClosedButton.setChecked(True)
            self.vorOpenButton.setChecked(False)
        elif vorState == "Open":
            self.vorNormalButton.setChecked(False)
            self.vorClosedButton.setChecked(False)
            self.vorOpenButton.setChecked(True)
        else:
            raise ValueError(f"Unexpected vor state: {vorState}")

        vorLayout.addWidget(self.vorNormalButton)
        vorLayout.addWidget(self.vorClosedButton)
        vorLayout.addWidget(self.vorOpenButton)

        vorGroup.setLayout(vorLayout)
        vorGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        leftColumnLayout.addWidget(vorGroup, alignment=Qt.AlignTop)

        # Process configuration group
        processGroup = QGroupBox("Process configuration")
        processLayout = QFormLayout()

        self.gasFactorEdit = QLineEdit()
        self.gasFactorEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.gasFactorEdit.editingFinished.connect(self.update_gas_factor)
        self.gasFactorEdit.setText("{:.5f}".format(self.controller.get_gas()))

        self.pvFullScaleEdit = QLineEdit()
        self.pvFullScaleEdit.setValidator(
            QRegExpValidator(QRegExp("(-|)[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.pvFullScaleEdit.editingFinished.connect(self.update_pv_full_scale)
        self.pvFullScaleEdit.setText(str(self.controller.get_pv_full_scale()))

        self.pvSigtypeDropdown = QComboBox()
        self.pvSigtypeDropdown.addItems(Controller.INPUT_PORT_TYPES.keys())
        self.pvSigtypeDropdown.currentTextChanged.connect(
            self.update_pv_signal_type)
        self.pvSigtypeDropdown.setCurrentText(
            str(self.controller.get_pv_signal_type()))

        self.spFullScaleEdit = QLineEdit()
        self.spFullScaleEdit.setValidator(
            QRegExpValidator(QRegExp("(-|)[0-9]{1,3}(|\\.[0-9]{1,3})")))
        self.spFullScaleEdit.editingFinished.connect(self.update_sp_full_scale)
        self.spFullScaleEdit.setText(str(self.controller.get_sp_full_scale()))

        self.spSigtypeDropdown = QComboBox()
        self.spSigtypeDropdown.addItems(Controller.OUTPUT_PORT_TYPES.keys())
        self.spSigtypeDropdown.currentTextChanged.connect(
            self.update_sp_signal_type)
        self.spSigtypeDropdown.setCurrentText(
            str(self.controller.get_sp_signal_type()))

        self.spSourceDropdown = QComboBox()
        self.spSourceDropdown.addItems(Controller.SP_SOURCES.keys())
        self.spSourceDropdown.currentTextChanged.connect(self.update_source)
        self.spSourceDropdown.setCurrentText(str(self.controller.get_source()))

        self.decimalDropdown = QComboBox()
        self.decimalDropdown.addItems(Controller.DECIMAL_POINTS.keys())
        self.decimalDropdown.currentTextChanged.connect(
            self.update_decimal_point)
        self.decimalDropdown.setCurrentText(
            str(self.controller.get_decimal_point()))

        self.measureUnitsDropdown = QComboBox()
        self.measureUnitsDropdown.addItems(Controller.MEASUREMENT_UNITS.keys())
        self.measureUnitsDropdown.currentTextChanged.connect(
            self.update_measure_units)
        self.measureUnitsDropdown.setCurrentText(
            str(self.controller.get_measurement_units()))

        self.timebaseDropdown = QComboBox()
        self.timebaseDropdown.addItems(Controller.RATE_TIME_BASE.keys())
        self.timebaseDropdown.currentTextChanged.connect(self.update_time_base)
        self.timebaseDropdown.setCurrentText(
            str(self.controller.get_time_base()))

        processLayout.addRow(QLabel("Gas factor"), self.gasFactorEdit)
        processLayout.addRow(QLabel("PV Full Scale"), self.pvFullScaleEdit)
        processLayout.addRow(QLabel("PV Signal Type"), self.pvSigtypeDropdown)
        processLayout.addRow(QLabel("SP Full Scale"), self.spFullScaleEdit)
        processLayout.addRow(QLabel("SP Signal Type"), self.spSigtypeDropdown)
        processLayout.addRow(QLabel("Setpoint source"), self.spSourceDropdown)
        processLayout.addRow(QLabel("Decimal point"), self.decimalDropdown)
        processLayout.addRow(QLabel("Measurement units"),
                             self.measureUnitsDropdown)
        processLayout.addRow(QLabel("Time base"), self.timebaseDropdown)

        processGroup.setLayout(processLayout)
        processGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        leftColumnLayout.addWidget(processGroup, alignment=Qt.AlignTop)
        leftColumnLayout.setStretch(1, 100)

        runtimeGroup = QGroupBox("Runtime options")
        runtimeLayout = QVBoxLayout()

        layout = QHBoxLayout()

        self.bufferSizeEdit = QLineEdit()
        self.bufferSizeEdit.setText("64")
        self.bufferSizeEdit.setValidator(QIntValidator())
        self.bufferSizeEdit.editingFinished.connect(self.update_buffer_size)

        layout.addWidget(QLabel("Sample buffer size"))
        layout.addWidget(self.bufferSizeEdit)
        layout.addWidget(QLabel("samples"))

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.intervalEdit = QLineEdit()
        self.intervalEdit.setText("1")
        self.intervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.intervalEdit.editingFinished.connect(self.update_graph_timer)

        layout.addWidget(QLabel("Data update interval"))
        layout.addWidget(self.intervalEdit)
        layout.addWidget(QLabel("minutes"))

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.setpointEdit = QLineEdit()
        self.setpointEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.setpointEdit.editingFinished.connect(self.update_setpoint)
        self.setpointEdit.setText(str(self.controller.get_setpoint()))

        self.setpointUnitsLabel = QLabel(
            f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
        )

        layout.addWidget(QLabel("Setpoint"))
        layout.addWidget(self.setpointEdit)
        layout.addWidget(self.setpointUnitsLabel)

        runtimeLayout.addLayout(layout)

        layout = QHBoxLayout()

        manualMeasureButton = QPushButton("Get measurement")
        manualMeasureButton.clicked.connect(self.update_plot)
        self.saveCsvButton = QPushButton("Start saving to CSV")
        self.saveCsvButton.clicked.connect(self.save_to_csv_start)

        layout.addWidget(manualMeasureButton)
        layout.addWidget(self.saveCsvButton)

        runtimeLayout.addLayout(layout)

        runtimeGroup.setLayout(runtimeLayout)
        runtimeGroup.setMaximumWidth(ControllerGUITab.LEFT_COLUMN_MAX_WIDTH)
        runtimeGroup.setFixedHeight(150)

        leftColumnLayout.addWidget(runtimeGroup, alignment=Qt.AlignBottom)

        return leftColumnLayout

    def create_right_column(self):
        # Create layouts and elements for the right column, including graph and sensor/temperature control/dosing groups
        rightColumnLayout = QVBoxLayout()
        rightInnerGrid = QGridLayout()

        # Creation of sensor 1 and sub-elements
        self.sensor1Group = QGroupBox("Sensor 1")
        self.sensor1Group.setCheckable(True)
        self.sensor1Group.setChecked(False)
        self.sensor1Group.clicked.connect(self.update_sensor1_group)
        sensor1Layout = QVBoxLayout()

        layout = QHBoxLayout()

        self.sensor1SampleIntervalEdit = QLineEdit()
        self.sensor1SampleIntervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.sensor1SampleIntervalEdit.setFixedWidth(100)
        self.sensor1SampleIntervalEdit.editingFinished.connect(
            self.update_sensor1_timer)
        self.sensor1SampleIntervalEdit.setText("1")

        label = QLabel('Sampling interval')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor1SampleIntervalEdit)
        layout.addWidget(QLabel('minutes'))
        layout.setStretch(2, 10)
        sensor1Layout.addLayout(layout)

        layout = QHBoxLayout()

        self.sensor1BufferSizeEdit = QLineEdit()
        self.sensor1BufferSizeEdit.setValidator(QIntValidator())
        self.sensor1BufferSizeEdit.setFixedWidth(100)
        self.sensor1BufferSizeEdit.editingFinished.connect(
            self.update_sensor1_buffer)
        self.sensor1BufferSizeEdit.setText("64")

        label = QLabel('Buffer size')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor1BufferSizeEdit)
        layout.addWidget(QLabel('samples'))
        layout.setStretch(2, 10)
        sensor1Layout.addLayout(layout)
        self.sensor1Group.setLayout(sensor1Layout)

        # Creation of sensor 2 and sub-elements
        self.sensor2Group = QGroupBox("Sensor 2")
        self.sensor2Group.setCheckable(True)
        self.sensor2Group.setChecked(False)
        self.sensor2Group.clicked.connect(self.update_sensor2_group)
        sensor2Layout = QVBoxLayout()

        layout = QHBoxLayout()

        self.sensor2SampleIntervalEdit = QLineEdit()
        self.sensor2SampleIntervalEdit.setValidator(
            QRegExpValidator(QRegExp("[0-9]*(|\\.[0-9]*)")))
        self.sensor2SampleIntervalEdit.setFixedWidth(100)
        self.sensor2SampleIntervalEdit.editingFinished.connect(
            self.update_sensor2_timer)
        self.sensor2SampleIntervalEdit.setText("1")

        label = QLabel('Sampling interval')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor2SampleIntervalEdit)
        layout.addWidget(QLabel('minutes'))
        layout.setStretch(2, 10)
        sensor2Layout.addLayout(layout)

        layout = QHBoxLayout()

        self.sensor2BufferSizeEdit = QLineEdit()
        self.sensor2BufferSizeEdit.setValidator(QIntValidator())
        self.sensor2BufferSizeEdit.setFixedWidth(100)
        self.sensor2BufferSizeEdit.editingFinished.connect(
            self.update_sensor2_buffer)
        self.sensor2BufferSizeEdit.setText("64")

        label = QLabel('Buffer size')
        label.setFixedWidth(90)
        layout.addWidget(label)
        layout.addWidget(self.sensor2BufferSizeEdit)
        layout.addWidget(QLabel('samples'))
        layout.setStretch(2, 10)
        sensor2Layout.addLayout(layout)
        self.sensor2Group.setLayout(sensor2Layout)

        self.tempControllerGroup = QGroupBox("Temperature controller")
        self.tempControllerGroup.setCheckable(True)
        self.tempControllerGroup.setEnabled(
            False)  # Disabled functionality as it is untested
        self.tempControllerGroup.setChecked(False)
        self.tempControllerGroup.clicked.connect(self.update_temperature_group)
        tempControllerLayout = QVBoxLayout()

        layout = QHBoxLayout()

        self.temperatureSlider = QSlider(Qt.Horizontal)
        self.temperatureSlider.setMinimumWidth(95)
        self.temperatureSlider.setMaximumWidth(1000)
        self.temperatureSlider.setMinimum(-199.9)
        self.temperatureSlider.setMaximum(850.0)
        self.temperatureSlider.setValue(100)
        self.temperatureSlider.sliderMoved.connect(self.update_temperature)
        self.temperatureLabel = QLabel("100")
        layout.addWidget(QLabel("Temperature"), alignment=Qt.AlignLeft)
        layout.addWidget(self.temperatureSlider, alignment=Qt.AlignLeft)
        layout.addWidget(self.temperatureLabel, alignment=Qt.AlignLeft)
        layout.addWidget(QLabel("℃"), alignment=Qt.AlignLeft)

        layout.setStretch(3, 200)
        tempControllerLayout.addLayout(layout)

        # these edits have validators, but input still has to be capped
        layout = QHBoxLayout()
        self.rangeLowEdit = QLineEdit()
        self.rangeLowEdit.setMinimumWidth(30)
        self.rangeLowEdit.setMaximumWidth(60)
        self.rangeLowEdit.setText("-199.9")
        self.rangeLowEdit.setValidator(
            QRegExpValidator(
                QRegExp("(-[0-9]{1,3}\\.[0-9]|[0-9]{1,3}\\.[0-9|[0-9]{1,4})")))
        self.rangeLowEdit.editingFinished.connect(self.update_range_low)

        self.rangeHighEdit = QLineEdit()
        self.rangeHighEdit.setMinimumWidth(30)
        self.rangeHighEdit.setMaximumWidth(60)
        self.rangeHighEdit.setText("850.0")
        self.rangeHighEdit.setValidator(
            QRegExpValidator(
                QRegExp("(-[0-9]{1,3}\\.[0-9]|[0-9]{1,3}\\.[0-9|[0-9]{1,4})")))
        self.rangeHighEdit.editingFinished.connect(self.update_range_high)

        layout.addWidget(QLabel("Range"))
        layout.addWidget(self.rangeLowEdit, alignment=Qt.AlignLeft)
        layout.addWidget(self.rangeHighEdit, alignment=Qt.AlignLeft)
        layout.addWidget(QLabel("℃"))
        layout.setStretch(3, 10)
        tempControllerLayout.addLayout(layout)

        self.rampingCheckbox = QCheckBox()
        self.rampingCheckbox.stateChanged.connect(self.update_ramping_enable)

        self.tempReadoutLabel = QLabel("Readout: None ℃")

        layout = QHBoxLayout()
        layout.addWidget(QLabel("Ramping"), alignment=Qt.AlignLeft)
        layout.addWidget(self.rampingCheckbox, alignment=Qt.AlignLeft)
        layout.addWidget(self.tempReadoutLabel, alignment=Qt.AlignBottom)
        layout.setStretch(1, 10)

        tempControllerLayout.addLayout(layout)

        layout = QHBoxLayout()

        self.gradientEdit = QLineEdit()
        self.gradientEdit.setMinimumWidth(30)
        self.gradientEdit.setMaximumWidth(60)
        self.gradientEdit.setText("0.1")  # default value from the datasheet
        self.gradientEdit.editingFinished.connect(self.update_gradient)

        self.tempControlButton = QPushButton("Enable output")
        self.tempControlButton.setCheckable(True)
        self.tempControlButton.clicked.connect(self.update_temp_control_enable)

        layout.addWidget(QLabel("Gradient"), alignment=Qt.AlignLeft)
        layout.addWidget(self.gradientEdit, alignment=Qt.AlignLeft)
        layout.addWidget(QLabel("℃/min"))
        layout.addWidget(self.tempControlButton, alignment=Qt.AlignBottom)
        layout.setStretch(2, 10)

        tempControllerLayout.addLayout(layout)

        self.tempControllerGroup.setLayout(tempControllerLayout)
        self.tempControllerGroup.setMinimumWidth(200)
        self.tempControllerGroup.setFixedHeight(150)

        dosingGroup = QGroupBox("Dosing control")
        dosingGroup.setCheckable(False)
        dosingLayout = QVBoxLayout()

        layout = QHBoxLayout()
        self.dosingTimesEdit = QLineEdit()
        self.dosingTimesEdit.setMinimumWidth(160)
        self.dosingTimesEdit.setText("1, 1, 1.5")
        self.dosingTimesEdit.setValidator(
            QRegExpValidator(QRegExp("(([0-9]+|[0-9]+\\.[0-9]+),(| ))+")))
        self.dosingTimesEdit.textChanged.connect(self.update_dosing_vectors)

        label = QLabel("Times")
        label.setFixedWidth(55)

        layout.addWidget(label)
        layout.addWidget(self.dosingTimesEdit)
        layout.addWidget(QLabel("minutes"))
        dosingLayout.addLayout(layout)

        layout = QHBoxLayout()
        self.dosingValuesEdit = QLineEdit()
        self.dosingValuesEdit.setMinimumWidth(160)
        self.dosingValuesEdit.setText("1.0, 2.0, 5.0")
        self.dosingValuesEdit.setValidator(
            QRegExpValidator(QRegExp("(([0-9]+|[0-9]+\\.[0-9]+),(| ))+")))
        self.dosingValuesEdit.textChanged.connect(self.update_dosing_vectors)

        label = QLabel("Setpoints")
        label.setFixedWidth(55)

        self.dosingUnitsLabel = QLabel(
            f"{self.measureUnitsDropdown.currentText()}/{self.timebaseDropdown.currentText()}"
        )

        layout.addWidget(label)
        layout.addWidget(self.dosingValuesEdit)
        layout.addWidget(self.dosingUnitsLabel)
        dosingLayout.addLayout(layout)

        self.dosingLabel = QLabel("Dosing disabled")

        self.dosingVorStateLabel = QLabel(
            f"VOR is {self.controller.get_valve_override().lower()}")

        if "normal" in self.dosingVorStateLabel.text():
            self.dosingVorStateLabel.setStyleSheet("color: green")
        else:
            self.dosingVorStateLabel.setStyleSheet("color: red")

        self.dosingControlButton = QPushButton("Start dosing")
        self.dosingControlButton.setCheckable(True)
        self.dosingControlButton.clicked.connect(self.update_dosing_state)

        dosingLayout.addWidget(self.dosingLabel, alignment=Qt.AlignLeft)
        layout = QHBoxLayout()
        layout.addWidget(self.dosingVorStateLabel, alignment=Qt.AlignLeft)
        layout.addWidget(self.dosingControlButton, alignment=Qt.AlignRight)

        dosingLayout.addLayout(layout)

        # finally, assign the layout to the group
        dosingGroup.setLayout(dosingLayout)
        dosingGroup.setMinimumWidth(200)
        dosingGroup.setFixedHeight(150)

        rightInnerGrid.addWidget(self.sensor1Group, 0, 0)
        rightInnerGrid.addWidget(self.sensor2Group, 0, 1)
        rightInnerGrid.addWidget(self.tempControllerGroup, 1, 0)
        rightInnerGrid.addWidget(dosingGroup, 1, 1)

        rightInnerGrid.setColumnStretch(0, 100)
        rightInnerGrid.setColumnStretch(1, 100)

        self.graph = PlotWidget()
        self.graph.getPlotItem().showGrid(x=True, y=True, alpha=1)
        if "qdarkstyle" in sys.modules:
            self.graph.setBackground((25, 35, 45))

        rightColumnLayout.addWidget(self.graph)
        rightColumnLayout.addLayout(rightInnerGrid)

        return rightColumnLayout

    # function to change the amount of stored samples without losing previously gathered samples
    def change_buffer_size(self, value):
        if value > self.sampleBufferSize:
            newBufPV = RingBuffer(capacity=value, dtype=np.float16)
            newBufTotal = RingBuffer(capacity=value, dtype=np.float32)
            newTimestampBuf = RingBuffer(capacity=value, dtype=datetime)

            newBufPV.extend(self.samplesPV)
            newBufTotal.extend(self.samplesTotalizer)
            newTimestampBuf.extend(self.sampleTimestamps)

            self.samplesPV = newBufPV
            self.samplesTotalizer = newBufTotal
            self.sampleTimestamps = newTimestampBuf
        elif value < self.sampleBufferSize:
            newBufPV = RingBuffer(capacity=value, dtype=np.float16)
            newBufTotal = RingBuffer(capacity=value, dtype=np.float32)
            newTimestampBuf = RingBuffer(capacity=value, dtype=datetime)

            newBufPV.extend(self.samplesPV[:-value])
            newBufTotal.extend(self.samplesTotalizer[:-value])
            newTimestampBuf.extend(self.sampleTimestamps[:-value])

            self.samplesPV = newBufPV
            self.samplesTotalizer = newBufTotal
            self.sampleTimestamps = newTimestampBuf
Exemple #27
0
class widget_mfi_lon_plot(QWidget):

    #-----------------------------------------------------------------------
    # DEFINE THE INITIALIZATION FUNCTION.
    #-----------------------------------------------------------------------

    def __init__(self, core):

        # Inherit all attributes of an instance of "QWidget".

        super(widget_mfi_lon_plot, self).__init__()

        # Store the Janus core.

        self.core = core

        # Prepare to respond to signals received from the core.

        self.connect(self.core, SIGNAL('janus_rset'), self.resp_rset)
        self.connect(self.core, SIGNAL('janus_chng_mfi'), self.resp_chng_mfi)

        # Initialize this widget's instance of "PlotWidget", which will
        # contain the plot of MFI magnetic field data.

        # Note.  The "QGridLayout" object given to this widget as its
        #        layout is essentially a dummy.  I could have just had
        #        this class inherit "PlotWidget", but I think that this
        #        gives me a bit more control (and a similar structure
        #        "janus_widget_fc_cup").

        self.setLayout(QGridLayout())

        self.plt = PlotWidget()
        self.layout().addWidget(self.plt)

        self.layout().setContentsMargins(0, 0, 0, 0)

        # Extract the individual elements of the "PlotWidget" object
        # (e.g., it's axes) for more convenient access later.

        self.vbx = self.plt.getViewBox()

        self.axs_x = self.plt.getAxis('bottom')
        self.axs_y = self.plt.getAxis('left')

        self.ptm = self.plt.getPlotItem()

        # Initialize and store the pens and fonts.

        self.pen_vbx = mkPen(color='k')
        self.pen_crv_lon = mkPen(color='#FFD700')

        self.fnt = self.core.app.font()

        # Configure the plot: disable automatic adjustments and
        # adjustments made by the user, change the background and
        # foreground colors, enable grid lines for both axes, label the
        # axes, adjust the tick font size, adjust the "AxisItem" sizes,
        # and add a margin around the entire plot.

        self.plt.disableAutoRange()
        self.plt.setMouseEnabled(False, False)
        self.plt.setMenuEnabled(False)
        self.plt.hideButtons()

        self.plt.setBackground('w')
        setConfigOption('foreground', 'k')

        #####self.plt.showGrid( True, True )

        labelStyle = {'color': 'k'}
        self.axs_x.setLabel('Time [s]', **labelStyle)
        self.axs_y.setLabel('Azim. [deg]', **labelStyle)

        self.axs_x.label.setFont(self.fnt)
        self.axs_y.label.setFont(self.fnt)

        self.axs_x.setTickFont(self.fnt)
        self.axs_y.setTickFont(self.fnt)

        self.axs_x.setHeight(35)
        self.axs_y.setWidth(40)

        self.vbx.border = self.pen_vbx

        self.ptm.setContentsMargins(5, 5, 5, 5)

        # Initialize the curves that will be added to this plot.

        self.crv_lon = None

        # Populate this plot and adjust it's settings.

        self.make_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR POPULATING THE PLOT.
    #-----------------------------------------------------------------------

    def make_plt(self):

        # Reset the plot (i.e., remove all plot elements).

        self.rset_plt()

        # Establish the ranges of its time and magnetic field values.
        # If the core contains no data or only a single datum,
        # improvise (for the purpose of later establishing axis limits).

        if (self.core.n_mfi >= 1):

            # Establish the domain of the plot.

            t_min = min(amin(self.core.mfi_s), 0.)
            t_max = max(amax(self.core.mfi_s), self.core.fc_spec['dur'])

            # Establish the range of the plot.  As part of this,
            # ensure that the range satisfies a minimum size and has
            # sufficient padding.

            ang_max = max(self.core.mfi_b_lon)
            ang_min = min(self.core.mfi_b_lon)

            ang_max = 5. + ang_max
            ang_min = -5. + ang_min

            d_t_0 = t_max - t_min

            d_t = max(1.5 + d_t_0, 3.)

            t_max = t_min + d_t

        else:

            t_min = 0.001
            t_max = 3.500

            ang_min = -360
            ang_max = 360

        # Set the range of the axis of each plot.

        self.plt.setXRange(t_min, t_max, padding=0.0)
        self.plt.setYRange(ang_min, ang_max, padding=0.0)

        # If the core contains no Wind/MFI magnetic field data, return.

        if (self.core.n_mfi <= 0):
            return

        # Generate and display each curve for the plot.

        self.crv_lon = PlotDataItem(self.core.mfi_s,
                                    self.core.mfi_b_lon,
                                    pen=self.pen_crv_lon)

        self.plt.addItem(self.crv_lon)

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESETTING THIS PLOT (CLEARING ALL ELEMENTS).
    #-----------------------------------------------------------------------

    def rset_plt(self):

        # Hide and remove each of this plot's elements.

        if (self.crv_lon is not None):
            self.plt.removeItem(self.crv_lon)

        # Permanently delete this plot's elements by setting each of the
        # variables that store them to "None".

        self.crv_lon = None

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "rset" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_rset(self):

        # Reset the plot.

        self.rset_plt()

    #-----------------------------------------------------------------------
    # DEFINE THE FUNCTION FOR RESPONDING TO THE "chng_mfi" SIGNAL.
    #-----------------------------------------------------------------------

    def resp_chng_mfi(self):

        # Regenerate the plot.

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

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

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

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

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

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

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

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

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

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

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

        QtCore.QMetaObject.connectSlotsByName(MainWindow)

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

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

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

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

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

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

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

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

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

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

    def clickeddrawgraph(self):
        global axis_Position, axis_Velocity
        pen = pg.mkPen(color=(255, 0, 0), width=3)
        self.Velocity_graph.plot(time, axis_Velocity, pen=pen)
        self.Position_graph.plot(time, axis_Position, pen=pen)
class PyQtGraphDataPlot(QWidget):

    limits_changed = Signal()

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

        self._curves = {}
        self._current_vline = None

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

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

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

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

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

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

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

    def get_ylim(self):
        _, y_range = self._plot_widget.viewRange()
        return y_range
class 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")
Exemple #31
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
Exemple #32
0
class ComplicatedTestResultsDialog(QMainWindow):
    def __init__(self, parent=None, methods=None, vertices_amounts=None, samples_amount=None, name_1=None, name_2=None):
        super(ComplicatedTestResultsDialog, self).__init__(parent)
        self.parent_window = parent
        self.setWindowTitle("Grismo - Wyniki dla testu wpływu liczby " + name_1)
        self.setMinimumWidth(630)
        self.setMinimumHeight(800)
        self.setMaximumHeight(900)
        self.methods = methods
        self.results_count = 0
        self.start_vertices = vertices_amounts[0]
        self.all_vertices_amount = len(vertices_amounts)
        self.samples_amount = samples_amount
        # store all results to calculate means
        self.all_results = []

        central = QWidget()
        self.setCentralWidget(central)
        central_layout = QVBoxLayout()
        central.setLayout(central_layout)

        # plot box
        plot_label = QLabel("Wykres dla wszystkich testów:")
        central_layout.addWidget(plot_label)
        self.plot_log_mode = False
        self.results_plot = PlotWidget()
        self.results_plot.setLogMode(False, self.plot_log_mode)
        self.results_plot.setBackground('w')
        self.results_plot.setTitle("Badanie wpływu liczby " + name_1 + " na czas testu")
        self.results_plot.setLabel('left', 'Czas obliczeń [s]', color='k', size=10)
        self.results_plot.setLabel('bottom', 'Liczba ' + name_1, color='k', size=10)
        self.results_plot.setXRange(self.start_vertices, vertices_amounts[-1])
        self.results_plot.setMaximumWidth(600)
        self.results_plot.showGrid(y=True)
        central_layout.addWidget(self.results_plot)

        switch_plot_log_button = QPushButton("Zmień skalę osi Y (logarytmiczna/liniowa)")
        switch_plot_log_button.setCheckable(False)
        switch_plot_log_button.clicked.connect(self.switch_plot_log)
        central_layout.addWidget(switch_plot_log_button)

        # prepare plot lines
        self.plot_data = []
        method_colors = ['k', 'b', 'g', 'r', 'y']
        self.results_plot.plot([], [], name="")
        self.results_plot.addLegend()
        for method_index in range(len(self.methods)):
            method_name = self.methods[method_index]
            method_color = method_colors[method_index]
            pen = mkPen(color=method_color, width=2)
            self.plot_data.append(self.results_plot.plot([], [], name=method_name, pen=pen, symbol='+', symbolSize=10,
                                                         symbolBrush=method_color))
            self.results_plot.addLegend()

        # tables box
        tables_box = QScrollArea(self)
        tables_box.setWidgetResizable(True)
        tables_box_content = QWidget(tables_box)
        tables_box_layout = QVBoxLayout(tables_box_content)
        tables_box_content.setLayout(tables_box_layout)
        tables_box.setWidget(tables_box_content)
        central_layout.addWidget(tables_box)

        # for each vertices_amount prepare table: label -> table -> label -> progress_bar
        self.results_tables = []
        self.results_progress_bars = []
        bold_font = QFont()
        bold_font.setBold(True)
        for i in vertices_amounts:
            vertices_label = QLabel("Wyniki dla grafów o  " + str(i) + " " + name_2 + ":")
            vertices_label.setFont(bold_font)
            results_table = QTableWidget()
            results_table.setRowCount(len(methods))
            results_table.setColumnCount(4)
            results_table.setColumnWidth(1, 150)
            results_table.setColumnWidth(2, 150)
            results_table.setMinimumHeight((len(methods) + 1) * 30)
            results_table.setHorizontalHeaderLabels(["Metoda", "Wyniki pozytywne", "Wyniki negatywne",
                                                     "Średni czas [s]"])
            progress_label = QLabel("Postęp:")
            results_progress_bar = QProgressBar()
            results_progress_bar.setValue(0)

            self.results_tables.append(results_table)
            self.results_progress_bars.append(results_progress_bar)
            tables_box_layout.addWidget(vertices_label)
            tables_box_layout.addWidget(results_table)
            tables_box_layout.addWidget(progress_label)
            tables_box_layout.addWidget(results_progress_bar)

            self.all_results.append([])

            for method_index in range(len(methods)):
                method_title = methods[method_index]
                results_table.setItem(method_index, 0, QTableWidgetItem(method_title))
                self.all_results[-1].append([])

    def add_result(self, result, vertices_amount, sample_number):
        # result: [method, decision, time]

        # vertices table index
        table_index = vertices_amount - self.start_vertices

        # method index
        method_index = self.methods.index(result[0])

        # add result to all stored results
        self.all_results[table_index][method_index].append(result)

        # positive and negatives
        # firstly extract 2nd column from results matrix
        new_positives = sum([row[1] for row in self.all_results[table_index][method_index]])
        new_negatives = len(self.all_results[table_index][method_index]) - new_positives

        self.results_tables[table_index].setItem(method_index, 1, QTableWidgetItem(str(new_positives)))
        self.results_tables[table_index].setItem(method_index, 2, QTableWidgetItem(str(new_negatives)))

        # mean
        new_mean = mean([row[2] for row in self.all_results[table_index][method_index]])
        self.results_tables[table_index].setItem(method_index, 3, QTableWidgetItem(str(new_mean)))

        # progress_bar
        self.results_progress_bars[table_index].setValue(sample_number / self.samples_amount * 100)
        self.results_count = self.results_count + 1

        # update plot
        self.update_plot()

    def update_plot(self):
        for method_index in range(len(self.methods)):
            # for this method find all mean values
            x = []
            y = []
            for vertices_index in range(self.all_vertices_amount):
                vertices_amount = vertices_index + self.start_vertices
                if len(self.all_results[vertices_index][method_index]):
                    x.append(vertices_amount)
                    y.append(mean([row[2] for row in self.all_results[vertices_index][method_index]]))
            self.plot_data[method_index].setData(x, y)

    def switch_plot_log(self):
        self.plot_log_mode = not self.plot_log_mode
        self.results_plot.setLogMode(False, self.plot_log_mode)

    def closeEvent(self, event):
        self.parent_window.stop_test = True
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"))
Exemple #34
0
class RealtimePlotWidget(QWidget):
    AUTO_RANGE_FRACTION = 0.99

    COLORS = [Qt.red, Qt.blue, Qt.green, Qt.magenta, Qt.cyan,
              Qt.darkRed, Qt.darkBlue, Qt.darkGreen, Qt.darkYellow, Qt.gray]

    def __init__(self, display_measurements, parent):
        super(RealtimePlotWidget, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)              # This is required to stop background timers!
        self._plot_widget = PlotWidget()
        self._plot_widget.setBackground((0, 0, 0))
        self._legend = self._plot_widget.addLegend()
        self._plot_widget.showButtons()
        self._plot_widget.showGrid(x=True, y=True, alpha=0.3)
        vbox = QVBoxLayout(self)
        vbox.addWidget(self._plot_widget)
        self.setLayout(vbox)

        self._last_update_ts = 0
        self._reset_required = False

        self._update_timer = QTimer(self)
        self._update_timer.setSingleShot(False)
        self._update_timer.timeout.connect(self._update)
        self._update_timer.start(200)

        self._color_index = 0
        self._curves = {}

        # Crosshair
        def _render_measurements(cur, ref):
            text = 'time %.6f sec,  y %.6f' % cur
            if ref is None:
                return text
            dt = cur[0] - ref[0]
            dy = cur[1] - ref[1]
            if abs(dt) > 1e-12:
                freq = '%.6f' % abs(1 / dt)
            else:
                freq = 'inf'
            display_measurements(text + ';' + ' ' * 4 + 'dt %.6f sec,  freq %s Hz,  dy %.6f' % (dt, freq, dy))

        display_measurements('Hover to sample Time/Y, click to set new reference')
        add_crosshair(self._plot_widget, _render_measurements)

        # Final reset
        self.reset()

    def _trigger_auto_reset_if_needed(self):
        ts = time.monotonic()
        dt = ts - self._last_update_ts
        self._last_update_ts = ts
        if dt > 2:
            self._reset_required = True

    def add_curve(self, curve_id, curve_name, data_x=[], data_y=[]):
        color = QColor(self.COLORS[self._color_index % len(self.COLORS)])
        self._color_index += 1
        pen = mkPen(color, width=1)
        plot = self._plot_widget.plot(name=curve_name, pen=pen)
        data_x = numpy.array(data_x)
        data_y = numpy.array(data_y)
        self._curves[curve_id] = {'data': (data_x, data_y), 'plot': plot}
        self._trigger_auto_reset_if_needed()

    def update_values(self, curve_id, x, y):
        curve = self._curves[curve_id]
        old_x, old_y = curve['data']
        curve['data'] = numpy.append(old_x, x), numpy.append(old_y, y)
        self._trigger_auto_reset_if_needed()

    def reset(self):
        for curve in self._curves.keys():
            self._plot_widget.removeItem(self._curves[curve]['plot'])

        self._curves = {}
        self._color_index = 0

        self._plot_widget.enableAutoRange(enable=self.AUTO_RANGE_FRACTION,
                                          x=self.AUTO_RANGE_FRACTION,
                                          y=self.AUTO_RANGE_FRACTION)

        self._legend.scene().removeItem(self._legend)
        self._legend = self._plot_widget.addLegend()

    def _update(self):
        if self._reset_required:
            self.reset()
            self._reset_required = False

        for curve in self._curves.values():
            if len(curve['data'][0]):
                curve['plot'].setData(*curve['data'])