Exemple #1
0
class ChartView(QChartView):
    def __init__(self):
        QChartView.__init__(self)
        #self.resize(300, 300)
        self.setRenderHint(QPainter.Antialiasing)  # 抗锯齿
        self.chart = QChart()
        self.seriesAcc = QLineSeries()
        self.seriesAcc.setName(CONF.leftUpNames[0])
        self.chart.addSeries(self.seriesAcc)
        #声明并初始化X轴,Y轴
        self.dtaxisX = QValueAxis()
        self.vlaxisY = QValueAxis()
        #设置坐标轴显示范围
        self.dtaxisX.setMin(0)
        #self.dtaxisX.setMax(100)
        self.vlaxisY.setMin(0)
        #self.vlaxisY.setMax(100)
        self.dtaxisX.setTickCount(3)
        self.vlaxisY.setTickCount(3)
        #设置坐标轴名称
        self.dtaxisX.setTitleText(CONF.leftUpNames[1])
        self.vlaxisY.setTitleText(CONF.leftUpNames[2])
        #设置网格不显示
        self.vlaxisY.setGridLineVisible(False)
        #把坐标轴添加到chart中
        self.chart.addAxis(self.dtaxisX, Qt.AlignBottom)
        self.chart.addAxis(self.vlaxisY, Qt.AlignLeft)

        self.seriesAcc.attachAxis(self.dtaxisX)
        self.seriesAcc.attachAxis(self.vlaxisY)

        self.initUI()

    def initUI(self):
        self.backend = BackendThread()
        self.backend.update_line.connect(self.handleLine)
        self.backend.start()

    def handleLine(self, data):
        if data[0] == 0:
            self.seriesAcc.clear()
        else:
            self.dtaxisX.setMax(data[0])
            self.vlaxisY.setMax(data[0])
            self.seriesAcc.clear()
            self.seriesAcc.append(0, 0)
            self.seriesAcc.append(data[0], data[1])

        self.setChart(self.chart)
Exemple #2
0
class Simulator(QtWidgets.QMainWindow, gui.Ui_MainWindow):
    def __init__(self):
        super().__init__()

        self.__car = car.motion()
        self.__car.param.fromJSON(car.defaultParams())
        self.__canbus = None

        self.__translator = QTranslator(self)

        self.setupUi(self)

        self.positionChart = QChart()
        self.positionSeries = QLineSeries()        

        self.speedChart = QChart()
        self.speedSeries = QLineSeries()

        self.fuelChart = QChart()
        self.fuelSeries = QLineSeries()

        self.engineChart = QChart()
        self.engineSeries = QLineSeries()

        self.positionChart.addSeries(self.positionSeries)
        self.speedChart.addSeries(self.speedSeries)
        self.fuelChart.addSeries(self.fuelSeries)
        self.engineChart.addSeries(self.engineSeries)

        self.positionChart.legend().hide()
        self.speedChart.legend().hide()
        self.fuelChart.legend().hide()
        self.engineChart.legend().hide()   

        self.positionChart.createDefaultAxes()
        self.speedChart.createDefaultAxes()
        self.fuelChart.createDefaultAxes()
        self.engineChart.createDefaultAxes()
        
        self.positionChart.setTitle("Position")
        self.speedChart.setTitle("Speed")
        self.fuelChart.setTitle("Fuel")
        self.engineChart.setTitle("Engine")

        self.positionChart.setMargins(QMargins())
        self.speedChart.setMargins(QMargins())
        self.fuelChart.setMargins(QMargins())
        self.engineChart.setMargins(QMargins())

        self.positionChartW.setChart(self.positionChart)
        self.speedChartW.setChart(self.speedChart)
        self.fuelChartW.setChart(self.fuelChart)
        self.engineChartW.setChart(self.engineChart)

        self.populateFields()

        for file in os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lang')):
            if file.startswith('carSim_') and file.endswith('.qm'):
                self.langSelector.addItem(file[7:-3])

    def changeEvent(self, event):
        if event.type() == QEvent.LanguageChange:
            self.retranslateUi(self)
        super().changeEvent(event)

    @pyqtSlot(str)
    def on_langSelector_currentTextChanged(self, lang):
        if lang:
            self.__translator.load(QLocale(lang), 'carSim', '_', 'lang', '.qm')
            QtWidgets.QApplication.instance().installTranslator(self.__translator)
        else:
            QtWidgets.QApplication.instance().removeTranslator(self.__translator)
    
    @pyqtSlot()
    def on_resetSimulationButton_clicked(self):
        self.__car = car.motion()
        self.__car.param.fromJSON(car.defaultParams())

        self.positionSeries.clear()
        self.speedSeries.clear()
        self.fuelSeries.clear()
        self.engineSeries.clear()

        self.populateFields()

    @pyqtSlot()
    def on_makeStepButton_clicked(self):
        try:
            # self.__car.setThrottle(self.engineField.text())
            self.__car.makeStep()
            # motionMessage=can.Message(arbitration_id=18,is_extended_id=False,data=self.__car.getCanBytes()[:])
            motionMessage = car.canMsg(
                StdId=18, Data=self.__car.getCanBytes()[:])
            print(motionMessage)
            if (self.__canbus is not None and self.__canbus.connected == True):
                self.__canbus.sendMsg(motionMessage)
            with open('log.dat', 'a') as outfile:
                outfile.write("%.1f\t%f\t%f\t%f\n" % (self.__car.getSimTime(),
                                                      self.__car.getSimDistance(), self.__car.getSimSpeed(), self.__car.getSimFuel()))
        except Exception as e:
            QtWidgets.QMessageBox.warning(
                self, _translate("Dialog", "Error"), str(e))

        self.populateFields()
        if float(self.timeField.text()) >= 240:
            if self.simulationStart.isChecked() == True:
                self.simulationStart.click()

    def populateFields(self):
        self.timeField.setText(f"{self.__car.getSimTime():.2f}")
        self.positionField.setText(f"{self.__car.getSimDistance():.2f}")
        self.speedField.setText(f"{self.__car.getSimSpeed():.2f}")
        self.fuelField.setText(f"{self.__car.getSimFuel():.2f}")
        if (self.__canbus is not None and self.__canbus.connected == True):
            self.engineField.setText(f"{self.__car.getThrottle():.2f}")

        xax = self.positionChart.axisX()

        if(self.__car.getSimTime()>self.positionChart.axisX().max()):
            self.positionChart.axisX().setMax(self.__car.getSimTime())
            self.speedChart.axisX().setMax(self.__car.getSimTime())
            self.fuelChart.axisX().setMax(self.__car.getSimTime())
            self.engineChart.axisX().setMax(self.__car.getSimTime())
        #elif(self.__car.getSimTime()<self.positionChart.axisX().min()):
        #    self.positionChart.axisX().setMin(self.__car.getSimTime())
        #    self.speedChart.axisX().setMin(self.__car.getSimTime())
        #    self.fuelChart.axisX().setMin(self.__car.getSimTime())
        #    self.engineChart.axisX().setMin(self.__car.getSimTime())

        if(self.__car.getSimDistance()>self.positionChart.axisY().max()):
            self.positionChart.axisY().setMax(self.__car.getSimDistance())
        elif(self.__car.getSimSpeed()<self.speedChart.axisY().min()):
            self.positionChart.axisY().setMin(self.__car.getSimDistance())

        if(self.__car.getSimSpeed()>self.speedChart.axisY().max()):
            self.speedChart.axisY().setMax(self.__car.getSimSpeed())
        elif(self.__car.getSimSpeed()<self.speedChart.axisY().min()):
            self.speedChart.axisY().setMin(self.__car.getSimSpeed())

        if(self.__car.getSimFuel()>self.fuelChart.axisY().max()):
            self.fuelChart.axisY().setMax(self.__car.getSimFuel())
        elif(self.__car.getSimFuel()<self.fuelChart.axisY().min()):
            self.fuelChart.axisY().setMin(self.__car.getSimFuel())

        self.positionSeries.append(self.__car.getSimTime(),self.__car.getSimDistance())
        self.speedSeries.append(self.__car.getSimTime(),self.__car.getSimSpeed())
        self.fuelSeries.append(self.__car.getSimTime(),self.__car.getSimFuel())
        self.engineSeries.append(self.__car.getSimTime(),self.__car.getThrottle())

    @pyqtSlot(str)
    def on_engineField_textEdited(self,newEngineValue):
        try:
            self.__car.setThrottle(newEngineValue)
        except:
            pass

    @pyqtSlot()
    def on_actionAbout_triggered(self):
        self.AboutDialog = QtWidgets.QDialog()
        self.AboutDialog.ui = gui.Ui_AboutDialog()
        self.AboutDialog.ui.setupUi(self.AboutDialog)
        self.AboutDialog.setAttribute(Qt.WA_DeleteOnClose)
        self.AboutDialog.exec_()

    @pyqtSlot()
    def on_actionExport_Settings_triggered(self):
        filename, _ = QtWidgets.QFileDialog.getSaveFileName(
            self, _translate("Dialog", "Save Config"), ".", filter=_translate("Dialog", "Config Files (*.json)")+";;"+_translate("Dialog", "All Files(*.*)"))
        if filename:
            fp = open(filename, 'w')
            self.__car.param.toJSON(file=fp)
            fp.close()

    @pyqtSlot()
    def on_actionImport_Settings_triggered(self):
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, _translate("Dialog", "Open Config"), ".", filter=_translate("Dialog", "Config Files (*.json)")+";;"+_translate("Dialog", "All Files(*.*)"))
        if filename:
            fp = open(filename, 'r')
            self.__car.param.fromJSON(fp)
            fp.close()

    @pyqtSlot()
    def on_refreshAvailablePorts_clicked(self):
        ports = serial.tools.list_ports.comports()
        self.availablePorts.clear()
        for port, desc, hwid in sorted(ports):
            self.availablePorts.addItem(desc, port)

    @pyqtSlot(bool)
    def on_connectPort_clicked(self, state):
        if state:
            try:
                self.__canbus = car.myCan(self.availablePorts.currentData(), [
                                          self.canReceived.appendPlainText], [
                                          self.__car.setSwitchingPoint], loopTime=0.025)
                self.__watch = QTimer(self)
                self.__watch.setInterval(1000)
                self.__watch.timeout.connect(self.syncTime)
                self.__watch.start()
            except Exception as e:
                self.connectPort.setChecked(False)
                QtWidgets.QMessageBox.critical(
                    self, _translate("Dialog", "Error"), str(e))
            else:
                self.connectPort.setText(
                    _translate("MainWindow", "Disconnect"))
                self.canInterfaceTypes.setEnabled(False)
                self.availablePorts.setEnabled(False)
                self.refreshAvailablePorts.setEnabled(False)

        else:
            self.connectPort.setText(_translate("MainWindow", "Connect"))
            self.__canbus = None
            del(self.__watch)
            self.canInterfaceTypes.setEnabled(True)
            self.availablePorts.setEnabled(True)
            self.refreshAvailablePorts.setEnabled(True)

    @pyqtSlot()
    def syncTime(self):
        self.__canbus.sendMsg(car.canMsg(StdId=0, Data=int(
            self.__car.getSimTime()*1000.0).to_bytes(4, 'little')))

    @pyqtSlot(bool)
    def on_simulationStart_clicked(self, state):
        if state:
            self.__ticker = QTimer(self)
            self.__ticker.setInterval(100)
            self.__ticker.timeout.connect(self.on_makeStepButton_clicked)
            self.__ticker.start()
            self.__car.setThrottle(1)
            self.simulationStart.setText(
                _translate("MainWindow", "Stop Simulation!"))
            lapData = 1
            with open('log.dat', 'a') as outfile:
                outfile.write("%.1f\t%f\t%f\t%f\n" % (self.__car.getSimTime(),
                                                      self.__car.getSimDistance(), self.__car.getSimSpeed(), self.__car.getSimFuel()))
        

        else:
            self.__ticker.stop()
            self.simulationStart.setText(
                _translate("MainWindow", "Start Simulation!"))
            lapData = 0

        lapMessage = car.canMsg(StdId=32, Data=[lapData])
        print(lapMessage)
        
        if (self.__canbus is not None and self.__canbus.connected == True):
            self.__canbus.sendMsg(lapMessage)
Exemple #3
0
class Chart(QWidget):
    def __init__(self, ch0Name='ch0', ch1Name='ch1', ch2Name='ch2', ch3Name='ch3'):
        super(Chart, self).__init__()
        self.ch0Name = ch0Name
        self.ch1Name = ch1Name
        self.ch2Name = ch2Name
        self.ch3Name = ch3Name
        self.data = []
        self.initUI()

    def initUI(self):
        vbox = QVBoxLayout()
        vbox.addWidget(self.chartUI())
        vbox.addWidget(self.controlUI())

        self.setLayout(vbox)

    def chartUI(self):
        self.chart1 = QLineSeries()
        self.chart1.setName(self.ch0Name)
        self.chart1.setPen(QPen(Qt.red))
        self.chart2 = QLineSeries()
        self.chart2.setName(self.ch1Name)
        self.chart2.setPen(QPen(Qt.darkYellow))
        self.chart3 = QLineSeries()
        self.chart3.setName(self.ch2Name)
        self.chart3.setPen(QPen(Qt.green))
        self.chart4 = QLineSeries()
        self.chart4.setName(self.ch3Name)
        self.chart4.setPen(QPen(Qt.blue))

        self.chart = QChart()
        self.chart.addSeries(self.chart1)
        self.chart.addSeries(self.chart2)
        self.chart.addSeries(self.chart3)
        self.chart.addSeries(self.chart4)
        self.chart.setAnimationOptions(QChart.AllAnimations)
        self.chart.setTitle("laser data")

        self.axis_x = QValueAxis()
        self.axis_y = QValueAxis()
        self.axis_x.setTickCount(10)
        self.axis_y.setTickCount(10)
        self.axis_x.setLabelFormat('%d')
        self.axis_y.setLabelFormat('%d')

        self.axis_x.setRange(0, 1000)
        self.axis_y.setRange(100, 300)
        self.chart.setAxisX(self.axis_x, self.chart1)
        self.chart.setAxisY(self.axis_y, self.chart1)
        self.chart.setAxisX(self.axis_x, self.chart2)
        self.chart.setAxisY(self.axis_y, self.chart2)
        self.chart.setAxisX(self.axis_x, self.chart3)
        self.chart.setAxisY(self.axis_y, self.chart3)
        self.chart.setAxisX(self.axis_x, self.chart4)
        self.chart.setAxisY(self.axis_y, self.chart4)

        self.chartView = QChartView()
        self.chartView.setChart(self.chart)
        self.chartView.setRubberBand(QChartView.RectangleRubberBand)
        self.chartView.setRenderHint(QPainter.Antialiasing)

        return self.chartView

    def controlUI(self):
        self.autoRefreshCb = QCheckBox('自动刷新')
        self.autoRefreshCb.setChecked(True)
        self.ch0Enable = QCheckBox(self.ch0Name)
        self.ch1Enable = QCheckBox(self.ch1Name)
        self.ch2Enable = QCheckBox(self.ch2Name)
        self.ch3Enable = QCheckBox(self.ch3Name)
        self.ch0Enable.setChecked(True)
        self.ch1Enable.setChecked(True)
        self.ch2Enable.setChecked(True)
        self.ch3Enable.setChecked(True)
        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.autoRefreshCb)
        hbox1.addWidget(self.ch0Enable)
        hbox1.addWidget(self.ch1Enable)
        hbox1.addWidget(self.ch2Enable)
        hbox1.addWidget(self.ch3Enable)

        self.xDataMinLabel = QLabel('x min:')
        self.xDataMaxLabel = QLabel('x max:')
        self.yDataMinLabel = QLabel('y min:')
        self.yDataMaxLabel = QLabel('y max:')

        self.xDataMinLine = QLineEdit()
        self.xDataMaxLine = QLineEdit()
        self.yDataMinLine = QLineEdit()
        self.yDataMaxLine = QLineEdit()
        self.setBtn = QPushButton('设置')

        hbox = QHBoxLayout()
        hbox.addWidget(self.xDataMinLabel)
        hbox.addWidget(self.xDataMinLine)
        hbox.addWidget(self.xDataMaxLabel)
        hbox.addWidget(self.xDataMaxLine)
        hbox.addWidget(self.yDataMinLabel)
        hbox.addWidget(self.yDataMinLine)
        hbox.addWidget(self.yDataMaxLabel)
        hbox.addWidget(self.yDataMaxLine)
        hbox.addWidget(self.setBtn)

        mainLayout = QVBoxLayout()
        mainLayout.addLayout(hbox1)
        mainLayout.addLayout(hbox)
        frame = QFrame()
        frame.setLayout(mainLayout)

        self.setBtn.clicked.connect(self.setAxisRange)
        self.ch0Enable.clicked.connect(self.changeCh)
        self.ch1Enable.clicked.connect(self.changeCh)
        self.ch2Enable.clicked.connect(self.changeCh)
        self.ch3Enable.clicked.connect(self.changeCh)
        return frame

    # @timethis
    def update(self):
        x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data
        self.chart1.clear()
        self.chart2.clear()
        self.chart3.clear()
        self.chart4.clear()
        try:
            for i in range(0, len(x0Data)):
                if self.ch0Enable.isChecked():
                    self.chart1.append(QPoint(x0Data[i], y0Data[i]))
            for i in range(0, len(x1Data)):
                if self.ch1Enable.isChecked():
                    self.chart2.append(QPoint(x1Data[i], y1Data[i]))
            for i in range(0, len(x2Data)):
                if self.ch2Enable.isChecked():
                    self.chart3.append(QPoint(x2Data[i], y2Data[i]))
            for i in range(0, len(x3Data)):
                if self.ch3Enable.isChecked():
                    self.chart4.append(QPoint(x3Data[i], y3Data[i]))
        except:
            logging.debug('y0Data is %s' % y0Data)
            logging.debug('y1Data is %s' % y1Data)
            logging.debug('y2Data is %s' % y2Data)
            logging.debug('y3Data is %s' % y3Data)
            self.chart1.clear()
            self.chart2.clear()
            self.chart3.clear()
            self.chart4.clear()
        # self.chartView.update()

        if self.autoRefreshCb.isChecked():
            self.fillAxisRange()
            self.setAxisRange()

    def fillAxisRange(self):
        x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data
        tmp = [min(x0Data), min(x1Data), min(x2Data), min(x3Data)]
        xDataMin = min(tmp)
        tmp = [max(x0Data), max(x1Data), max(x2Data), max(x3Data)]
        xDataMax = max(tmp)
        tmp = [min(y0Data), min(y1Data), min(y2Data), min(y3Data)]
        yDataMin = min(tmp)
        tmp = [max(y0Data), max(y1Data), max(y2Data), max(y3Data)]
        yDataMax = max(tmp)

        xDataAvr = (xDataMin + xDataMax) // 2
        yDataAvr = (yDataMin + yDataMax) // 2

        self.xDataMinLine.setText(str(xDataAvr - xDataAvr*6//5))
        self.xDataMaxLine.setText(str(xDataAvr + xDataAvr*6//5))
        self.yDataMinLine.setText(str(yDataAvr - yDataAvr*6//5))
        self.yDataMaxLine.setText(str(yDataAvr + yDataAvr*6//5))

    @pyqtSlot()
    def setAxisRange(self):
        if self.xDataMinLine.text() and self.xDataMaxLine.text() and \
            self.yDataMinLine.text() and self.yDataMaxLine.text():
            self.axis_x.setRange(int(self.xDataMinLine.text()), int(self.xDataMaxLine.text()))
            self.axis_y.setRange(int(self.yDataMinLine.text()), int(self.yDataMaxLine.text()))
        else:
            QMessageBox.warning(self, '警告', '缺少参数')

    @pyqtSlot()
    def changeCh(self):

        self.chart1.clear()
        self.chart2.clear()
        self.chart3.clear()
        self.chart4.clear()
        x0Data, y0Data, x1Data, y1Data, x2Data, y2Data, x3Data, y3Data = self.data

        for i in range(0, len(x0Data)):
            if self.ch0Enable.isChecked():
                self.chart1.append(QPoint(x0Data[i], y0Data[i]))
        for i in range(0, len(x1Data)):
            if self.ch1Enable.isChecked():
                self.chart2.append(QPoint(x1Data[i], y1Data[i]))
        for i in range(0, len(x2Data)):
            if self.ch2Enable.isChecked():
                self.chart3.append(QPoint(x2Data[i], y2Data[i]))
        for i in range(0, len(x3Data)):
            if self.ch3Enable.isChecked():
                self.chart4.append(QPoint(x3Data[i], y3Data[i]))
Exemple #4
0
class ChartView(QChartView):
    def __init__(self, no_margins=False):
        super().__init__()
        self.__last_mouse_pos = None
        self.lineSeries = QLineSeries()
        # self.lineSeries.setPointsVisible(True)
        self.no_margins = no_margins

        #Create a menu by right click on QChartView
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)

        ##Axis cofnig
        self.x_time_scaled = False
        self.x_name = None
        self.y_name = None
        self.x_tick_num = 30
        self.y_tick_num = 20
        self.x_label_angle = -90
        self.y_label_angle = 0
        self.y_min = None
        self.y_max = None
        self.x_min = None
        self.x_max = None

    def mousePressEvent(self, event: QMouseEvent):
        if event.button() == Qt.MiddleButton:
            self.__last_mouse_pos = event.pos()
            event.accept()

        QChartView.mousePressEvent(self, event)

    def mouseMoveEvent(self, event: QMouseEvent):
        if event.buttons() & Qt.MiddleButton:
            dif_pos = event.pos() - self.__last_mouse_pos

            self.chart().scroll(-dif_pos.x(), dif_pos.y())
            event.accept()

            self.__last_mouse_pos = event.pos()

        QChartView.mouseMoveEvent(self, event)

    def wheelEvent(self, event: QWheelEvent):
        factor = event.angleDelta().y()
        if factor < 0:
            self.chart().zoom(0.75)
        else:
            self.chart().zoom(1.25)

    def show_context_menu(self, pos: QPoint):
        menu = QMenu()

        plot_save_action = QAction('Сохранить график', self)
        plot_save_action.triggered.connect(self.save_plot)
        menu.addAction(plot_save_action)

        menu.exec(self.mapToGlobal(pos))

    def save_plot(self):
        pixmap = self.grab()

        pixmap_name = QFileDialog.getSaveFileName(
            self, 'Сохранение графика', None,
            "PNG (*.png);;JPG (*.jpg);;BMP (*.bmp)")[0]

        if not pixmap_name:
            return

        pixmap.save(pixmap_name, os.path.splitext(pixmap_name)[1][1:])

    def make_axis(self):
        if self.x_time_scaled:
            axis_x = QDateTimeAxis()
            axis_x.setFormat("yyyy-MM-dd HH:mm:ss")
            axis_x.setTitleText("Время")
        else:
            axis_x = QValueAxis()
            axis_x.setTitleText(self.x_name)

        if self.x_min:
            axis_x.setMin(self.x_min)
        if self.x_max:
            axis_x.setMax(self.x_max)

        axis_x.setLabelsAngle(self.x_label_angle)
        axis_x.setTickCount(self.x_tick_num)

        axis_y = QValueAxis()
        if self.y_min:
            axis_y.setMin(self.y_min)
        if self.y_max:
            axis_y.setMax(self.y_max)

        axis_y.setTitleText(self.y_name)
        axis_y.setTickCount(self.y_tick_num)
        axis_y.setLabelsAngle(self.y_label_angle)

        return axis_x, axis_y

    def build_plot(self,
                   data,
                   title,
                   is_legend_visible=False,
                   series_name=None):
        axis_x, axis_y = self.make_axis()

        chart = QChart()
        if self.no_margins:
            chart.setMargins(QMargins(0, 0, 0, 0))

        self.clean()

        if data != None:
            self.lineSeries = self.fill_series(data)
            self.lineSeries.setName(series_name)

        chart.addSeries(self.lineSeries)
        chart.legend().setVisible(is_legend_visible)
        chart.setTitle(title)
        chart.addAxis(axis_x, Qt.AlignBottom)
        chart.addAxis(axis_y, Qt.AlignLeft)

        self.lineSeries.attachAxis(axis_x)
        self.lineSeries.attachAxis(axis_y)

        self.setChart(chart)

    def build_multiple_plot(self, first_data, second_data, title):
        axis_x, axis_y = self.make_axis()

        chart = QChart()
        if self.no_margins:
            chart.setMargins(QMargins(0, 0, 0, 0))

        self.clean()

        first_lineseries = self.fill_series(first_data)
        second_lineseries = self.fill_series(second_data)

        chart.addSeries(first_lineseries)
        chart.addSeries(second_lineseries)
        chart.addAxis(axis_x, Qt.AlignBottom)
        chart.addAxis(axis_y, Qt.AlignLeft)
        chart.legend().setVisible(False)
        chart.setTitle(title)

        first_lineseries.attachAxis(axis_x)
        first_lineseries.attachAxis(axis_y)

        second_lineseries.attachAxis(axis_x)
        second_lineseries.attachAxis(axis_y)

        first_lineseries.setPointsVisible(True)
        second_lineseries.setPointsVisible(True)

        self.setChart(chart)

    def series_append(self, x, y, x_min, y_min, x_range=False, y_range=False):
        self.lineSeries.append(x, y)

        self.chart().axisX().setMin(x_min)
        self.chart().axisY().setMin(y_min - 0.2)

        if x_range:
            self.chart().axisX().setMax(x)

        if y_range:
            self.chart().axisY().setMax(y + 0.2)

    def add_series(self, data, series_name=None):
        series = self.fill_series(data)
        series.setName(series_name)

        self.chart().addSeries(series)

        series.attachAxis(self.chart().axisX())
        series.attachAxis(self.chart().axisY())

    def fill_series(self, data):
        series = QLineSeries()
        series.setPointsVisible(True)

        xf = data[0]
        yf = data[1]

        for i in range(len(xf)):
            series.append(xf[i], yf[i])

        return series

    def clean(self):
        self.lineSeries.clear()
class MainInterface(QMainWindow):
    '''实现 GUI 以及其连接整个程序的功能

    @属性说明: 


    @方法说明: 


    @注意: 

    '''
    def __init__(self, parent=None):
        super().__init__(parent)  # 父类初始化
        self.ui = Ui_main_interface()  # 创建UI类
        self.ui.setupUi(self)
        self.showMaximized()  # 最大化界面
        self.setWindowTitle("疲劳检测")  # 界面标题
        self.time = QTimer()  # 创建定时器
        self._connect_slot()  # 初始化槽函数连接
        self.eye_data_chart_init()  # 初始化眼睛闭合数据折线图
        self._t = 0  # 用来计数
        self._perclos_threshold = 0.3  # 设置初始化阈值

    def _connect_slot(self):
        '''初始化信号与槽的连接

        @参数说明: 
            无

        @返回值: 
            无

        @注意: 
            无
        '''
        self.ui.btn_start.clicked.connect(self._display)
        self.time.timeout.connect(self.test)

    def paintEvent(self, evevt):
        """绘图软件背景图

        Qt里面默认事件处理函数,在界面需要重新绘制时触发
        此方法主要是绘制软件的背景图

        @参数说明: 
            evevt:Qt默认事件

        @返回值: 
            无

        @注意: 
            无
        """
        temp_painter = QPainter(self)
        # 创建背景图QPixmap()对象
        soft_background_image = QPixmap("resources/groud.jpg")
        # 绘制背景图
        temp_painter.drawPixmap(0, 0, self.width(), self.height(),
                                soft_background_image)
        # 执行父类的paintEvent()函数,以便父类执行其内建的一些操作
        super().paintEvent(evevt)

    def eye_data_chart_init(self):
        '''初始化左右眼闭合程度曲线图表

        @参数说明: 
            无

        @返回值: 
            无

        @注意: 
            无
        '''
        # 创建 chart 和 chartview
        self._chart = QChart()
        self._chart.setTitle("眼睛闭合程度值")  # 设置图表标题
        self._chartView = QChartView(self)
        self._chartView.setChart(self._chart)  # chart 添加到 chartview

        # 完成布局
        self.ui.horizontalLayout_2.addWidget(self._chartView)

        ## 创建曲线系列
        self._series0 = QLineSeries()
        self._series1 = QLineSeries()
        self._series0.setName("左眼曲线")  # 设置曲线名
        self._series1.setName("右眼曲线")
        self._chart.addSeries(self._series0)  # 序列添加到图表
        self._chart.addSeries(self._series1)

        # 创建坐标轴
        self._axis_x = QValueAxis()  # x 轴
        self._axis_x.setRange(0, 60)  # 设置 x 轴坐标范围
        self._axis_x.setTitleText("time(secs)")  # x 轴标题
        self._axis_y = QValueAxis()  # y 轴
        self._axis_y.setRange(0, 0.5)  # 设置 y 轴坐标范围
        self._axis_y.setTitleText("value")  # y 轴标题

        # 为序列设置坐标轴
        self._chart.setAxisX(self._axis_x, self._series0)
        self._chart.setAxisY(self._axis_y, self._series0)
        self._chart.setAxisX(self._axis_x, self._series1)
        self._chart.setAxisY(self._axis_y, self._series1)

    @pyqtSlot(bool)
    def _display(self, checked):
        '''

        @参数说明: 


        @返回值: 


        @注意: 

        '''
        if (checked == False):  # 当按键为 False 时,停止检查
            self.ui.le_eye_threshold.setEnabled(True)
            self.ui.btn_start.setText("启动")
            self.ui.lb_fatigue_detection.setText("检测停止")
            self.time.stop()
        else:
            threshold_str = self.ui.le_eye_threshold.text()  # 获得睁闭眼阈值
            threshold_str = re.match(r"\d\.\d\d$", threshold_str)  # 对睁闭眼阈值做限定
            if (threshold_str == None):
                message_title = "阈值格式错误"
                message_text = "请输入正确的阈值格式,格式为 x.xx (x 为数字)"
                QMessageBox.critical(self, message_title, message_text)
            else:
                self.ui.btn_start.setText("停止")
                self.ui.le_eye_threshold.setEnabled(False)
                model_path = r"E:\make_data\facial"  # 人脸关键模型路径
                opencv_facial_path = r"E:\Fatigue_Detection\model_data\facial_model\haarcascade_frontalface_default.xml"  # 人脸检测模型路径
                cap_index = eval(
                    self.ui.cmb_cap_index.currentText())  # 从 combabox 获取设想头索引
                # cap_file = r"C:\Users\LWL\Pictures\Camera Roll\WIN_20200503_07_51_19_Pro.mp4"
                self.facial_data = GetFacialData(
                    tf_model=model_path,
                    facial_model_file=opencv_facial_path,
                    cap_index=cap_index)  # 创建 GetFacialData 类
                self.time.start(1000)  # 设置每次检测的间隔时间
                self.ui.lb_fatigue_detection.setText("检测中")
                self._series0.clear()
                self._series1.clear()
                self._t = 0  # 重新开始计数
                self._perclos_threshold = eval(threshold_str.group())

    def test(self):
        ret, frame = self.facial_data.get_frame()
        if (ret == -1):
            message_title = "摄像头打开失败"
            message_text = "摄像头打开失败,请检测摄像头索引是否正确"
            self.time.stop()
            QMessageBox.critical(self, message_title, message_text)
        if (ret == -2):
            message_title = "获取帧失败"
            message_text = "从摄像头获取帧失败,请重启软件"
            self.time.stop()
            QMessageBox.critical(self, message_title, message_text)
        else:
            frame = cv2.medianBlur(frame, 5)
            ret, rect = self.facial_data.get_facial(frame)
            h, w = frame.shape[:2]
            if (ret == -1):
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                temp_q_image = QImage(frame, w, h, QImage.Format_RGB888)
                #  在 lb_display 中显示图片
                self.ui.lb_display.setPixmap(QPixmap.fromImage(temp_q_image))
                self.ui.lb_facial_number.setText(str(rect))  # 显示当前检测人脸数
            else:
                self.ui.lb_facial_number.setText("1")  # 显示当前检测人脸数
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                facial = frame[rect[2]:rect[3], rect[0]:rect[1]]

                image = cv2.cvtColor(facial, cv2.COLOR_RGB2GRAY)
                image_h, image_w = image.shape[:2]
                image = cv2.resize(image, (150, 150))
                image = np.reshape(image, [1, 150, 150, 1])
                image = image / 255.
                facial_keypoints = self.facial_data.get_result(image)
                facial_keypoints = (facial_keypoints[0] + 1) / 2
                facial_keypoints[::
                                 2] = facial_keypoints[::2] * image_w + rect[0]
                facial_keypoints[
                    1::2] = facial_keypoints[1::2] * image_h + rect[2]

                # 圈出人脸范围
                facial = cv2.rectangle(frame, (rect[0], rect[2]),
                                       (rect[1], rect[3]), (255, 0, 0), 1)

                # 将人脸多特征点标记到图片上
                for i in range(12):
                    facial = cv2.circle(frame,
                                        (int(facial_keypoints[2 * i]),
                                         int(facial_keypoints[2 * i + 1])), 2,
                                        (255, 0, 0), -1)  # 进行打点

                # 获得左右眼的闭合程度
                eye_process_data = result_process.eyes_process(
                    facial_keypoints)

                # 添加点到图表上
                self._series0.append(self._t, eye_process_data[0])
                self._series1.append(self._t, eye_process_data[1])

                # 在label上显示左右眼计算值
                self.ui.lb_left_eye_figure.setText(str(
                    eye_process_data[0]))  # 显示左眼的计算值
                self.ui.lb_right_eye_figure.setText(str(
                    eye_process_data[1]))  # 显示右眼的计算值

                temp_q_image = QImage(facial.data, w, h, QImage.Format_RGB888)
                #  在 lb_display 中显示图片
                self.ui.lb_display.setPixmap(QPixmap.fromImage(temp_q_image))

                self._t += 1  # 每个 1s 绘制点
                if (self._t > 60):
                    # 获取 series0 以及 series1 中所有的数据
                    left_eye_point = self._series0.pointsVector()
                    right_eye_point = self._series1.pointsVector()
                    # 使用正则表达式提取其中的计算数据
                    left_eye_data = np.array(
                        re.findall(r"\d+\.\d{2,5}", str(left_eye_point)))
                    right_eye_data = np.array(
                        re.findall(r"\d+\.\d{2,5}", str(right_eye_point)))
                    perclos_judge_result = result_process.perclos_judge(
                        left_eye_data, self._perclos_threshold)
                    # 对 perclos_judge 的结果进行输出
                    if (perclos_judge_result == -2):
                        self.ui.lb_fatigue_detection.setText("过度疲劳")
                        message_title = "过度疲劳警告提醒"
                        message_text = "为了你的人身安全,请停下手中工作,休息一段时间!"
                        QMessageBox.critical(self, message_title,
                                             message_text)  # 过度疲劳提醒
                    elif (perclos_judge_result == -1):
                        self.ui.lb_fatigue_detection.setText("疲劳状态")
                    else:
                        self.ui.lb_fatigue_detection.setText("状态良好")
                    # 清除所有的 series0 以及 series1 数据,重新绘图
                    self._series0.clear()
                    self._series1.clear()
                    self._t = 0  # 重新开始计数
Exemple #6
0
class Display(QWidget):
    def __init__(self, trainer='MLP', debug=False):
        # QWidget Setup
        QWidget.__init__(self,
                         flags=Qt.CustomizeWindowHint | Qt.WindowTitleHint)
        self.setWindowTitle("NeuroSky GUI")
        self.resize(1400, 1000)

        # Linker Params
        self._linker = Linker(debug=debug, trainer=trainer)
        self.TRAINER_FORWARD = self._linker.trainer.add_identifier('forward')
        self.TRAINER_BACKWARD = self._linker.trainer.add_identifier('backward')
        self.TRAINER_IDLE = self._linker.trainer.add_identifier('idle')

        # Indicators
        self._raw_data_indicator = self._create_indicator('Raw Data:')
        self._poor_level_indicator = self._create_indicator(
            'Poor Level Signal:')
        self._sample_rate_indicator = self._create_indicator('Sample Rate:')
        self._prediction_indicator = self._create_indicator('Prediction:')
        self._training_status_indicator = self._create_indicator(
            'Training Status:')
        self._forward_counter_indicator = self._create_indicator(
            'Current Forward Count:')
        self._backward_counter_indicator = self._create_indicator(
            'Current Backward Count:')
        self._idle_counter_indicator = self._create_indicator(
            'Current Idle Count:')

        # Initializing layout
        self.main_page()

        # Series
        self._x_axis = 0
        self._connect_data()

    def main_page(self):  # type: (Display) -> None
        # Top Layout
        top_left_layout = QVBoxLayout()
        top_left_layout.addLayout(self._raw_data_indicator['layout'])
        top_left_layout.addLayout(self._poor_level_indicator['layout'])
        top_left_layout.addLayout(self._sample_rate_indicator['layout'])

        top_right_layout = QVBoxLayout()
        top_right_layout.addWidget(self._get_connector_chart(),
                                   alignment=Qt.AlignCenter)
        # top_right_layout.setStretchFactor(self._get_connector_chart(), 1)

        top_layout = QHBoxLayout()
        top_layout.addLayout(top_left_layout)
        top_layout.addLayout(top_right_layout)

        # Bottom Layout
        bottom_left_layout = QVBoxLayout()
        bottom_left_layout.addLayout(self._prediction_indicator['layout'])
        bottom_left_layout.addLayout(self._training_status_indicator['layout'])
        bottom_left_layout.addLayout(self._idle_counter_indicator['layout'])
        bottom_left_layout.addLayout(self._forward_counter_indicator['layout'])
        bottom_left_layout.addLayout(
            self._backward_counter_indicator['layout'])

        bottom_right_layout = QVBoxLayout()
        bottom_right_layout.addWidget(self._get_processor_chart(),
                                      alignment=Qt.AlignCenter)

        bottom_layout = QHBoxLayout()
        bottom_layout.addLayout(bottom_left_layout)
        bottom_layout.addLayout(bottom_right_layout)

        # Outer Layout
        outer_layout = QVBoxLayout()
        outer_layout.addLayout(top_layout)
        outer_layout.addLayout(bottom_layout)

        # Set Layout
        self.setLayout(outer_layout)

    def _get_connector_chart(self):  # type: (Display) -> QChartView
        # Create pen
        pen = QLineSeries().pen()
        pen.setColor(Qt.blue)
        pen.setWidthF(1)

        # Series
        self._connector_series = QLineSeries()
        self._connector_series.setPen(pen)
        self._connector_series.useOpenGL()

        # Chart
        self._connector_chart = QChart()
        self._connector_chart.legend().hide()
        self._connector_chart.addSeries(self._connector_series)
        self._connector_chart.createDefaultAxes()
        self._connector_chart.axisX().setMax(100)
        self._connector_chart.axisX().setMin(0)
        self._connector_chart.axisY().setMax(500)
        self._connector_chart.axisY().setMin(-500)

        # Chart View
        view = QChartView(self._connector_chart)
        view.setRenderHint(QPainter.Antialiasing)
        view.setStyleSheet('margin: 0px; height: 250%; width: 400%;')
        return view

    def _get_processor_chart(self):  # type: (Display) -> QChartView
        # Create pen
        pen = QLineSeries().pen()
        pen.setColor(Qt.red)
        pen.setWidthF(1)

        # Series
        self._processor_series = QLineSeries()
        self._processor_series.setPen(pen)
        self._processor_series.useOpenGL()

        # Chart
        self._processor_chart = QChart()
        self._processor_chart.legend().hide()
        self._processor_chart.addSeries(self._processor_series)
        self._processor_chart.createDefaultAxes()
        self._processor_chart.axisX().setMax(100)
        self._processor_chart.axisX().setMin(0)
        self._processor_chart.axisY().setMax(5000)
        self._processor_chart.axisY().setMin(0)

        self._processor_x_axis = QValueAxis()
        self._processor_x_axis.setLabelFormat('%i')
        self._processor_chart.setAxisX(self._processor_x_axis,
                                       self._processor_series)

        self._processor_y_axis = QLogValueAxis()
        self._processor_y_axis.setLabelFormat('%g')
        self._processor_y_axis.setBase(8)

        # Chart View
        view = QChartView(self._processor_chart)
        view.setRenderHint(QPainter.Antialiasing)
        view.setStyleSheet('margin: 0px; height: 250%; width: 400%;')
        return view

    def _connect_data(self):  # type: (Display) -> None
        self._linker.raw.connect(self._add_connector_data)
        self._linker.poor_signal_level.connect(
            lambda level: self._poor_level_indicator['label'].setText(
                str(level)))
        self._linker.sampling_rate.connect(
            lambda rate: self._sample_rate_indicator['label'].setText(str(rate)
                                                                      ))
        self._linker.fft.connect(self._add_processor_data)
        self._linker.prediction.connect(
            lambda prediction: self._prediction_indicator['label'].setText(
                str(prediction)))
        self._linker.training_status.connect(
            lambda status: self._training_status_indicator['label'].setText(
                str(status)))
        self._linker.identifiers.connect(self._connect_identifiers)

    def keyPressEvent(self, event):  # type: (Display, {key}) -> None
        key = event.key()
        if key == Qt.Key_Escape:
            self._linker.close()
            self.close()
        elif key == Qt.Key_W:
            # self._linker.connector.record(
            #     './data/raw_data/' + self._linker.trainer.get_next_connector_label(self.TRAINER_FORWARD)
            # )
            # self._linker.processor.record(
            #     './data/processed_data/' + self._linker.trainer.get_next_processor_label(self.TRAINER_FORWARD)
            # )
            self._linker.trainer.train(self.TRAINER_FORWARD)
        elif key == Qt.Key_S:
            # self._linker.connector.record(
            #     './data/raw_data/' + self._linker.trainer.get_next_connector_label(self.TRAINER_BACKWARD)
            # )
            # self._linker.processor.record(
            #     './data/processed_data/' + self._linker.trainer.get_next_processor_label(self.TRAINER_BACKWARD)
            # )
            self._linker.trainer.train(self.TRAINER_BACKWARD)
        elif key == Qt.Key_Space:
            # self._linker.connector.record(
            #     './data/raw_data/' + self._linker.trainer.get_next_connector_label(self.TRAINER_IDLE)
            # )
            # self._linker.processor.record(
            #     './data/processed_data/' + self._linker.trainer.get_next_processor_label(self.TRAINER_IDLE)
            # )
            self._linker.trainer.train(self.TRAINER_IDLE)
        else:
            print(key)

    @staticmethod
    def _create_indicator(
            label):  # type: (Any) -> Dict[str, Union[QHBoxLayout, QLabel]]
        layout = QHBoxLayout()
        display_widget = QLabel(label)
        layout.addWidget(display_widget, alignment=Qt.AlignCenter)
        label_widget = QLabel('Initializing...')
        layout.addWidget(label_widget, alignment=Qt.AlignCenter)
        return {
            'layout': layout,
            'display': display_widget,
            'label': label_widget
        }

    @pyqtSlot(int)
    def _add_connector_data(self,
                            data):  # type: (Display, Any) -> Optional[Any]
        self._raw_data_indicator['label'].setText(str(data))
        self._connector_series.append(self._x_axis, data)
        if self._connector_series.count() >= 100:
            self._connector_series.clear()
            self._x_axis = 0
        else:
            self._x_axis += 1

    @pyqtSlot(np.ndarray)
    def _add_processor_data(
            self, data):  # type: (Display, {__getitem__}) -> Optional[Any]
        self._processor_series.clear()
        x_axis = data[0]
        y_axis = data[1]
        for i in range(len(x_axis)):
            self._processor_series.append(x_axis[i], y_axis[i])

    @pyqtSlot(list)
    def _connect_identifiers(self, identifiers):
        for identifier in identifiers:
            if identifier['name'] == self.TRAINER_IDLE:
                self._idle_counter_indicator['label'].setText(
                    str(identifier['training_count']))
            elif identifier['name'] == self.TRAINER_FORWARD:
                self._forward_counter_indicator['label'].setText(
                    str(identifier['training_count']))
            elif identifier['name'] == self.TRAINER_BACKWARD:
                self._backward_counter_indicator['label'].setText(
                    str(identifier['training_count']))
Exemple #7
0
class Demo(QWidget,QFont):
    def __init__(self):
        super(Demo,self).__init__()     #子类调用父类的方法
        self.BuildUI()                  #构造界面
        self.CreatChart()               #创建曲线
        self.connection()

##==============自定义功能函数============
    def BuildUI(self):   ##构造界面
        self.resize(800, 600)
        self.setFont(QFont("黑体", 10.5))  ##设置字体
        self.setWindowTitle("水工标准设计反应谱v1.1(Hs小毕)")  ##s设置窗口标题
        self.setWindowIcon(QIcon(':/fyp.ico'))

        # 定义控件
        #定义“输入”控件===========================
        self.label1 = QLabel("水工建筑物类型", self)
        # 标准设计反应谱最大值的代表值
        BEITA = ["土石坝", "重力坝", "拱坝", "水闸|进水塔|边坡|其他"]
        self.comboBox1 = QComboBox()
        self.comboBox1.addItems(BEITA)
        self.comboBox1.setCurrentIndex(1)  # 设置默认值
        self.label2 = QLabel("特征周期Tg(s)", self)
        self.line2 = QLineEdit()
        self.line2.setPlaceholderText("单位(s)")
        self.label3 = QLabel("加速度幅值A(g)", self)
        self.line3 = QLineEdit()
        self.line3.setPlaceholderText("单位(g)")
        self.groupbox_1 = QGroupBox('输入数据', self)
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.label1)
        self.v_layout.addWidget(self.comboBox1)
        self.v_layout.addWidget(self.label2)
        self.v_layout.addWidget(self.line2)
        self.v_layout.addWidget(self.label3)
        self.v_layout.addWidget(self.line3)
        self.groupbox_1.setLayout(self.v_layout)

        #定义“生成”控件===========================
        self.v1_layout = QVBoxLayout()
        self.groupbox_2 = QGroupBox('生成曲线', self)
        self.button1 = QPushButton("生成曲线",self)
        self.v1_layout.addWidget(self.button1)
        self.groupbox_2.setLayout(self.v1_layout)

        #定义“输出单位”控件
        self.groupbox_3 = QGroupBox('输出单位', self)
        self.h_layout = QHBoxLayout()
        self.unit_g = QRadioButton('g', self)
        self.unit_g.setChecked(True)                #设置单位“g”为默认
        self.unit_m = QRadioButton('m/sec2', self)
        self.unit_mm = QRadioButton('mm/sec2', self)
        self.h_layout.addWidget(self.unit_g)
        self.h_layout.addWidget(self.unit_m)
        self.h_layout.addWidget(self.unit_mm)
        self.groupbox_3.setLayout(self.h_layout)
        #定义输出的列数
        self.groupbox_4 = QGroupBox('输出列数', self)
        self.h1_layout = QHBoxLayout()
        self.list2 = QRadioButton('时间|谱值')
        self.list2.setChecked(True)  # 设置时间|谱值为默认
        self.list1 = QRadioButton('谱值')
        self.h1_layout.addWidget(self.list2)
        self.h1_layout.addWidget(self.list1)
        self.groupbox_4.setLayout(self.h1_layout)
        #输出时间间隔
        self.groupbox_5 = QGroupBox('输出时间间隔(s)', self)
        self.v2_layout = QHBoxLayout()
        self.Dtime = QRadioButton('0.01')
        self.Dtime.setChecked(True)  # 设置0.01s为默认
        self.Dtime_Edit = QLineEdit()
        self.Dtime1 = QRadioButton(self.Dtime_Edit)
        self.v2_layout.addWidget(self.Dtime)
        self.v2_layout.addWidget(self.Dtime1)
        self.v2_layout.addWidget(self.Dtime_Edit)
        self.groupbox_5.setLayout(self.v2_layout)
        #定义输出的文件选择
        self.groupbox_6 = QGroupBox('输出文件', self)
        self.v3_layout = QVBoxLayout()
        self.h3_layout = QHBoxLayout()
        self.Enter = QPushButton('点击输出',self)
        self.out_line=QLineEdit()
        self.out_select=QPushButton('浏览',self)
        self.h3_layout.addWidget(self.out_line)
        self.h3_layout.addWidget(self.out_select)
        self.v3_layout.addLayout(self.h3_layout)
        self.v3_layout.addWidget(self.Enter)
        self.groupbox_6.setLayout(self.v3_layout)

        # 定义绘图控件===========================
        self.chartView = QChartView()  # 创建 ChartView
        self.v6_layout = QVBoxLayout()
        self.v6_layout.addWidget(self.groupbox_1)
        self.v6_layout.addWidget(self.groupbox_2)
        self.v6_layout.addWidget(self.groupbox_3)
        self.v6_layout.addWidget(self.groupbox_4)
        self.v6_layout.addWidget(self.groupbox_5)
        self.v6_layout.addWidget(self.groupbox_6)

        self.h4_layout = QHBoxLayout()
        self.h4_layout.addLayout(self.v6_layout)
        self.h4_layout.addWidget(self.chartView)
        self.setLayout(self.h4_layout)

    def CreatChart(self):
        self.chart = QChart()  # 创建 Chart
        self.chart.setTitle("反应谱曲线")
        self.chartView.setChart(self.chart)  # Chart添加到ChartView
        # 创建曲线序列
        self.series0 = QLineSeries()
        self.chart.addSeries(self.series0)  # 序列添加到图表
        self.chart.createDefaultAxes()
        ##创建坐标轴
        self.axisX = QValueAxis()  # X 轴
        self.axisX.setTitleText("T(s)")  # 标题
        self.axisX.setLabelFormat("%.1f")     #标签格式
        self.axisX.setTickCount(5)           #主分隔个数
        self.axisX.setMinorTickCount(4)
        self.axisY=QValueAxis()  # Y 轴
        self.axisY.setTitleText("Se/g")
        self.axisY.setTickCount(5)
        self.axisY.setMinorTickCount(4)
        self.axisY.setLabelFormat("%.2f")     #标签格式
        # 为序列设置坐标轴
        self.chart.setAxisX(self.axisX, self.series0)  # 为序列设置坐标轴
        self.chart.setAxisY(self.axisY, self.series0)

    def PrepareData(self):
        """
        定义绘图中的数据
        """
        # 序列添加数值
        Str_dict={"土石坝":1.6, "重力坝":2, "拱坝":2.5, "水闸|进水塔|边坡|其他":2.25}
        Str_list =self.comboBox1.currentText()
        BETA_Data = Str_dict[Str_list]
        # 特征周期
        TG = float(self.line2.text())
        # 加速度幅值
        PGA = float(self.line3.text())
        t = 0
        intv = 0.01
        pointCount = 301
        self.series0.clear()   #清楚数据========
        for T in range(pointCount):
            T= round(T * intv,2)
            if T <= 0.1:
                y1 = (BETA_Data-1)/(0.1-0)*T+1
            elif 0.1<T and T <= TG:
                y1= BETA_Data
            else:
                y1 = BETA_Data*(TG/T)**0.6
            y1 = y1 * PGA
            self.series0.append(T, y1)
        #设置坐标轴范围=========================
        self.axisX.setRange(0,3)
        self.axisY.setRange(0,BETA_Data*PGA+1)

    def outputfilename(self):
        """
        定义输出路径
        """
        dlg = QFileDialog()
        filt = "Srf Files(*.Srf);;Text Files (*.txt);;All Files (*)"
        fileName, _ =dlg.getSaveFileName(self, "另存为文件", ".",filt)
        self.out_line.setText(fileName)

    def Output_Data(self):
        """
        定义输出的数据
        """
        # 序列添加数值
        Str_dict={"土石坝":1.6, "重力坝":2, "拱坝":2.5, "水闸|进水塔|边坡|其他":2.25}
        Str_list =self.comboBox1.currentText()
        BETA_Data = Str_dict[Str_list]
        # 特征周期
        TG = float(self.line2.text())
        # 加速度幅值
        PGA = float(self.line3.text())
        # 输出单位
        if self.unit_g.isChecked()==True:
            UNIT = 1
        elif self.unit_g.isChecked()==True:
            UNIT = 9.81
        else:
            UNIT = 9810
        # 输出间隔
        if self.Dtime.isChecked()==True:
            intv = 0.01
        else:
            intv = float(self.Dtime_Edit.text())
        pointCount = 301
        fileNameout = QLineEdit.text(self.out_line)
        with open(fileNameout, 'w', encoding='gbk') as f_out:
            for T in range(pointCount):
                T = round(T * intv, 2)
                if T <= 0.1:
                    y1 = (BETA_Data - 1) / (0.1 - 0) * T + 1
                elif 0.1 < T and T <= TG:
                    y1 = BETA_Data
                else:
                    y1 = BETA_Data * (TG / T) ** 0.6
                y1 = y1 * PGA * UNIT
                if self.list2.isChecked()==True:
                    f_out.write(f"{T}\t\t{y1}\n")
                else:
                    f_out.write(f"{y1}\n")
    def connection(self):
        """
        槽函数
        """
        self.button1.clicked.connect(lambda: self.PrepareData())
        self.out_select.clicked.connect(lambda: self.outputfilename())
        self.Enter.clicked.connect(lambda: self.Output_Data())
Exemple #8
0
class AmzHistoryChart(QWidget):
    """A chart that graphs the history of an AmazonListing's sales rank, price, and number of offers."""

    def __init__(self, parent=None):
        super(AmzHistoryChart, self).__init__(parent=parent)

        self.dbsession = Session()
        self.context_menu_actions = []
        self._avg_pointspan = 0
        self._max_points = 100
        self.source = None
        self.history = None

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

        # Set up the chart
        self.chart_view = QChartView(self)
        self.chart_view.setRenderHint(QPainter.Antialiasing)
        self.chart_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.chart_view.customContextMenuRequested.connect(self.context_menu)

        self.chart = QChart()
        self.chart.legend().hide()
        self.chart.setFlags(QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsSelectable)
        self.chart.installEventFilter(self)
        self.chart_view.setChart(self.chart)

        self.layout().addWidget(self.chart_view)

        # Create the axes
        rcolor = QColor(50, 130, 220)
        pcolor = QColor(0, 200, 0)
        ocolor = QColor(255, 175, 0)

        self.timeAxis = QDateTimeAxis()
        self.timeAxis.setFormat('M/dd hh:mm')
        self.timeAxis.setTitleText('Date/Time')
        self.chart.addAxis(self.timeAxis, Qt.AlignBottom)

        self.timeAxis.minChanged.connect(self.on_timeaxis_min_changed)

        self.rankAxis = QValueAxis()
        self.rankAxis.setLabelFormat('%\'i')
        self.rankAxis.setTitleText('Sales Rank')
        self.rankAxis.setLinePenColor(rcolor)
        self.rankAxis.setLabelsColor(rcolor)
        self.chart.addAxis(self.rankAxis, Qt.AlignLeft)

        self.priceAxis = QValueAxis()
        self.priceAxis.setLabelFormat('$%.2f')
        self.priceAxis.setTitleText('Price')
        self.priceAxis.setLinePenColor(pcolor)
        self.priceAxis.setLabelsColor(pcolor)
        self.chart.addAxis(self.priceAxis, Qt.AlignRight)

        # Create the series
        self.rankLine = QLineSeries()
        self.chart.addSeries(self.rankLine)
        self.rankLine.attachAxis(self.timeAxis)
        self.rankLine.attachAxis(self.rankAxis)
        self.rankLine.setColor(rcolor)

        self.priceLine = QLineSeries()
        self.chart.addSeries(self.priceLine)
        self.priceLine.attachAxis(self.timeAxis)
        self.priceLine.attachAxis(self.priceAxis)
        self.priceLine.setColor(pcolor)

        self.salesPoints = QScatterSeries()
        self.chart.addSeries(self.salesPoints)
        self.salesPoints.attachAxis(self.timeAxis)
        self.salesPoints.attachAxis(self.rankAxis)
        self.salesPoints.setColor(ocolor)

    def add_context_action(self, action):
        """Add an action to the chart's context menu."""
        self.context_menu_actions.append(action)

    def add_context_actions(self, actions):
        """Adds all action in an iterable."""
        self.context_menu_actions.extend(actions)

    def remove_context_action(self, action):
        """Removes an action from the chart's context menu."""
        self.context_menu_actions.remove(action)

    def context_menu(self, point):
        """Show a context menu on the chart."""
        menu = QMenu(self)
        menu.addActions(self.context_menu_actions)

        point = self.chart_view.viewport().mapToGlobal(point)
        menu.popup(point)

    def set_source(self, source):
        """Set the source listing for the graph."""
        self.source = source

        # Update the chart
        self.rankLine.clear()
        self.priceLine.clear()
        self.salesPoints.clear()
        self.history = None

        start_date = datetime.utcnow() - timedelta(days=5)
        self.load_history_from(start_date)

        self.reset_axes()

    def load_history_from(self, start_date=datetime.utcfromtimestamp(0)):
        """Load history data from start-present."""
        if not self.source:
            self._avg_pointspan = 0
            return

        # Get the earliest point already in the chart
        points = self.rankLine.pointsVector()

        if points:
            # The chart is drawn right-to-left, so the last point is the earliest point
            earliest_msecs = points[-1].x()
            earliest = datetime.fromtimestamp(earliest_msecs / 1000, timezone.utc)

            if earliest <= start_date:
                return

        else:
            earliest = datetime.now(timezone.utc)

        # Get the product history stats if we don't already have them
        if self.history is None:
            self.history = dbhelpers.ProductHistoryStats(self.dbsession, self.source.id)

        # Start adding points to the chart
        last_row = None
        for row in self.dbsession.query(AmzProductHistory).\
                                  filter(AmzProductHistory.amz_listing_id == self.source.id,
                                         AmzProductHistory.timestamp > start_date.replace(tzinfo=None),
                                         AmzProductHistory.timestamp < earliest.replace(tzinfo=None)).\
                                  order_by(AmzProductHistory.timestamp.desc()):

            # SqlAlchemy returns naive timestamps
            time = row.timestamp.replace(tzinfo=timezone.utc).timestamp() * 1000

            self.rankLine.append(time, row.salesrank or 0)
            self.priceLine.append(time, row.price or 0)

            if last_row:
                # It's possible for salesrank to be None
                try:
                    slope = (last_row.salesrank - row.salesrank) / (last_row.timestamp.timestamp() - row.timestamp.timestamp())
                    if slope < -0.3:
                        self.salesPoints.append(last_row.timestamp.replace(tzinfo=timezone.utc).timestamp() * 1000,
                                                last_row.salesrank)
                except (TypeError, AttributeError):
                    pass

            last_row = row

        # Calculate the average span between points
        spans = 0
        for p1, p2 in itertools.zip_longest(itertools.islice(points, 0, None, 2), itertools.islice(points, 1, None, 2)):
            if p1 and p2: spans += abs(p1.x() - p2.x())

        self._avg_pointspan = spans // 2

    def on_timeaxis_min_changed(self, min):
        """Respond to a change in the time axis' minimum value."""
        # toTime_t() converts to UTC automatically
        utc_min = datetime.fromtimestamp(min.toTime_t(), timezone.utc)
        self.load_history_from(start_date=utc_min - timedelta(days=1))

    def reset_axes(self):
        """Resets the chart axes."""
        r = self.rankLine.pointsVector()
        p = self.priceLine.pointsVector()

        # If there is only one data point, set the min and max to the day before and the day after
        if len(r) == 1:
            tmin = QDateTime.fromMSecsSinceEpoch(r[0].x(), Qt.LocalTime).addDays(-1)
            tmax = QDateTime.fromMSecsSinceEpoch(r[0].x(), Qt.LocalTime).addDays(+1)
        else:
            tmin = min(r, key=lambda pt: pt.x(), default=QPointF(QDateTime.currentDateTime().addDays(-1).toMSecsSinceEpoch(), 0)).x()
            tmax = max(r, key=lambda pt: pt.x(), default=QPointF(QDateTime.currentDateTime().addDays(+1).toMSecsSinceEpoch(), 0)).x()
            tmin = QDateTime.fromMSecsSinceEpoch(tmin, Qt.LocalTime)
            tmax = QDateTime.fromMSecsSinceEpoch(tmax, Qt.LocalTime)

        self.timeAxis.setMin(tmin)
        self.timeAxis.setMax(tmax)

        # Find the min and max values of the series
        min_point = lambda pts: min(pts, key=lambda pt: pt.y(), default=QPointF(0, 0))
        max_point = lambda pts: max(pts, key=lambda pt: pt.y(), default=QPointF(0, 0))

        rmin = min_point(r)
        rmax = max_point(r)
        pmin = min_point(p)
        pmax = max_point(p)

        # Scale the mins and maxes to 'friendly' values
        scalemin = lambda v, step: ((v - step / 2) // step) * step
        scalemax = lambda v, step: ((v + step / 2) // step + 1) * step

        # The the axis bounds

        rmin = max(scalemin(rmin.y(), 1000), 0)
        rmax = scalemax(rmax.y(), 1000)
        pmin = max(scalemin(pmin.y(), 5), 0)
        pmax = scalemax(pmax.y(), 5)

        self.rankAxis.setMin(rmin)
        self.rankAxis.setMax(rmax)
        self.priceAxis.setMin(pmin)
        self.priceAxis.setMax(pmax)

    def eventFilter(self, watched, event):
        """Intercept and handle mouse events."""
        if event.type() == QEvent.GraphicsSceneWheel and event.orientation() == Qt.Vertical:
            factor = 0.95 if event.delta() < 0 else 1.05
            self.chart.zoom(factor)
            return True

        if event.type() == QEvent.GraphicsSceneMouseDoubleClick:
            self.chart.zoomReset()
            self.reset_axes()
            return True

        if event.type() == QEvent.GraphicsSceneMouseMove:
            delta = event.pos() - event.lastPos()
            self.chart.scroll(-delta.x(), delta.y())
            return True

        return False
Exemple #9
0
class VolumeFigure:
    def __init__(self, name):
        self.chart_volume_view = QChartView()
        self.chart_volume_view.chart().setLocalizeNumbers(True)
        self.volume_series = QCandlestickSeries()

        self.volume_time_axis = QDateTimeAxis()
        self.volume_time_axis.setFormat('h:mm')
        self.volume_axis = QValueAxis()

        self.volume_average_series = QLineSeries()

        self.chart_volume_view.chart().addSeries(self.volume_series)
        self.chart_volume_view.chart().addSeries(self.volume_average_series)

        self.chart_volume_view.chart().addAxis(self.volume_time_axis,
                                               Qt.AlignBottom)
        self.chart_volume_view.chart().addAxis(self.volume_axis, Qt.AlignLeft)
        self.chart_volume_view.chart().legend().hide()
        self.chart_volume_view.setRenderHint(QPainter.Antialiasing)

    def in_datetime_range(self, q):
        return self.datetime_range[0] < q < self.datetime_range[1]

    def get_chart_view(self):
        return self.chart_volume_view

    def clear_series_data(self):
        self.volume_series.clear()
        self.volume_average_series.clear()

    def set_volume_average(self, vol):
        self.volume_average_series.append(self.datetime_range[0], vol)
        self.volume_average_series.append(self.datetime_range[1], vol)

    def set_datetime(self, d):
        self.chart_datetime = d
        self.datetime_range = (d.timestamp() * 1000,
                               d.replace(hour=23, minute=59).timestamp() *
                               1000)
        start_time = QDateTime()
        until_time = QDateTime()
        start_time.setDate(QDate(d.year, d.month, d.day))
        until_time.setDate(QDate(d.year, d.month, d.day))
        start_time.setTime(QTime(9, 0))
        until_time.setTime(QTime(16, 0))
        self.volume_time_axis.setRange(start_time, until_time)

    def add_volume_data(self, q, volume):
        if self.in_datetime_range(q):
            self.volume_series.append(QCandlestickSet(0, volume, 0, volume, q))

    def attach(self):
        self.volume_time_axis.setTickCount(7)
        self.volume_average_series.attachAxis(self.volume_axis)
        self.volume_average_series.attachAxis(self.volume_time_axis)
        self.volume_series.attachAxis(self.volume_axis)
        self.volume_series.attachAxis(self.volume_time_axis)

    def set_max(self, vol):
        self.volume_axis.setRange(0, vol)
Exemple #10
0
class PriceFigure:
    def __init__(self, name):
        self.name = name
        self.chart_view = QChartView()

        self.price_time_axis = QDateTimeAxis()
        self.price_time_axis.setFormat('h:mm')

        self.price_axis = QValueAxis()
        self.candle_stick_series = QCandlestickSeries()
        self.candle_stick_series.setIncreasingColor(Qt.red)
        self.candle_stick_series.setDecreasingColor(Qt.blue)

        self.moving_average_series = QLineSeries()

        self.top_edge_series = QScatterSeries()
        self.bottom_edge_series = QScatterSeries()

        self.trend_lines = []
        self.short_top_trend_series = QLineSeries()
        self.short_bottom_trend_series = QLineSeries()
        self.long_top_trend_series = QLineSeries()
        self.long_bottom_trend_series = QLineSeries()
        self.trend_lines.append(self.short_top_trend_series)
        self.trend_lines.append(self.short_bottom_trend_series)
        self.trend_lines.append(self.long_top_trend_series)
        self.trend_lines.append(self.long_bottom_trend_series)

        self.chart_view.chart().addSeries(self.candle_stick_series)
        self.chart_view.chart().addSeries(self.moving_average_series)
        self.chart_view.chart().addSeries(self.top_edge_series)
        self.chart_view.chart().addSeries(self.bottom_edge_series)
        self.chart_view.chart().addSeries(self.short_top_trend_series)
        self.chart_view.chart().addSeries(self.long_top_trend_series)
        self.chart_view.chart().addSeries(self.short_bottom_trend_series)
        self.chart_view.chart().addSeries(self.long_bottom_trend_series)

        self.chart_view.chart().addAxis(self.price_time_axis, Qt.AlignBottom)
        self.chart_view.chart().addAxis(self.price_axis, Qt.AlignLeft)
        self.chart_view.chart().legend().hide()
        self.chart_view.setRenderHint(QPainter.Antialiasing)
        self.set_marker_color()
        self.set_trend_line_pen()

    def set_trend_line_pen(self):
        brushes = [
            QBrush(QColor(255, 0, 0, 90)),
            QBrush(QColor(0, 0, 255, 90)),
            QBrush(QColor(205, 56, 47, 255)),
            QBrush(QColor(0, 153, 213, 255))
        ]
        for i, tl in enumerate(self.trend_lines):
            tl.setPen(QPen(brushes[i], 4, Qt.DotLine))

    def set_marker_color(self):
        self.top_edge_series.setPen(Qt.black)
        self.top_edge_series.setBrush(QBrush(QColor(255, 0, 255, 90)))
        self.bottom_edge_series.setPen(Qt.black)
        self.bottom_edge_series.setBrush(QBrush(QColor(0, 255, 255, 90)))

    def set_datetime(self, d):
        self.chart_datetime = d
        self.datetime_range = (d.timestamp() * 1000,
                               d.replace(hour=23, minute=59).timestamp() *
                               1000)
        start_time = QDateTime()
        until_time = QDateTime()
        start_time.setDate(QDate(d.year, d.month, d.day))
        until_time.setDate(QDate(d.year, d.month, d.day))
        start_time.setTime(QTime(9, 0))
        until_time.setTime(QTime(16, 0))
        self.price_time_axis.setRange(start_time, until_time)

    def attach(self):
        self.price_time_axis.setTickCount(7)
        self.candle_stick_series.attachAxis(self.price_time_axis)
        self.candle_stick_series.attachAxis(self.price_axis)
        self.moving_average_series.attachAxis(self.price_time_axis)
        self.moving_average_series.attachAxis(self.price_axis)
        self.top_edge_series.attachAxis(self.price_time_axis)
        self.top_edge_series.attachAxis(self.price_axis)
        self.bottom_edge_series.attachAxis(self.price_time_axis)
        self.bottom_edge_series.attachAxis(self.price_axis)
        self.short_top_trend_series.attachAxis(self.price_time_axis)
        self.short_top_trend_series.attachAxis(self.price_axis)
        self.long_top_trend_series.attachAxis(self.price_time_axis)
        self.long_top_trend_series.attachAxis(self.price_axis)
        self.short_bottom_trend_series.attachAxis(self.price_time_axis)
        self.short_bottom_trend_series.attachAxis(self.price_axis)
        self.long_bottom_trend_series.attachAxis(self.price_time_axis)
        self.long_bottom_trend_series.attachAxis(self.price_axis)

    def in_datetime_range(self, q):
        return self.datetime_range[0] < q < self.datetime_range[1]

    def clear_series_data(self):
        self.candle_stick_series.clear()
        self.moving_average_series.clear()
        self.top_edge_series.clear()
        self.bottom_edge_series.clear()
        self.short_top_trend_series.clear()
        self.long_top_trend_series.clear()
        self.short_bottom_trend_series.clear()
        self.long_bottom_trend_series.clear()

    def get_chart_view(self):
        return self.chart_view

    def add_moving_average(self, q, price):
        if self.in_datetime_range(q):
            self.moving_average_series.append(q, price)

    def add_candle_stick(self, q, o, h, l, c):
        if self.in_datetime_range(q):
            self.candle_stick_series.append(QCandlestickSet(o, h, l, c, q))

    def set_price_range(self, price_min, price_max):
        self.price_axis.setRange(price_min, price_max)
        tick_count = int(
            math.ceil((price_max - price_min) / price_min * 100. / 2.0))
        self.price_axis.setTickCount(tick_count if tick_count + 1 > 2 else 2)

    def add_top_edge(self, q, price):
        if self.in_datetime_range(q):
            self.top_edge_series.append(q, price)

    def add_bottom_edge(self, q, price):
        if self.in_datetime_range(q):
            self.bottom_edge_series.append(q, price)

    def add_short_top_trend(self, q, price, draw_horizontal=False):
        if self.in_datetime_range(q):
            if draw_horizontal:
                self.short_top_trend_series.append(q, price)
                if self.name == 'yesterday':
                    self.short_top_trend_series.append(self.datetime_range[1],
                                                       price)
                else:
                    self.short_top_trend_series.append(self.datetime_range[0],
                                                       price)
            else:
                self.short_top_trend_series.append(q, price)

    def add_long_top_trend(self, q, price, draw_horizontal=False):
        if self.in_datetime_range(q):
            if draw_horizontal:
                self.long_top_trend_series.append(q, price)
                if self.name == 'yesterday':
                    self.long_top_trend_series.append(self.datetime_range[1],
                                                      price)
                else:
                    self.long_top_trend_series.append(self.datetime_range[0],
                                                      price)
            else:
                self.long_top_trend_series.append(q, price)

    def add_short_bottom_trend(self, q, price, draw_horizontal=False):
        if self.in_datetime_range(q):
            if draw_horizontal:
                self.short_bottom_trend_series.append(q, price)
                if self.name == 'yesterday':
                    self.short_bottom_trend_series.append(
                        self.datetime_range[1], price)
                else:
                    self.short_bottom_trend_series.append(
                        self.datetime_range[0], price)
            else:
                self.short_bottom_trend_series.append(q, price)

    def add_long_bottom_trend(self, q, price, draw_horizontal=False):
        if self.in_datetime_range(q):
            if draw_horizontal:
                self.long_bottom_trend_series.append(q, price)
                if self.name == 'yesterday':
                    self.long_bottom_trend_series.append(
                        self.datetime_range[1], price)
                else:
                    self.long_bottom_trend_series.append(
                        self.datetime_range[0], price)
            else:
                self.long_bottom_trend_series.append(q, price)
class TelemetryDialog(QDialog):
    resized = QtCore.pyqtSignal()
    visibility = QtCore.pyqtSignal(bool)

    def __init__(self, winTitle="Network Telemetry", parent=None):
        super(TelemetryDialog, self).__init__(parent)

        self.visibility.connect(self.onVisibilityChanged)

        self.winTitle = winTitle

        self.updateLock = Lock()

        # Used to detect network change
        self.lastNetKey = ""
        self.lastSeen = None
        self.maxPoints = 20
        self.maxRowPoints = 60

        self.paused = False
        self.streamingSave = False
        self.streamingFile = None
        self.linesBeforeFlush = 10
        self.currentLine = 0

        # OK and Cancel buttons
        #buttons = QDialogButtonBox(QDialogButtonBox.Ok,Qt.Horizontal, self)
        #buttons.accepted.connect(self.accept)
        #buttons.move(170, 280)

        desktopSize = QApplication.desktop().screenGeometry()
        #self.mainWidth=1024
        #self.mainHeight=768
        #self.mainWidth = desktopSize.width() * 3 / 4
        #self.mainHeight = desktopSize.height() * 3 / 4

        self.setGeometry(self.geometry().x(),
                         self.geometry().y(),
                         desktopSize.width() / 2,
                         desktopSize.height() / 2)

        self.setWindowTitle(winTitle)

        self.radar = RadarWidget(self)
        self.radar.setGeometry(self.geometry().width() / 2, 10,
                               self.geometry().width() / 2 - 20,
                               self.geometry().width() / 2 - 20)

        self.createTable()

        self.btnExport = QPushButton("Export Table", self)
        self.btnExport.clicked[bool].connect(self.onExportClicked)
        self.btnExport.setStyleSheet("background-color: rgba(2,128,192,255);")

        self.btnPause = QPushButton("Pause Table", self)
        self.btnPause.setCheckable(True)
        self.btnPause.clicked[bool].connect(self.onPauseClicked)
        self.btnPause.setStyleSheet("background-color: rgba(2,128,192,255);")

        self.btnStream = QPushButton("Streaming Save", self)
        self.btnStream.setCheckable(True)
        self.btnStream.clicked[bool].connect(self.onStreamClicked)
        self.btnStream.setStyleSheet("background-color: rgba(2,128,192,255);")

        self.createChart()

        self.setBlackoutColors()

        self.setMinimumWidth(600)
        self.setMinimumHeight(600)

        self.center()

    def createTable(self):
        # Set up location table
        self.locationTable = QTableWidget(self)
        self.locationTable.setColumnCount(8)
        self.locationTable.setGeometry(10, 10,
                                       self.geometry().width() / 2 - 20,
                                       self.geometry().height() / 2)
        self.locationTable.setShowGrid(True)
        self.locationTable.setHorizontalHeaderLabels([
            'macAddr', 'SSID', 'Strength', 'Timestamp', 'GPS', 'Latitude',
            'Longitude', 'Altitude'
        ])
        self.locationTable.resizeColumnsToContents()
        self.locationTable.setRowCount(0)
        self.locationTable.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)

        self.ntRightClickMenu = QMenu(self)
        newAct = QAction('Copy', self)
        newAct.setStatusTip('Copy data to clipboard')
        newAct.triggered.connect(self.onCopy)
        self.ntRightClickMenu.addAction(newAct)

        self.locationTable.setContextMenuPolicy(Qt.CustomContextMenu)
        self.locationTable.customContextMenuRequested.connect(
            self.showNTContextMenu)

    def setBlackoutColors(self):
        self.locationTable.setStyleSheet(
            "QTableView {background-color: black;gridline-color: white;color: white} QTableCornerButton::section{background-color: white;}"
        )
        headerStyle = "QHeaderView::section{background-color: white;border: 1px solid black;color: black;} QHeaderView::down-arrow,QHeaderView::up-arrow {background: none;}"
        self.locationTable.horizontalHeader().setStyleSheet(headerStyle)
        self.locationTable.verticalHeader().setStyleSheet(headerStyle)

        mainTitleBrush = QBrush(Qt.red)
        self.timeChart.setTitleBrush(mainTitleBrush)

        self.timeChart.setBackgroundBrush(QBrush(Qt.black))
        self.timeChart.axisX().setLabelsColor(Qt.white)
        self.timeChart.axisY().setLabelsColor(Qt.white)
        titleBrush = QBrush(Qt.white)
        self.timeChart.axisX().setTitleBrush(titleBrush)
        self.timeChart.axisY().setTitleBrush(titleBrush)

    def resizeEvent(self, event):
        wDim = self.geometry().width() / 2 - 20
        hDim = self.geometry().height() / 2

        smallerDim = wDim
        if hDim < smallerDim:
            smallerDim = hDim

        # Radar
        self.radar.setGeometry(self.geometry().width() - smallerDim - 10, 10,
                               smallerDim, smallerDim)

        # chart
        self.timePlot.setGeometry(10, 10,
                                  self.geometry().width() - smallerDim - 30,
                                  smallerDim)

        # Buttons
        self.btnPause.setGeometry(10,
                                  self.geometry().height() / 2 + 18, 110, 25)
        self.btnExport.setGeometry(150,
                                   self.geometry().height() / 2 + 18, 110, 25)
        self.btnStream.setGeometry(290,
                                   self.geometry().height() / 2 + 18, 110, 25)

        # Table
        self.locationTable.setGeometry(10,
                                       self.geometry().height() / 2 + 50,
                                       self.geometry().width() - 20,
                                       self.geometry().height() / 2 - 60)

    def center(self):
        # Get our geometry
        qr = self.frameGeometry()
        # Find the desktop center point
        cp = QDesktopWidget().availableGeometry().center()
        # Move our center point to the desktop center point
        qr.moveCenter(cp)
        # Move the top-left point of the application window to the top-left point of the qr rectangle,
        # basically centering the window
        self.move(qr.topLeft())

    def showNTContextMenu(self, pos):
        curRow = self.locationTable.currentRow()

        if curRow == -1:
            return

        self.ntRightClickMenu.exec_(self.locationTable.mapToGlobal(pos))

    def onCopy(self):
        self.updateLock.acquire()

        curRow = self.locationTable.currentRow()
        curCol = self.locationTable.currentColumn()

        if curRow == -1 or curCol == -1:
            self.updateLock.release()
            return

        curText = self.locationTable.item(curRow, curCol).text()

        clipboard = QApplication.clipboard()
        clipboard.setText(curText)

        self.updateLock.release()

    def onVisibilityChanged(self, visible):
        if not visible:
            self.paused = True
            self.btnPause.setStyleSheet("background-color: rgba(255,0,0,255);")
            # We're coming out of streaming
            self.streamingSave = False
            self.btnStream.setStyleSheet(
                "background-color: rgba(2,128,192,255);")
            self.btnStream.setChecked(False)
            if (self.streamingFile):
                self.streamingFile.close()
                self.streamingFile = None
            return
        else:
            self.paused = False
            self.btnPause.setStyleSheet(
                "background-color: rgba(2,128,192,255);")
            if self.locationTable.rowCount() > 1:
                self.locationTable.scrollToItem(self.locationTable.item(0, 0))

    def hideEvent(self, event):
        self.visibility.emit(False)

    def showEvent(self, event):
        self.visibility.emit(True)

    def onPauseClicked(self, pressed):
        if self.btnPause.isChecked():
            self.paused = True
            self.btnPause.setStyleSheet("background-color: rgba(255,0,0,255);")
        else:
            self.paused = False
            self.btnPause.setStyleSheet(
                "background-color: rgba(2,128,192,255);")

    def onStreamClicked(self, pressed):
        if not self.btnStream.isChecked():
            # We're coming out of streaming
            self.streamingSave = False
            self.btnStream.setStyleSheet(
                "background-color: rgba(2,128,192,255);")
            if (self.streamingFile):
                self.streamingFile.close()
                self.streamingFile = None
            return

        self.btnStream.setStyleSheet("background-color: rgba(255,0,0,255);")
        self.streamingSave = True

        fileName = self.saveFileDialog()

        if not fileName:
            self.btnStream.setStyleSheet(
                "background-color: rgba(2,128,192,255);")
            self.btnStream.setChecked(False)
            return

        try:
            self.streamingFile = open(
                fileName, 'w', 1
            )  # 1 says use line buffering, otherwise it fully buffers and doesn't write
        except:
            QMessageBox.question(self, 'Error',
                                 "Unable to write to " + fileName,
                                 QMessageBox.Ok)
            self.streamingFile = None
            self.streamingSave = False
            self.btnStream.setStyleSheet(
                "background-color: rgba(2,128,192,255);")
            self.btnStream.setChecked(False)
            return

        self.streamingFile.write(
            'MAC Address,SSID,Strength,Timestamp,GPS,Latitude,Longitude,Altitude\n'
        )

    def onExportClicked(self):
        fileName = self.saveFileDialog()

        if not fileName:
            return

        try:
            outputFile = open(fileName, 'w')
        except:
            QMessageBox.question(self, 'Error',
                                 "Unable to write to " + fileName,
                                 QMessageBox.Ok)
            return

        outputFile.write(
            'MAC Address,SSID,Strength,Timestamp,GPS,Latitude,Longitude,Altitude\n'
        )

        numItems = self.locationTable.rowCount()

        if numItems == 0:
            outputFile.close()
            return

        self.updateLock.acquire()

        for i in range(0, numItems):
            outputFile.write(
                self.locationTable.item(i, 0).text() + ',"' +
                self.locationTable.item(i, 1).text() + '",' +
                self.locationTable.item(i, 2).text() + ',' +
                self.locationTable.item(i, 3).text())
            outputFile.write(',' + self.locationTable.item(i, 4).text() + ',' +
                             self.locationTable.item(i, 5).text() + ',' +
                             self.locationTable.item(i, 6).text() + ',' +
                             self.locationTable.item(i, 7).text() + '\n')

        self.updateLock.release()
        outputFile.close()

    def saveFileDialog(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(
            self,
            "QFileDialog.getSaveFileName()",
            "",
            "CSV Files (*.csv);;All Files (*)",
            options=options)
        if fileName:
            return fileName
        else:
            return None

    def createChart(self):
        self.timeChart = QChart()
        titleFont = QFont()
        titleFont.setPixelSize(18)
        titleBrush = QBrush(QColor(0, 0, 255))
        self.timeChart.setTitleFont(titleFont)
        self.timeChart.setTitleBrush(titleBrush)
        self.timeChart.setTitle('Signal (Past ' + str(self.maxPoints) +
                                ' Samples)')
        # self.timeChart.addSeries(testseries)
        # self.timeChart.createDefaultAxes()
        self.timeChart.legend().hide()

        # Axis examples: https://doc.qt.io/qt-5/qtcharts-multiaxis-example.html
        newAxis = QValueAxis()
        newAxis.setMin(0)
        newAxis.setMax(self.maxPoints)
        newAxis.setTickCount(11)
        newAxis.setLabelFormat("%d")
        newAxis.setTitleText("Sample")
        self.timeChart.addAxis(newAxis, Qt.AlignBottom)

        newAxis = QValueAxis()
        newAxis.setMin(-100)
        newAxis.setMax(-10)
        newAxis.setTickCount(9)
        newAxis.setLabelFormat("%d")
        newAxis.setTitleText("dBm")
        self.timeChart.addAxis(newAxis, Qt.AlignLeft)

        chartBorder = Qt.darkGray
        self.timePlot = QChartView(self.timeChart, self)
        self.timePlot.setBackgroundBrush(chartBorder)
        self.timePlot.setRenderHint(QPainter.Antialiasing)

        self.timeSeries = QLineSeries()
        pen = QPen(Qt.yellow)

        pen.setWidth(2)
        self.timeSeries.setPen(pen)
        self.timeChart.addSeries(self.timeSeries)
        self.timeSeries.attachAxis(self.timeChart.axisX())
        self.timeSeries.attachAxis(self.timeChart.axisY())

    def updateNetworkData(self, curNet):
        if not self.isVisible():
            return

        # Signal is -NN dBm.  Need to make it positive for the plot
        self.radar.updateData(curNet.signal * -1)

        if self.winTitle == "Client Telemetry":
            self.setWindowTitle(self.winTitle + " - [" + curNet.macAddr +
                                "] " + curNet.ssid)
        else:
            self.setWindowTitle(self.winTitle + " - " + curNet.ssid)

        self.radar.draw()

        #  Network changed.  Clear our table and time data
        updateChartAndTable = False

        self.updateLock.acquire()

        if (curNet.getKey() != self.lastNetKey):
            self.lastNetKey = curNet.getKey()
            self.locationTable.setRowCount(0)
            self.timeSeries.clear()
            updateChartAndTable = True

            ssidTitle = curNet.ssid
            if len(ssidTitle) > 28:
                ssidTitle = ssidTitle[:28]
                ssidTitle = ssidTitle + '...'

            self.timeChart.setTitle(ssidTitle + ' Signal (Past ' +
                                    str(self.maxPoints) + ' Samples)')
        else:
            if self.lastSeen != curNet.lastSeen:
                updateChartAndTable = True

        if updateChartAndTable:
            # Update chart
            numPoints = len(self.timeSeries.pointsVector())

            if numPoints >= self.maxPoints:
                self.timeSeries.remove(0)
                # Now we need to reset the x data to pull the series back
                counter = 0
                for curPoint in self.timeSeries.pointsVector():
                    self.timeSeries.replace(counter, counter, curPoint.y())
                    counter += 1

            if curNet.signal >= -100:
                self.timeSeries.append(numPoints, curNet.signal)
            else:
                self.timeSeries.append(numPoints, -100)

            # Update Table
            self.addTableData(curNet)

            # Limit points in each
            if self.locationTable.rowCount() > self.maxRowPoints:
                self.locationTable.setRowCount(self.maxRowPoints)

        self.updateLock.release()

    def addTableData(self, curNet):
        if self.paused:
            return

        # rowPosition = self.locationTable.rowCount()
        # Always insert at row(0)
        rowPosition = 0

        self.locationTable.insertRow(rowPosition)

        #if (addedFirstRow):
        #    self.locationTable.setRowCount(1)

        # ['macAddr','SSID', 'Strength', 'Timestamp','GPS', 'Latitude', 'Longitude', 'Altitude']
        self.locationTable.setItem(rowPosition, 0,
                                   QTableWidgetItem(curNet.macAddr))
        tmpssid = curNet.ssid
        if (len(tmpssid) == 0):
            tmpssid = '<Unknown>'
        newSSID = QTableWidgetItem(tmpssid)

        self.locationTable.setItem(rowPosition, 1, newSSID)
        self.locationTable.setItem(rowPosition, 2,
                                   IntTableWidgetItem(str(curNet.signal)))
        self.locationTable.setItem(
            rowPosition, 3,
            DateTableWidgetItem(curNet.lastSeen.strftime("%m/%d/%Y %H:%M:%S")))
        if curNet.gps.isValid:
            self.locationTable.setItem(rowPosition, 4, QTableWidgetItem('Yes'))
        else:
            self.locationTable.setItem(rowPosition, 4, QTableWidgetItem('No'))

        self.locationTable.setItem(
            rowPosition, 5, FloatTableWidgetItem(str(curNet.gps.latitude)))
        self.locationTable.setItem(
            rowPosition, 6, FloatTableWidgetItem(str(curNet.gps.longitude)))
        self.locationTable.setItem(
            rowPosition, 7, FloatTableWidgetItem(str(curNet.gps.altitude)))
        #order = Qt.DescendingOrder
        #self.locationTable.sortItems(3, order )

        # If we're in streaming mode, write the data out to disk as well
        if self.streamingFile:
            self.streamingFile.write(
                self.locationTable.item(rowPosition, 0).text() + ',"' +
                self.locationTable.item(rowPosition, 1).text() + '",' +
                self.locationTable.item(rowPosition, 2).text() + ',' +
                self.locationTable.item(rowPosition, 3).text() + ',' +
                self.locationTable.item(rowPosition, 4).text() + ',' +
                self.locationTable.item(rowPosition, 5).text() + ',' +
                self.locationTable.item(rowPosition, 6).text() + ',' +
                self.locationTable.item(rowPosition, 7).text() + '\n')

            if (self.currentLine > self.linesBeforeFlush):
                self.streamingFile.flush()
                self.currentLine += 1

        numRows = self.locationTable.rowCount()

        if numRows > 1:
            self.locationTable.scrollToItem(self.locationTable.item(0, 0))

    def onTableHeadingClicked(self, logical_index):
        header = self.locationTable.horizontalHeader()
        order = Qt.DescendingOrder
        # order = Qt.DescendingOrder
        if not header.isSortIndicatorShown():
            header.setSortIndicatorShown(True)
        elif header.sortIndicatorSection() == logical_index:
            # apparently, the sort order on the header is already switched
            # when the section was clicked, so there is no need to reverse it
            order = header.sortIndicatorOrder()
        header.setSortIndicator(logical_index, order)
        self.locationTable.sortItems(logical_index, order)

    def updateData(self, newRadius):
        self.radar.updateData(newRadius)

    def showTelemetry(parent=None):
        dialog = TelemetryDialog(parent)
        result = dialog.exec_()
        return (result == QDialog.Accepted)
class ContentView(QWidget):
    def __init__(self):
        super().__init__()

        self.m_chart_1 = QChart()
        self.m_chart_2 = QChart()
        self.m_chart_3 = QChart()
        self.m_chart_4 = QChart()
        self.m_series_1 = QLineSeries()
        self.m_series_2 = QLineSeries()
        self.m_series_3 = QLineSeries()
        self.m_series_4 = QLineSeries()

        self.y_original = []
        self.x_data = []
        self.y_processed = []
        self.sampling_rate = 0

        self.pathForVocalMute = ""

        self.select_action_drop = QComboBox()

        self.echo_shift = 0.4
        self.echo_alpha = 0.5

        self.init_ui()

    def init_ui(self):
        main_layout = QVBoxLayout()

        # Drag&Drop area
        drag_drop = DragDropArea(parent=self)
        main_layout.addWidget(drag_drop)

        # Chart layout
        chart_layout_1 = QHBoxLayout()
        chart_layout_2 = QHBoxLayout()

        # Chart 1
        chart_view_1 = QChartView(self.m_chart_1)
        chart_view_1.setMinimumSize(400, 300)

        self.m_chart_1.addSeries(self.m_series_1)

        pen = self.m_series_1.pen()
        pen.setColor(Qt.red)
        pen.setWidthF(.1)
        self.m_series_1.setPen(pen)
        self.m_series_1.setUseOpenGL(True)

        axis_x = QValueAxis()
        axis_x.setRange(0, 100)
        axis_x.setLabelFormat("%g")
        axis_x.setTitleText("Samples")

        axis_y = QValueAxis()
        axis_y.setRange(-10, 10)
        axis_y.setTitleText("Audio level")

        self.m_chart_1.setAxisX(axis_x, self.m_series_1)
        self.m_chart_1.setAxisY(axis_y, self.m_series_1)
        self.m_chart_1.setTitle("Original signal time domain")

        chart_layout_1.addWidget(chart_view_1)

        # Chart 2
        chart_view_2 = QChartView(self.m_chart_2)
        chart_view_2.setMinimumSize(400, 300)

        self.m_chart_2.setTitle("Original signal frequency domain")

        pen = self.m_series_2.pen()
        pen.setColor(Qt.blue)
        pen.setWidthF(.1)
        self.m_series_2.setPen(pen)
        self.m_series_2.setUseOpenGL(True)

        self.m_chart_2.addSeries(self.m_series_2)

        chart_layout_1.addWidget(chart_view_2)

        # Chart 3
        chart_view_3 = QChartView(self.m_chart_3)
        chart_view_3.setMinimumSize(400, 300)

        self.m_chart_3.addSeries(self.m_series_3)

        pen = self.m_series_3.pen()
        pen.setColor(Qt.green)
        pen.setWidthF(.1)
        self.m_series_3.setPen(pen)
        self.m_series_3.setUseOpenGL(True)

        axis_x = QValueAxis()
        axis_x.setRange(0, 100)
        axis_x.setLabelFormat("%g")
        axis_x.setTitleText("Samples")

        axis_y = QValueAxis()
        axis_y.setRange(-10, 10)
        axis_y.setTitleText("Audio level")

        self.m_chart_3.setAxisX(axis_x, self.m_series_3)
        self.m_chart_3.setAxisY(axis_y, self.m_series_3)
        self.m_chart_3.setTitle("Processed signal time domain")

        chart_layout_2.addWidget(chart_view_3)

        # Chart 4
        chart_view_4 = QChartView(self.m_chart_4)
        chart_view_4.setMinimumSize(400, 300)

        self.m_chart_4.setTitle("Processed signal frequency domain")

        pen = self.m_series_4.pen()
        pen.setColor(Qt.magenta)
        pen.setWidthF(.1)
        self.m_series_4.setPen(pen)
        self.m_series_4.setUseOpenGL(True)

        self.m_chart_4.addSeries(self.m_series_4)

        chart_layout_2.addWidget(chart_view_4)

        main_layout.addLayout(chart_layout_1)
        main_layout.addLayout(chart_layout_2)

        # Action buttons
        player_layout = QHBoxLayout()

        self.select_action_drop.addItems([
            "Add noise", "Filter", "Mute equipment", "Mute vocal", "Add echo",
            "Filter echo"
        ])

        player_layout.addWidget(self.select_action_drop)

        noise_jc = QIcon('rate_ic.png')
        noise_btn = QPushButton('Process')
        noise_btn.setIcon(noise_jc)
        noise_btn.clicked.connect(self.on_action)

        player_layout.addWidget(noise_btn)

        play_jc = QIcon('play_ic.png')
        play_orig_btn = QPushButton('Play Original')
        play_orig_btn.setIcon(play_jc)
        play_orig_btn.clicked.connect(self.on_play_orig)

        player_layout.addWidget(play_orig_btn)

        play_jc = QIcon('play_ic.png')
        play_btn = QPushButton('Play Processed')
        play_btn.setIcon(play_jc)
        play_btn.clicked.connect(self.on_play)

        player_layout.addWidget(play_btn)

        stop_jc = QIcon('stop_ic.png')
        stop_btn = QPushButton('Stop')
        stop_btn.setIcon(stop_jc)
        stop_btn.clicked.connect(self.on_stop)

        player_layout.addWidget(stop_btn)

        main_layout.addLayout(player_layout)

        self.setLayout(main_layout)

    ''''
        Toolbar actions
    '''

    def browse_file(self):
        path1 = QFileDialog.getOpenFileName(self, 'Open File',
                                            os.getenv('HOME'), '*.wav')
        print(path1[0])

        rate, data = wavfile.read(path1[0])

        self.sampling_rate = rate
        self.y_original = data[:, 0]

        self.show_original_data()

    def on_file_upload(self, file_url):
        print(file_url[7:])

        self.pathForVocalMute = file_url[7:]

        rate, data = wavfile.read(file_url[7:])

        self.sampling_rate = rate
        self.y_original = data[:, 0]

        self.show_original_data()

    def on_save(self):
        print("on_save")
        if len(self.y_processed) > 0:
            path = QFileDialog.getSaveFileName(self, 'Save File',
                                               os.getenv('HOME'), 'audio/wav')
            if path[0] != '':
                data2 = np.asarray([self.y_processed,
                                    self.y_processed]).transpose()
                wavfile.write(path[0], self.sampling_rate, data2)
            else:
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Critical)
                msg.setText("No path")
                msg.setInformativeText("You should define path to save file")
                msg.setWindowTitle("Error")
                msg.exec_()
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("No data")
            msg.setInformativeText(
                "No data to save, you should upload and process sound file")
            msg.setWindowTitle("Error")
            msg.exec_()

    ''''
        Action selection
    '''

    def on_action(self):
        if self.select_action_drop.currentText() == "Add noise":
            self.on_add_noise()
        elif self.select_action_drop.currentText() == "Filter":
            self.on_filter()
        elif self.select_action_drop.currentText() == "Mute equipment":
            self.on_mute_equipment()
        elif self.select_action_drop.currentText() == "Mute vocal":
            self.on_mute_voice()
        elif self.select_action_drop.currentText() == "Add echo":
            self.on_add_echo()
        elif self.select_action_drop.currentText() == "Filter echo":
            self.on_filter_echo()

    '''
        Noise addition
    '''

    def on_add_noise(self):
        if len(self.y_original) == 0:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Upload sound file")
            msg.setInformativeText(
                "First you should add sound file to process")
            msg.setWindowTitle("Error")
            msg.exec_()
            return

        noise = np.random.normal(0,
                                 self.y_original.max() / 30,
                                 len(self.y_original))
        arr1 = np.array(self.y_original)
        self.y_processed = arr1 + noise
        self.show_processed_data()

    def on_filter(self):
        print("on_filter")

        if len(self.y_original) == 0:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Upload sound file")
            msg.setInformativeText(
                "First you should add sound file to process")
            msg.setWindowTitle("Error")
            msg.exec_()
            return

        filter1, filter2, limit1, limit2, extra, max_ripple, min_attenuation, ok = FilterSelectionDialog.show_dialog(
            parent=self)
        print(filter1, filter2, limit1, limit2, extra, max_ripple,
              min_attenuation, ok)

        if ok:
            if filter1 == "FIR filter":
                self.on_fir_filter(filter2, limit1, limit2, extra)
            elif filter1 == "IIR filter":
                self.on_iir_filter(filter2, limit1, limit2, extra, max_ripple,
                                   min_attenuation)

    def on_mute_equipment(self):
        print("on_mute_equipment")

        check_piano, check_organ, check_flute, check_french_horn, check_trumpet, check_violin, \
        check_guitar_acoustic, check_guitar_bass, check_clarinet, \
        check_saxophone, ok = MuteInstrumentsDialog.show_dialog(parent=self)

        print(check_piano, check_organ, check_flute, check_french_horn,
              check_trumpet, check_violin, check_guitar_acoustic,
              check_guitar_bass, check_clarinet, check_saxophone, ok)
        '''
        Piano	A0 (28 Hz) to C8 (4,186 Hz or 4.1 KHz)
        Organ	C0 (16 Hz) to A9 (7,040 KHz)	
        Concert Flute	C4 (262 Hz) to B6 (1,976 Hz)	
        French Horn	A2 (110 Hz) to A5 (880 Hz)
        Trumpet	E3 (165 Hz) to B5 (988 Hz)
        Violin	G3 (196 Hz) - G7 (3,136 Hz) (G-D-E-A) (or C8 (4,186 Hz?)
        Guitar (Acoustic)	E2 (82 Hz) to F6 (1,397 Hz)
        Guitar (Bass)	4 string E1 (41 Hz) to C4 (262 Hz)
        Clarinet	E3 (165 Hz) to G6 (1,568 Hz)	
        Saxaphone Eb 138-830 (880)
        '''
        if ok:
            print(check_piano)

        limit1 = 0.1
        limit2 = 0.2
        if check_piano:
            pass
        elif check_organ:
            pass
        elif check_flute:
            limit1 = 262 / self.sampling_rate
            limit2 = 1976 / self.sampling_rate
            pass
        elif check_french_horn:
            limit1 = 110 / self.sampling_rate
            limit2 = 880 / self.sampling_rate
            pass
        elif check_trumpet:
            limit1 = 165 / self.sampling_rate
            limit2 = 988 / self.sampling_rate
            pass
        elif check_violin:
            limit1 = 196 / self.sampling_rate
            limit2 = 3136 / self.sampling_rate
            pass
        elif check_guitar_acoustic:
            limit1 = 82 / self.sampling_rate
            limit2 = 1397 / self.sampling_rate
            pass
        elif check_guitar_bass:
            limit1 = 41 / self.sampling_rate
            limit2 = 262 / self.sampling_rate
            pass
        elif check_clarinet:
            limit1 = 165 / self.sampling_rate
            limit2 = 1568 / self.sampling_rate
            pass
        elif check_saxophone:
            limit1 = 138 / self.sampling_rate
            limit2 = 880 / self.sampling_rate
            pass

        print(limit1, limit2)

        print([
            0.0, 0.0001, limit1 - 0.0001, limit1, limit2, limit2 + 0.0001,
            0.9991, 1.0
        ], [0, 1, 1, 0, 0, 1, 1, 0])
        design_filter = signal.firwin2(1000000, [
            0.0, 0.0001, limit1 - 0.0001, limit1, limit2, limit2 + 0.0001,
            0.9991, 1.0
        ], [0, 1, 1, 0, 0, 1, 1, 0])

        self.y_processed = signal.convolve(self.y_original,
                                           design_filter,
                                           mode='same')

        w1, h1 = signal.freqz(design_filter)

        result = FilterResponseDialog.show_dialog(parent=self, w1=w1, h1=h1)

        if result:
            self.show_processed_data()

    def on_mute_voice(self):
        y, sr = librosa.load(self.pathForVocalMute, sr=self.sampling_rate)

        S_full, phase = librosa.magphase(librosa.stft(y))

        S_filter = librosa.decompose.nn_filter(
            S_full,
            aggregate=np.median,
            metric='cosine',
            width=int(librosa.time_to_frames(2, sr=sr)))

        S_filter = np.minimum(S_full, S_filter)

        margin_i, margin_v = 2, 10
        power = 2

        mask_i = librosa.util.softmask(S_filter,
                                       margin_i * (S_full - S_filter),
                                       power=power)

        mask_v = librosa.util.softmask(S_full - S_filter,
                                       margin_v * S_filter,
                                       power=power)

        S_foreground = mask_v * S_full
        S_background = mask_i * S_full

        self.y_processed = librosa.istft(S_background)

        self.show_processed_data()

    def on_add_echo(self):
        if len(self.y_original) == 0:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Upload sound file")
            msg.setInformativeText(
                "First you should add sound file to process")
            msg.setWindowTitle("Error")
            msg.exec_()
            return

        num_shift = int(self.sampling_rate * self.echo_shift)
        zeros = np.zeros(num_shift)

        original = np.append(self.y_original, zeros)
        echo = np.append(zeros, self.y_original) * self.echo_alpha

        self.y_processed = original + echo

        np.delete(
            self.y_processed,
            np.arange(
                len(self.y_processed) - len(zeros), len(self.y_processed)))

        self.show_processed_data()

    def on_filter_echo(self):
        ceps = cepstrum.real_cepstrum(np.array(self.y_original))

        index, result = CepstrumDialog.show_dialog(self, ceps)

        if result:
            print(index)

            b = np.array([1])

            a = np.zeros(index + 1)
            a[0] = 1
            a[len(a) - 1] = self.echo_alpha

            zi = signal.lfilter_zi(b, a)

            self.y_processed, _ = signal.lfilter(b,
                                                 a,
                                                 self.y_original,
                                                 axis=0,
                                                 zi=zi * self.y_original[0])

            w1, h1 = signal.freqz(b, a)

            result = FilterResponseDialog.show_dialog(parent=self,
                                                      w1=w1,
                                                      h1=h1)

            if result:
                self.show_processed_data()

    '''
        Filters
    '''

    def on_fir_filter(self, filter_type, limit1, limit2, extra):
        if filter_type == "Low-pass":
            design_filter = signal.firwin(41, limit1, window=extra)
        elif filter_type == "High-pass":
            temp = np.zeros(41)
            temp[20] = 1
            design_filter = temp - np.array(
                signal.firwin(41, limit1, window=extra))
        elif filter_type == "Band-pass":
            temp = np.zeros(41)
            temp[20] = 1
            design_filter = temp - np.array(
                signal.firwin(41, [limit1, limit2], window=extra))
        elif filter_type == "Band-reject":
            design_filter = signal.firwin(41, [limit1, limit2], window=extra)

        self.y_processed = signal.convolve(self.y_original,
                                           design_filter,
                                           mode='same')

        w1, h1 = signal.freqz(design_filter)

        result = FilterResponseDialog.show_dialog(parent=self, w1=w1, h1=h1)

        if result:
            self.show_processed_data()

    def on_iir_filter(self, filter_type, limit1, limit2, extra, max_ripple,
                      min_attenuation):
        if filter_type == "Low-pass":
            b, a = signal.iirfilter(4,
                                    limit1,
                                    rp=int(max_ripple),
                                    rs=int(min_attenuation),
                                    btype='lowpass',
                                    ftype=extra)
        elif filter_type == "High-pass":
            b, a = signal.iirfilter(4,
                                    limit1,
                                    rp=int(max_ripple),
                                    rs=int(min_attenuation),
                                    btype='highpass',
                                    ftype=extra)
        elif filter_type == "Band-pass":
            b, a = signal.iirfilter(4, [limit1, limit2],
                                    rp=int(max_ripple),
                                    rs=int(min_attenuation),
                                    btype='bandpass',
                                    ftype=extra)
        elif filter_type == "Band-reject":
            b, a = signal.iirfilter(4, [limit1, limit2],
                                    rp=int(max_ripple),
                                    rs=int(min_attenuation),
                                    btype='bandstop',
                                    ftype=extra)

        self.y_processed = signal.lfilter(b, a, self.y_original)

        w1, h1 = signal.freqz(b, a)

        result = FilterResponseDialog.show_dialog(parent=self, w1=w1, h1=h1)

        if result:
            self.show_processed_data()

    '''
        Audio controls
    '''

    def on_play(self):
        print("on_play")

        if len(self.y_processed) > 0:
            data2 = np.asarray(self.y_processed)
            sd.play(data2, self.sampling_rate)
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Upload sound file")
            msg.setInformativeText(
                "First you should upload and process sound file to play")
            msg.setWindowTitle("Error")
            msg.exec_()

    def on_stop(self):
        sd.stop()

    def on_play_orig(self):
        print("on_play_orig")

        if len(self.y_original) > 0:
            data = np.asarray(self.y_original)
            sd.play(data, self.sampling_rate)
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Upload sound file")
            msg.setInformativeText("First you should add sound file to play")
            msg.setWindowTitle("Error")
            msg.exec_()

    '''
        Signal plots
    '''

    def show_original_data(self):
        # Time domain
        y_data_scaled = np.interp(
            self.y_original, (self.y_original.min(), self.y_original.max()),
            (-10, +10))

        sample_size = len(self.y_original)
        self.x_data = np.linspace(0., 100., sample_size)

        points_1 = []

        for k in range(len(y_data_scaled)):
            points_1.append(QPointF(self.x_data[k], y_data_scaled[k]))

        self.m_series_1.replace(points_1)

        # Frequency domain
        y_freq_data = np.abs(fftpack.fft(self.y_original))
        y_freq_data = np.interp(y_freq_data,
                                (y_freq_data.min(), y_freq_data.max()),
                                (0, +10))
        x_freq_data = fftpack.fftfreq(len(
            self.y_original)) * self.sampling_rate

        axis_x = QValueAxis()
        axis_x.setRange(0, self.sampling_rate / 2)
        axis_x.setLabelFormat("%g")
        axis_x.setTitleText("Frequency [Hz]")

        axis_y = QValueAxis()
        axis_y.setRange(np.min(y_freq_data), np.max(y_freq_data))
        axis_y.setTitleText("Magnitude")

        self.m_chart_2.setAxisX(axis_x, self.m_series_2)
        self.m_chart_2.setAxisY(axis_y, self.m_series_2)

        points_2 = []

        for k in range(len(y_freq_data)):
            points_2.append(QPointF(x_freq_data[k], y_freq_data[k]))

        self.m_series_2.replace(points_2)

        self.m_series_3.clear()
        self.m_series_4.clear()

    def show_processed_data(self):
        # Time domain
        y_data_scaled = np.interp(
            self.y_processed, (self.y_processed.min(), self.y_processed.max()),
            (-10, +10))

        points_3 = []

        sample_size = len(self.y_processed)
        x_data = np.linspace(0., 100., sample_size)

        for k in range(len(y_data_scaled)):
            points_3.append(QPointF(x_data[k], y_data_scaled[k]))

        self.m_series_3.replace(points_3)

        # Frequency domain
        y_freq_data = np.abs(fftpack.fft(self.y_processed))
        y_freq_data = np.interp(y_freq_data,
                                (y_freq_data.min(), y_freq_data.max()),
                                (0, +10))
        x_freq_data = fftpack.fftfreq(len(
            self.y_processed)) * self.sampling_rate

        axis_x = QValueAxis()
        axis_x.setRange(0, self.sampling_rate / 2)
        axis_x.setLabelFormat("%g")
        axis_x.setTitleText("Frequency [Hz]")

        axis_y = QValueAxis()
        axis_y.setRange(np.min(y_freq_data), np.max(y_freq_data))
        axis_y.setTitleText("Magnitude")

        self.m_chart_4.setAxisX(axis_x, self.m_series_4)
        self.m_chart_4.setAxisY(axis_y, self.m_series_4)

        points_4 = []

        for k in range(len(y_freq_data)):
            points_4.append(QPointF(x_freq_data[k], y_freq_data[k]))

        self.m_series_4.replace(points_4)
Exemple #13
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.pixelRow = QLabel()
        self.pixelRow.setFixedSize(20, nbPixels)

        self.matrixDisplay = QTextEdit()
        self.matrixDisplay.setFixedSize(165, 180)

        self.valuesDisplay = QTextEdit()
        self.valuesDisplay.setFixedSize(50, nbPixels)

        # CHART
        self.serie = QLineSeries()

        self.chart = QChart()
        self.chart.addSeries(self.serie)
        self.chart.legend().hide()
        self.chart.layout().setContentsMargins(0, 0, 0, 0)

        self.xAxis = QValueAxis()
        self.xAxis.setTitleText("Height")
        self.xAxis.setLabelFormat("%d")
        self.xAxis.setRange(0, nbPixels)

        self.yAxis = QValueAxis()
        self.yAxis.setLabelFormat("%d")
        self.yAxis.setTitleText("Distance ")
        self.yAxis.setRange(0, couleurMax)

        self.chart.setAxisX(self.xAxis)
        self.chart.setAxisY(self.yAxis)

        self.serie.attachAxis(self.xAxis)
        self.serie.attachAxis(self.yAxis)

        self.chart.setTitle("Profile line")

        self.chartView = QChartView(self)
        self.chartView.setChart(self.chart)
        self.chartView.rotate(90)
        self.chartView.setGeometry(20, 195, 450, 400)
        #end CHART

        self.timer = QTimer(self)
        self.timer.setInterval(periode)
        self.timer.start
        self.timer.timeout.connect(self.refresh)

        self.startButton = QPushButton("START")
        self.startButton.setDefault(True)
        self.startButton.clicked.connect(self.startTimer)
        self.startButton.setFixedSize(100, 50)

        self.stopButton = QPushButton("STOP")
        self.stopButton.setDefault(True)
        self.stopButton.clicked.connect(self.stopTimer)
        self.stopButton.setFixedSize(100, 50)

        topLayout = QGridLayout()
        topLayout.addWidget(self.startButton, 0, 0)
        topLayout.addWidget(self.stopButton, 1, 0)
        topLayout.addWidget(self.matrixDisplay, 0, 1, 2, 1)

        mainLayout = QGridLayout()
        mainLayout.addLayout(topLayout, 0, 0)
        mainLayout.addWidget(self.pixelRow, 0, 1, 2, 1)
        mainLayout.addWidget(self.valuesDisplay, 0, 2, 2, 1)
        mainLayout.addWidget(self.chartView, 1, 0)

        mainwidget = QWidget()
        mainwidget.setLayout(mainLayout)
        self.setCentralWidget(mainwidget)

        self.setWindowTitle("Minecraft Depth Map")

    def startTimer(self):
        self.timer.start()

    def stopTimer(self):
        self.timer.stop()

    def refresh(self):
        self.serie.clear()
        self.valuesDisplay.clear()
        screen = app.primaryScreen()
        #grabWindow(wID, x, y, w, h)
        pix = QPixmap(
            screen.grabWindow(0,
                              int((screenW * 3) / 4) - 10,
                              int((screenH - nbPixels) / 2), 20, nbPixels))
        self.pixelRow.setPixmap(pix)
        img = QImage(pix.toImage())

        array = [0 for i in range(nbBlocsH)]

        for i in range(nbBlocsH):
            y = nbPixels - (i * (nbPixels / nbBlocsH) + (nbPixels /
                                                         (2 * nbBlocsH)))
            colorvalue = 255 - QColor(img.pixel(10, y)).black()
            self.valuesDisplay.append(str(colorvalue))
            self.valuesDisplay.append("\n")
            self.serie.append(y, colorvalue)

            #convert colors from 0->couleurMax to 0->nbBlocsD
            if colorvalue > couleurMax:
                colorvalue = nbBlocsD
            elif colorvalue < couleurMin:
                colorvalue = 0
            else:
                colorvalue = int(colorvalue / (couleurMax / nbBlocsD))
            array[i] = colorvalue

        self.convertToMatrix(array)

    def convertToMatrix(self, array):

        matrix = [[0 for j in range(nbBlocsD)] for i in range(nbBlocsH)]

        for i in range(nbBlocsH):
            if array[i] < nbBlocsD:
                matrix[i][array[i]] = 1
                if i < (nbBlocsH - 1):
                    if array[i + 1] > (array[i] + 1):
                        for j in range(array[i] + 1,
                                       min(nbBlocsD, array[i + 1])):
                            matrix[i][j] = 1
                if i > 0:
                    if array[i - 1] > (array[i] + 1):
                        for j in range(array[i] + 1,
                                       min(nbBlocsD, array[i - 1])):
                            matrix[i][j] = 1

        #test1Scalable.convertToHexa(motifF,nbBlocsD,nbBlocsH)  # es-ce bien la fonction a utiliser pour l'affichage ?
        self.displayMatrix(matrix)

    def displayMatrix(self, matrix):
        self.matrixDisplay.clear()
        for j in range(nbBlocsD - 1, -1, -1):
            line = ""
            for i in range(nbBlocsH):
                line = line + str(matrix[i][j]) + "  "
                #self.matrixDisplay.append( line)
                #self.matrixDisplay.append( str(matrix[i][j]) + "  ")
                #self.matrixDisplay.moveCursor( QTextCursor.EndOfLine )
            self.matrixDisplay.append(line)
Exemple #14
0
class MyWidget(QWidget):
    def __init__(self):
        super().__init__()
        uic.loadUi('ws_ui.ui', self)
        self.con = sqlite3.connect("ws_database.db")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)

        self.create_linechart()
        self.tmp, self.hmd, self.prs = 0, 0, 0
        self.make_measure()

        self.measure_timer = QTimer(self)
        self.measure_timer.setInterval(MEASURE_FREQUENCIES * 1000)
        self.measure_timer.timeout.connect(self.make_measure)
        self.measure_timer.start()

        self.update_timer = QTimer(self)
        self.update_timer.setInterval(1000)
        self.update_timer.timeout.connect(self.update_labels)
        self.update_timer.start()

        self.update_labels()

    def quit(self):
        self.destroy()
        quit()

    def make_measure(self):
        sns = sensor_measure()

        if sns[0] != ERROR_CODE:
            self.tmp = sns[0]

        else:
            print('tmp error')

        if sns[1] != ERROR_CODE:
            self.hmd = sns[1]

        else:
            print('hmd error')

        if sns[2] != ERROR_CODE:
            self.prs = sns[2]

        else:
            print('prs error')

        time = int(dt.datetime.now().timestamp())

        req = """
              INSERT INTO short_term_data(tmp, hmd, prs, time_from_epoch)
              VALUES(?,?,?,?)
              """

        self.con.execute(req, (self.tmp, self.hmd, self.prs, time))
        self.con.commit()

        self.update_linechart()

    def update_labels(self):
        deg = u'\N{DEGREE SIGN}'
        hpa = 'ʰᴾᵃ'
        self.time_label.setText(dt.datetime.now().strftime('%H:%M'))
        self.tmp_label.setText('{} {}C'.format(self.tmp, deg))
        self.hmd_label.setText('{} %'.format(self.hmd))
        self.prs_label.setText('{} {}'.format(self.prs, hpa))

    def create_linechart(self):
        self.chart = QChart()
        self.chart.legend().hide()

        self.series = QLineSeries()

        self.axisValue = QValueAxis()
        self.axisCurrentTime = QValueAxis()
        self.axisTime = QDateTimeAxis()
        self.axisTime.setFormat("hh:mm")

        self.chartview = QChartView(self.chart, self.groupBox)
        self.chartview.resize(540, 460)
        self.chartview.move(0, 0)
        self.chartview.setRenderHint(QPainter.Antialiasing)

    def update_linechart(self):
        if self.axisTime in self.chart.axes():
            self.chart.removeAxis(self.axisTime)

        if self.axisCurrentTime in self.chart.axes():
            self.chart.removeAxis(self.axisCurrentTime)

        if self.axisValue in self.chart.axes():
            self.chart.removeAxis(self.axisValue)

        if self.series in self.chart.series():
            self.chart.removeSeries(self.series)

        self.series.clear()

        self.axisValue.setMax(50)
        self.axisValue.setMin(-50)

        req = """
              SELECT tmp, time_from_epoch
              FROM short_term_data
              WHERE (time_from_epoch - ?) < 86400 AND NOT tmp = ?
              """

        cur = self.con.cursor()
        result = list(cur.execute(req, (int(dt.datetime.now().timestamp()), ERROR_CODE)))

        for measure in result:
            self.series.append(measure[1] * 1000, measure[0])

        self.axisTime.setMin(QDateTime.fromMSecsSinceEpoch(int(dt.datetime.now().timestamp()) * 1000 - 86390000))
        self.axisTime.setMax(QDateTime.fromMSecsSinceEpoch(int(dt.datetime.now().timestamp()) * 1000))

        self.chart.addSeries(self.series)
        self.chart.addAxis(self.axisTime, Qt.AlignBottom)
        self.series.attachAxis(self.axisTime)
        self.chart.addAxis(self.axisValue, Qt.AlignLeft)
        self.series.attachAxis(self.axisValue)

        self.chart.setTitle('Температура')