예제 #1
0
 def add_data(self, xdata, ydata, color=None):
     curve = QLineSeries()
     pen = curve.pen()
     if color is not None:
         pen.setColor(color)
     pen.setWidthF(.1)
     curve.setPen(pen)
     curve.setUseOpenGL(True)
     curve.append(series_to_polyline(xdata, ydata))
     self.chart.addSeries(curve)
     self.chart.createDefaultAxes()
     self.ncurves += 1
예제 #2
0
    def add_data(self, xdata, ydata, color=None, legend_text=None):
        curve = QLineSeries()
        pen = curve.pen()
        if color is not None:
            pen.setColor(color)
        pen.setWidthF(1.5)

        curve.setPen(pen)
        # curve.setPointsVisible(True)

        # curve.setUseOpenGL(True)

        self.total_samples = max(self.total_samples, len(xdata))

        # Decimate
        xdecimated, ydecimated = self.decimate(xdata, ydata)

        # Data must be in ms since epoch
        # curve.append(self.series_to_polyline(xdecimated * 1000.0, ydecimated))
        # self.reftime = datetime.datetime.fromtimestamp(xdecimated[0])

        # if len(xdecimated) > 0:
        #    xdecimated = xdecimated - xdecimated[0]

        xdecimated *= 1000  # No decimal expected
        points = []
        for i, _ in enumerate(xdecimated):
            # TODO hack
            # curve.append(QPointF(xdecimated[i], ydecimated[i]))
            points.append(QPointF(xdecimated[i], ydecimated[i]))

        curve.replace(points)
        points.clear()

        if legend_text is not None:
            curve.setName(legend_text)

        # Needed for mouse events on series
        self.chart.setAcceptHoverEvents(True)
        self.xvalues[self.ncurves] = np.array(xdecimated)

        # connect signals / slots
        # curve.clicked.connect(self.lineseries_clicked)
        # curve.hovered.connect(self.lineseries_hovered)

        # Add series
        self.chart.addSeries(curve)
        self.ncurves += 1
        self.update_axes()
 def add_data(self, data, chart, color=None):
     curve = QLineSeries(chart)
     curve.setName("latency")
     pen = curve.pen()
     if color is not None:
         pen.setColor(color)
     pen.setWidthF(1)
     curve.setPen(pen)
     curve.setUseOpenGL(True)
     for x in data:
         curve.append(x[0], x[1])
     # curve.append(series_to_polyline(xdata, ydata))
     chart.addSeries(curve)
     chart.createDefaultAxes()
     return curve
예제 #4
0
    def __drawBode(self):
        self.chart.removeAllSeries()  #删除所有序列
        ## 创建序列
        pen = QPen(Qt.red)
        pen.setWidth(2)

        seriesMag = QLineSeries()  #幅频曲线序列
        seriesMag.setName("幅频曲线")
        seriesMag.setPen(pen)
        seriesMag.setPointsVisible(False)
        seriesMag.hovered.connect(self.do_seriesMag_hovered)

        seriesPhase = QLineSeries()  #相频曲线序列
        pen.setColor(Qt.blue)
        seriesPhase.setName("相频曲线")
        seriesPhase.setPen(pen)
        seriesPhase.setPointsVisible(True)
        seriesPhase.hovered.connect(self.do_seriesPhase_hovered)

        ## 为序列添加数据点
        count = len(self.__vectW)  #数据点数
        for i in range(count):
            seriesMag.append(self.__vectW[i], self.__vectMag[i])
            seriesPhase.append(self.__vectW[i], self.__VectPhase[i])

    ##设置坐标轴范围
        minMag = min(self.__vectMag)
        maxMag = max(self.__vectMag)
        minPh = min(self.__VectPhase)
        maxPh = max(self.__VectPhase)
        self.__axisMag.setRange(minMag, maxMag)
        self.__axisPhase.setRange(minPh, maxPh)

        ##序列添加到chart,并指定坐标轴
        self.chart.addSeries(seriesMag)
        seriesMag.attachAxis(self.__axisFreq)
        seriesMag.attachAxis(self.__axisMag)

        self.chart.addSeries(seriesPhase)
        seriesPhase.attachAxis(self.__axisFreq)
        seriesPhase.attachAxis(self.__axisPhase)

        for marker in self.chart.legend().markers():  #QLegendMarker类型列表
            marker.clicked.connect(self.do_LegendMarkerClicked)
예제 #5
0
class PeersCountGraphView(BaseTimedGraph):
    peersCountFetched = AsyncSignal(int)

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

        self.setObjectName('PeersCountGraph')
        self.peersCountFetched.connectTo(self.onPeersCount)
        self.axisY.setTitleText(iPeers())

        pen = QPen(QColor('#60cccf'))
        pen.setWidth(2)

        self.seriesPeers = QLineSeries()
        self.seriesPeers.setName('Peers')
        self.seriesPeers.setPen(pen)
        self.chart.addSeries(self.seriesPeers)
        self.seriesPeers.attachAxis(self.axisX)
        self.seriesPeers.attachAxis(self.axisY)

        self.setChart(self.chart)

    async def onPeersCount(self, count):
        dtNow = QDateTime.currentDateTime()
        dtMsecs = dtNow.toMSecsSinceEpoch()

        delta = 120 * 1000
        if not self.seriesPurgedT or (dtMsecs - self.seriesPurgedT) > delta:
            self.removeOldSeries(self.seriesPeers, dtMsecs - delta)
            self.seriesPurgedT = dtMsecs

        peersVector = self.seriesPeers.pointsVector()
        values = [p.y() for p in peersVector]

        if values:
            self.axisY.setMax(max(values) + 10)
            self.axisY.setMin(min(values) - 10)

        dateMin = QDateTime.fromMSecsSinceEpoch(dtMsecs - (30 * 1000))
        dateMax = QDateTime.fromMSecsSinceEpoch(dtMsecs + 2000)

        self.seriesPeers.append(dtMsecs, count)
        self.axisX.setRange(dateMin, dateMax)
예제 #6
0
   def do_redrawWave(self):
      self.chart.removeAllSeries()  # 删除所有序列
      pen=QPen(self.__colorLine)    # 曲线颜色
      pen.setWidth(2)
      seriesWave = QLineSeries() 
      seriesWave.setUseOpenGL(True) 
      seriesWave.setPen(pen)

      vx=0
      intv=0.001  #1000Hz采样
      pointCount=len(self.__vectData)
      for i in range(pointCount):
         value=self.__vectData[i]
         seriesWave.append(vx,value)
         vx =vx+ intv
      self.__axisX.setRange(0,vx)

      self.chart.addSeries(seriesWave)
      seriesWave.attachAxis(self.__axisX)
      seriesWave.attachAxis(self.__axisY)
예제 #7
0
    def add_data(self, xdata, ydata, color=None, legend_text=None):
        curve = QLineSeries()
        pen = curve.pen()
        if color is not None:
            pen.setColor(color)
        pen.setWidthF(1.5)
        curve.setPen(pen)

        #curve.setUseOpenGL(True)

        # Decimate
        xdecimated, ydecimated = self.decimate(xdata, ydata)

        # Data must be in ms since epoch
        # curve.append(self.series_to_polyline(xdecimated * 1000.0, ydecimated))
        for i in range(len(xdecimated)):
            # TODO hack
            x = xdecimated[i] - xdecimated[0]
            curve.append(QPointF(x, ydecimated[i]))

        self.reftime = datetime.datetime.fromtimestamp(xdecimated[0])

        if legend_text is not None:
            curve.setName(legend_text)

        # Needed for mouse events on series
        self.chart.setAcceptHoverEvents(True)

        # connect signals / slots
        # curve.clicked.connect(self.lineseries_clicked)
        # curve.hovered.connect(self.lineseries_hovered)

        # Add series
        self.chart.addSeries(curve)
        self.ncurves += 1
        self.update_axes()
예제 #8
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']))
예제 #9
0
파일: chart.py 프로젝트: kdurant/workTools
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]))
예제 #10
0
    def initChart(self):
        series = QLineSeries()

        data = [
            QPoint(0, 4),
            QPoint(3, 2),
            QPoint(7, 7),
            QPoint(9, 10),
            QPoint(12, 17),
            QPoint(17, 9),
            QPoint(20, 22),
            QPoint(22, 2),
            QPoint(28, 13)
        ]

        series.append(data)

        # creating chart object
        chart = QChart()
        chart.legend().hide()
        chart.addSeries(series)

        pen = QPen(QColor(0, 0, 128))
        pen.setWidth(3)
        series.setPen(pen)

        font = QFont("Open Sans")
        font.setPixelSize(40)
        font.setBold(True)
        chart.setTitleFont(font)
        chart.setTitleBrush(QBrush(Qt.yellow))
        chart.setTitle("Custom Chart Demo")

        backgroundGradient = QLinearGradient()
        backgroundGradient.setStart(QPoint(0, 0))
        backgroundGradient.setFinalStop(QPoint(0, 1))
        backgroundGradient.setColorAt(0.0, QColor(175, 201, 182))
        backgroundGradient.setColorAt(1.0, QColor(51, 105, 66))
        backgroundGradient.setCoordinateMode(QGradient.ObjectBoundingMode)
        chart.setBackgroundBrush(backgroundGradient)

        plotAreaGraident = QLinearGradient()
        plotAreaGraident.setStart(QPoint(0, 1))
        plotAreaGraident.setFinalStop(QPoint(1, 0))
        plotAreaGraident.setColorAt(0.0, QColor(222, 222, 222))
        plotAreaGraident.setColorAt(1.0, QColor(51, 105, 66))
        plotAreaGraident.setCoordinateMode(QGradient.ObjectBoundingMode)
        chart.setPlotAreaBackgroundBrush(plotAreaGraident)
        chart.setPlotAreaBackgroundVisible(True)

        # customize axis
        axisX = QCategoryAxis()
        axisY = QCategoryAxis()

        labelFont = QFont("Open Sans")
        labelFont.setPixelSize(25)

        axisX.setLabelsFont(labelFont)
        axisY.setLabelsFont(labelFont)

        axisPen = QPen(Qt.white)
        axisPen.setWidth(2)

        axisX.setLinePen(axisPen)
        axisY.setLinePen(axisPen)

        axisBrush = QBrush(Qt.white)
        axisX.setLabelsBrush(axisBrush)
        axisY.setLabelsBrush(axisBrush)

        axisX.setRange(0, 30)
        axisX.append("low", 10)
        axisX.append("medium", 20)
        axisX.append("high", 30)

        axisY.setRange(0, 30)
        axisY.append("slow", 10)
        axisY.append("average", 20)
        axisY.append("fast", 30)

        axisX.setGridLineVisible(False)
        axisY.setGridLineVisible(False)

        chart.addAxis(axisX, Qt.AlignBottom)
        chart.addAxis(axisY, Qt.AlignLeft)

        series.attachAxis(axisX)
        series.attachAxis(axisY)

        self.chartView = QChartView(chart)
        self.chartView.setRenderHint(QPainter.Antialiasing)
예제 #11
0
   def __createChart(self):  ##创建图表
      chart = QChart()  #创建 Chart
   ##      chart.setTitle("简单函数曲线")
      chart.legend().setVisible(True)
      self.chartView.setChart(chart)   #Chart添加到chartView

      pen=QPen()
      pen.setWidth(2)

   ##========LineSeries折线 和 ScatterSeries散点
      seriesLine = QLineSeries()
      seriesLine.setName("LineSeries折线")
      seriesLine.setPointsVisible(False)     #数据点不可见
      pen.setColor(Qt.red)
      seriesLine.setPen(pen)
      seriesLine.hovered.connect(self.do_series_hovered)    #信号 hovered
      seriesLine.clicked.connect(self.do_series_clicked)    #信号 clicked
      chart.addSeries(seriesLine)   #添加到chart

      seriesLinePoint = QScatterSeries()    #散点序列
      seriesLinePoint.setName("ScatterSeries散点")
      shape=QScatterSeries.MarkerShapeCircle  #MarkerShapeRectangle
      seriesLinePoint.setMarkerShape(shape)   #散点形状,只有2种
      seriesLinePoint.setBorderColor(Qt.yellow)
      seriesLinePoint.setBrush(QBrush(Qt.red))
      seriesLinePoint.setMarkerSize(10)      #散点大小
      seriesLinePoint.hovered.connect(self.do_series_hovered)  #信号 hovered
      seriesLinePoint.clicked.connect(self.do_series_clicked)  #信号 clicked
      chart.addSeries(seriesLinePoint)    #添加到chart

   ##======== SplineSeries 曲线和 QScatterSeries 散点
      seriesSpLine = QSplineSeries()
      seriesSpLine.setName("SplineSeries曲线")
      seriesSpLine.setPointsVisible(False)    #数据点不可见
      pen.setColor(Qt.blue)
      seriesSpLine.setPen(pen)
      seriesSpLine.hovered.connect(self.do_series_hovered)  #信号 hovered
      seriesSpLine.clicked.connect(self.do_series_clicked)  #信号 clicked


      seriesSpPoint = QScatterSeries()    #散点序列
      seriesSpPoint.setName("QScatterSeries")
      shape=QScatterSeries.MarkerShapeRectangle  #MarkerShapeCircle
      seriesSpPoint.setMarkerShape(shape) #散点形状,只有2种
      seriesSpPoint.setBorderColor(Qt.green)
      seriesSpPoint.setBrush(QBrush(Qt.blue))
      seriesSpPoint.setMarkerSize(10)     #散点大小
      seriesSpPoint.hovered.connect(self.do_series_hovered) #信号 hovered
      seriesSpPoint.clicked.connect(self.do_series_clicked) #信号 clicked

      chart.addSeries(seriesSpLine)
      chart.addSeries(seriesSpPoint)

   ##  创建缺省坐标轴
      chart.createDefaultAxes()  #创建缺省坐标轴并与序列关联
      chart.axisX().setTitleText("time(secs)")
      chart.axisX().setRange(0,10)
      chart.axisX().applyNiceNumbers()

      chart.axisY().setTitleText("value")
      chart.axisY().setRange(-2,2)
      chart.axisY().applyNiceNumbers()

      for marker in chart.legend().markers():  #QLegendMarker类型列表
         marker.clicked.connect(self.do_LegendMarkerClicked)
예제 #12
0
class Chart(QChart):
    MIN_X = 0
    MAX_X = 750
    MIN_Y = -1
    MAX_Y = 1
    TICKS = 5
    PENCOLOR = Qt.red
    PENWIDTH = 1

    def __init__(self, parent=None):
        super(Chart, self).__init__(parent)
        self.parent = parent
        # we will draw lines
        self.series = QLineSeries(parent)
        # color and pen-width
        self.series.setPen(QPen(self.PENCOLOR, self.PENWIDTH))

        self.addSeries(self.series)

        self.legend().hide()
        self.__construct_axises()

    def setRange_X_axis(self, min_X, max_X):
        self.MIN_X = min_X
        self.MAX_X = max_X
        self.axisX().setRange(self.MIN_X, self.MAX_X)

    def setRange_Y_axis(self, min_Y, max_Y):
        self.MIN_Y = min_Y
        self.MAX_Y = max_Y
        self.axisY().setRange(self.MIN_Y, self.MAX_Y)

    def add_point(self, x, y):
        self.series.append(x, y)

    def get_series(self) -> list:
        return self.series.pointsVector()

    def remove_point(self, index):
        self.series.remove(index)

    def remove_points(self, index, count):
        self.series.removePoints(index, count)

    def replace_point(self, index, x, y):
        self.series.replace(index, x, y)

    def replace_series(self, lst):
        self.series.replace(lst)

    def get_series_count(self):
        return self.series.count()

    def __construct_axises(self):
        self.createDefaultAxes()

        # X-Axis
        x_axis = self.axisX()
        x_axis.hide()
        x_axis.setRange(self.MIN_X, self.MAX_X)

        # Y-axis
        y_axis = self.axisY()
        y_axis.setRange(self.MIN_Y, self.MAX_Y)
        y_axis.setTickCount(self.TICKS)
예제 #13
0
def run_evolution():
    range_a = float(str(form.input_a.text()))
    range_b = float(str(form.input_b.text()))
    precision = int(str(form.input_d.text()))
    particles_number = int(str(form.input_particles.text()))
    iterations = int(str(form.input_iterations.text()))
    c1_weight = float(str(form.input_c1.text()))
    c2_weight = float(str(form.input_c2.text()))
    c3_weight = float(str(form.input_c3.text()))
    neighborhood_distance = float(str(form.input_neighborhood.text()))

    app.setOverrideCursor(QtCore.Qt.WaitCursor)

    best_real, best_fx, best_fxs, avg_fxs, min_fxs, particles = evolution(
        range_a, range_b, precision, particles_number, iterations, c1_weight,
        c2_weight, c3_weight, neighborhood_distance)

    chart = QChart()
    bests = QLineSeries()
    avg = QLineSeries()
    mins = QLineSeries()

    pen_best = bests.pen()
    pen_best.setWidth(1)
    pen_best.setBrush(QtGui.QColor("red"))

    pen_avg = avg.pen()
    pen_avg.setWidth(1)
    pen_avg.setBrush(QtGui.QColor("green"))

    pen_min = mins.pen()
    pen_min.setWidth(1)
    pen_min.setBrush(QtGui.QColor("blue"))

    bests.setPen(pen_best)
    avg.setPen(pen_avg)
    mins.setPen(pen_min)

    form.best_table.item(1, 0).setText(str(best_real))
    form.best_table.item(1, 1).setText(str(best_fx))

    for i in range(len(best_fxs)):
        bests.append(i + 1, best_fxs[i])
        avg.append(i + 1, avg_fxs[i])
        mins.append(i + 1, min_fxs[i])

    chart.addSeries(bests)
    chart.addSeries(avg)
    chart.addSeries(mins)

    chart.setBackgroundBrush(QtGui.QColor(41, 43, 47))
    chart.createDefaultAxes()
    chart.legend().hide()
    chart.setContentsMargins(-10, -10, -10, -10)
    chart.layout().setContentsMargins(0, 0, 0, 0)
    chart.axisX().setTickCount(11)
    chart.axisX().setLabelsColor(QtGui.QColor("white"))
    chart.axisX().setGridLineColor(QtGui.QColor("grey"))
    chart.axisX().setLabelFormat("%i")
    chart.axisY().setRange(-2, 2)
    chart.axisY().setLabelsColor(QtGui.QColor("white"))
    chart.axisY().setGridLineColor(QtGui.QColor("grey"))
    form.widget.setChart(chart)

    draw_thread.particles_list = particles
    draw_thread.start()

    app.restoreOverrideCursor()
예제 #14
0
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)
예제 #15
0
    def __drawChart(self):  ##绘制图表
        self.chart.removeAllSeries()  #删除所有序列
        self.chart.setTitle("股票日线图--" + self.ui.tabWidget.tabText(0))

        ## 1. 创建蜡烛图
        seriesCandle = QCandlestickSeries()
        seriesCandle.setName("蜡烛图")
        seriesCandle.setIncreasingColor(Qt.red)  #暴涨
        seriesCandle.setDecreasingColor(Qt.darkGreen)  #暴跌

        visible = self.ui.chkBox_Outline.isChecked()
        seriesCandle.setBodyOutlineVisible(visible)
        seriesCandle.setCapsVisible(self.ui.chkBox_Caps.isChecked())

        self.chart.addSeries(seriesCandle)
        seriesCandle.attachAxis(self.__axisX)
        seriesCandle.attachAxis(self.__axisY)

        seriesCandle.clicked.connect(self.do_candleClicked)
        seriesCandle.hovered.connect(self.do_candleHovered)

        ## 2. 创建MA曲线
        pen = QPen()
        pen.setWidth(2)

        seriesMA1 = QLineSeries()  #不能使用QSplineSeries
        seriesMA1.setName("MA5")
        pen.setColor(Qt.magenta)
        seriesMA1.setPen(pen)
        self.chart.addSeries(seriesMA1)
        seriesMA1.attachAxis(self.__axisX)
        seriesMA1.attachAxis(self.__axisY)

        seriesMA2 = QLineSeries()
        seriesMA2.setName("MA10")
        pen.setColor(Qt.yellow)
        seriesMA2.setPen(pen)
        self.chart.addSeries(seriesMA2)
        seriesMA2.attachAxis(self.__axisX)
        seriesMA2.attachAxis(self.__axisY)

        seriesMA3 = QLineSeries()
        seriesMA3.setName("MA20")
        pen.setColor(Qt.cyan)
        seriesMA3.setPen(pen)
        self.chart.addSeries(seriesMA3)
        seriesMA3.attachAxis(self.__axisX)
        seriesMA3.attachAxis(self.__axisY)

        seriesMA4 = QLineSeries()
        seriesMA4.setName("MA60")
        pen.setColor(Qt.green)  #green
        seriesMA4.setPen(pen)
        self.chart.addSeries(seriesMA4)
        seriesMA4.attachAxis(self.__axisX)
        seriesMA4.attachAxis(self.__axisY)

        ## 3. 填充数据到序列
        dataRowCount = self.itemModel.rowCount()  #数据点个数
        for i in range(dataRowCount):
            dateStr = self.itemModel.item(i, 0).text()  #日期字符串,如"2017/02/03"
            dateValue = QDate.fromString(dateStr, "yyyy/MM/dd")  #QDate
            dtValue = QDateTime(dateValue)  #日期时间 QDateTime
            timeStamp = dtValue.toMSecsSinceEpoch()  #毫秒数

            oneCandle = QCandlestickSet()  #QCandlestickSet
            oneCandle.setOpen(float(self.itemModel.item(i, 1).text()))  #开盘
            oneCandle.setHigh(float(self.itemModel.item(i, 2).text()))  #最高
            oneCandle.setLow(float(self.itemModel.item(i, 3).text()))  #最低
            oneCandle.setClose(float(self.itemModel.item(i, 4).text()))  #收盘
            oneCandle.setTimestamp(timeStamp)  #时间戳
            seriesCandle.append(oneCandle)  #添加到序列

            M1 = float(self.itemModel.item(i, 5).text())
            M2 = float(self.itemModel.item(i, 6).text())
            M3 = float(self.itemModel.item(i, 7).text())
            M4 = float(self.itemModel.item(i, 8).text())

            seriesMA1.append(timeStamp, M1)
            seriesMA2.append(timeStamp, M2)
            seriesMA3.append(timeStamp, M3)
            seriesMA4.append(timeStamp, M4)

    ## 4. 设置坐标轴范围
        minDateStr = self.itemModel.item(0, 0).text()  #日期字符串,如"2017/02/03"
        minDate = QDate.fromString(minDateStr, "yyyy/MM/dd")  #QDate
        minDateTime = QDateTime(minDate)  #最小日期时间,QDateTime

        maxDateStr = self.itemModel.item(dataRowCount - 1,
                                         0).text()  #日期字符串,如"2017/05/03"
        maxDate = QDate.fromString(maxDateStr, "yyyy/MM/dd")
        maxDateTime = QDateTime(maxDate)  #最大日期时间

        self.__axisX.setRange(minDateTime, maxDateTime)  #日期时间范围
        dateFormat = self.ui.comboDateFormat.currentText()  #格式,如"MM-dd"
        self.__axisX.setFormat(dateFormat)  #标签格式

        self.__axisY.applyNiceNumbers()  #自动

        for marker in self.chart.legend().markers():  #QLegendMarker类型列表
            marker.clicked.connect(self.do_LegendMarkerClicked)
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)
예제 #17
0
class RowingMonitorMainWindow(QtWidgets.QMainWindow):
    COLOR_RED = QColor('#E03A3E')
    COLOR_BLUE = QColor('#009DDC')

    DISABLE_LOGGING = False

    PLOT_VISIBLE_SAMPLES = 200
    PLOT_MIN_Y = -1
    PLOT_MAX_Y = 55
    PLOT_TIME_WINDOW_SECONDS = 7
    PLOT_WIDTH_INCHES = 2
    PLOT_HEIGHT_INCHES = 1
    PLOT_DPI = 300
    PLOT_FAST_DRAWING = False

    WORK_PLOT_VISIBLE_STROKES = 64
    WORK_PLOT_MIN_Y = 0
    WORK_PLOT_MAX_Y = 350

    BOAT_SPEED_PLOT_VISIBLE_STROKES = 64
    BOAT_SPEED_PLOT_MIN_Y = 0
    BOAT_SPEED_PLOT_MAX_Y = 10

    GUI_FONT = QtGui.QFont('Nunito SemiBold', 12)
    GUI_FONT_LARGE = QtGui.QFont('Nunito', 24)
    GUI_FONT_MEDIUM = QtGui.QFont('Nunito', 16)

    def __init__(self, config, data_source, *args, **kwargs):
        super(RowingMonitorMainWindow, self).__init__(*args, **kwargs)

        self.setWindowTitle('Rowing Monitor')

        self.config = config
        self.log_folder_path = config.log_folder_path
        self.workout = wo.WorkoutMetricsTracker(
            config=config,
            data_source=data_source
        )

        # Connect workut emitter to UI update
        self.workout_qt_emitter = SignalEmitter()
        self.workout_qt_emitter.updated.connect(self.ui_callback)

        # Setup main window layout
        self.main_widget = QtWidgets.QWidget()
        self.main_widget.setFocus()
        self.setCentralWidget(self.main_widget)
        self.app_layout = QtWidgets.QVBoxLayout(self.main_widget)
        self.app_layout.setContentsMargins(0, 0, 0, 0) #(left, top, right, bottom)

        # Build button bar
        self.button_bar_background_widget = QtWidgets.QWidget(self.main_widget)
        self.button_bar_background_widget.setObjectName('ButtonBarBackground')
        self.button_bar_background_widget.setStyleSheet('QWidget#ButtonBarBackground {background-color: #F1F1F1;}')
        self.button_bar_layout = QtWidgets.QHBoxLayout(self.button_bar_background_widget)
        self.start_button = QtWidgets.QPushButton('Start')
        self.start_button.setFlat(True)

        # Start button style
        palette = self.start_button.palette()
        palette.setColor(palette.Button, QColor('#E03A3E'))
        palette.setColor(palette.ButtonText, QColor('white'))
        self.start_button.setAutoFillBackground(True)
        self.start_button.setPalette(palette)
        self.start_button.update()
        self.start_button.setFont(self.GUI_FONT)
        self.start_button.setMinimumSize(97, 60)
        self.start_button.setMaximumSize(97, 60)

        # Add to main window
        self.button_bar_layout.addWidget(self.start_button)
        #self.button_bar_layout.addWidget(self.button_bar_background_widget)
        self.button_bar_layout.setAlignment(QtCore.Qt.AlignLeft)
        self.button_bar_layout.setContentsMargins(0, 0, 0, 0) #(left, top, right, bottom)
        self.app_layout.addWidget(self.button_bar_background_widget)#.addLayout(self.button_bar_layout)

        self.stats_layout = QtWidgets.QHBoxLayout()
        self.stats_layout.setContentsMargins(0, 0, 0, 0)
        self.stats_layout.setSpacing(0)
        self.app_layout.addLayout(self.stats_layout)

        # Build workout stats bar
        self.metrics_panel_layout = QtWidgets.QVBoxLayout()
        self.charts_panel_layout = QtWidgets.QVBoxLayout()

        self.workout_totals_layout = QtWidgets.QVBoxLayout()
        self.time_label = QtWidgets.QLabel(self._format_total_workout_time(0))
        self.distance_label = QtWidgets.QLabel(self._format_total_workout_distance(0))
        self.time_label.setAlignment(QtCore.Qt.AlignCenter)
        self.distance_label.setAlignment(QtCore.Qt.AlignCenter)
        self.time_label.setFixedHeight(40)
        self.distance_label.setFixedHeight(30)
        self.workout_totals_layout.addWidget(self.time_label)
        self.workout_totals_layout.addWidget(self.distance_label)
        #self.workout_totals_layout.setSpacing(0)
        self.workout_totals_layout.setContentsMargins(0, 0, 0, 30)
        self.metrics_panel_layout.addLayout(self.workout_totals_layout)

        self.stroke_stats_layout = QtWidgets.QVBoxLayout()
        self.spm_label = QtWidgets.QLabel(self._format_strokes_per_minute(99))
        self.stroke_ratio_label = QtWidgets.QLabel(self._format_stroke_ratio(1))
        self.spm_label.setAlignment(QtCore.Qt.AlignCenter)
        self.stroke_ratio_label.setAlignment(QtCore.Qt.AlignCenter)
        self.spm_label.setFixedHeight(40)
        self.stroke_ratio_label.setFixedHeight(30)
        self.stroke_stats_layout.addWidget(self.spm_label)
        self.stroke_stats_layout.addWidget(self.stroke_ratio_label)
        #self.stroke_stats_layout.setSpacing(0)
        self.stroke_stats_layout.setContentsMargins(0, 30, 0, 30)
        self.metrics_panel_layout.addLayout(self.stroke_stats_layout)

        self.boat_stats_layout = QtWidgets.QVBoxLayout()
        self.boat_speed_label = QtWidgets.QLabel(self._format_boat_speed(0))
        self.split_time_label = QtWidgets.QLabel(self._format_boat_pace(0))
        self.boat_speed_label.setAlignment(QtCore.Qt.AlignCenter)
        self.split_time_label.setAlignment(QtCore.Qt.AlignCenter)
        self.boat_speed_label.setFixedHeight(40)
        self.split_time_label.setFixedHeight(30)
        self.boat_stats_layout.addWidget(self.boat_speed_label)
        self.boat_stats_layout.addWidget(self.split_time_label)
        #self.boat_stats_layout.setSpacing(0)
        self.boat_stats_layout.setContentsMargins(0, 30, 0, 0)
        self.metrics_panel_layout.addLayout(self.boat_stats_layout)

        # Appearance
        self.time_label.setFont(self.GUI_FONT_LARGE)
        self.distance_label.setFont(self.GUI_FONT_MEDIUM)
        self.spm_label.setFont(self.GUI_FONT_LARGE)
        self.stroke_ratio_label.setFont(self.GUI_FONT_MEDIUM)
        self.boat_speed_label.setFont(self.GUI_FONT_LARGE)
        self.split_time_label.setFont(self.GUI_FONT_MEDIUM)


        # Add to main window
        self.metrics_panel_layout.setSpacing(0)
        self.metrics_panel_layout.setContentsMargins(60, 30, 30, 30) #(left, top, right, bottom)
        self.charts_panel_layout.setSpacing(30)
        self.charts_panel_layout.setContentsMargins(30, 30, 60, 60)#(30, 30, 60, 60) #(left, top, right, bottom)
        self.stats_layout.addLayout(self.metrics_panel_layout)
        self.stats_layout.addLayout(self.charts_panel_layout)

        self.xdata = [0.0 for i in range(self.PLOT_VISIBLE_SAMPLES)]
        self.ydata = [0.0 for i in range(self.PLOT_VISIBLE_SAMPLES)]

        self.work_per_stroke_data = [0.0 for i in range(self.WORK_PLOT_VISIBLE_STROKES)]
        self.boat_speed_data = [0.0 for i in range(self.WORK_PLOT_VISIBLE_STROKES)]
        self.seen_strokes = 0

        ############################################
        # Add torque chart
        self.torque_plot = QChart()
        self.torque_plot.setContentsMargins(-26, -26, -26, -26)
        #self.torque_plot.setAnimationOptions(QChart.GridAxisAnimations)
        self.torque_plot.legend().setVisible(False)
        self.torque_plot_horizontal_axis = QValueAxis()
        self.torque_plot_vertical_axis = QValueAxis()
        self.torque_plot.addAxis(self.torque_plot_vertical_axis, QtCore.Qt.AlignLeft)
        self.torque_plot.addAxis(self.torque_plot_horizontal_axis, QtCore.Qt.AlignBottom)

        # Line series
        self.torque_plot_series = QLineSeries(self)
        for i in range(self.PLOT_VISIBLE_SAMPLES):
            self.torque_plot_series.append(0, 0)
        #self.torque_plot_series.setColor(QColor('#009DDC'))
        pen = self.torque_plot_series.pen()
        pen.setWidth(3)
        pen.setColor(self.COLOR_BLUE)
        pen.setJoinStyle(QtCore.Qt.RoundJoin)
        pen.setCapStyle(QtCore.Qt.RoundCap)
        self.torque_plot_series.setPen(pen)

        # Area series
        self.torque_plot_area_series = QAreaSeries()
        self.torque_plot_area_series.setUpperSeries(self.torque_plot_series)
        self.torque_plot_area_series.setLowerSeries(QLineSeries(self))
        for i in range(self.PLOT_VISIBLE_SAMPLES):
            self.torque_plot_area_series.lowerSeries().append(0, 0)
        self.torque_plot_area_series.setColor(self.COLOR_BLUE)

        # Compose plot
        # self.torque_plot.addSeries(self.torque_plot_area_series)
        # self.torque_plot_area_series.attachAxis(self.torque_plot_horizontal_axis)
        # self.torque_plot_area_series.attachAxis(self.torque_plot_vertical_axis)
        self.torque_plot.addSeries(self.torque_plot_series)
        self.torque_plot_series.attachAxis(self.torque_plot_horizontal_axis)
        self.torque_plot_series.attachAxis(self.torque_plot_vertical_axis)

        # Set axes range
        self.torque_plot_vertical_axis.setRange(self.PLOT_MIN_Y, self.PLOT_MAX_Y)
        #self.torque_plot_vertical_axis.setTickCount(10)
        self.torque_plot_vertical_axis.setVisible(False)
        self.torque_plot_horizontal_axis.setRange(-self.PLOT_TIME_WINDOW_SECONDS, 0)
        self.torque_plot_horizontal_axis.setVisible(False)

        # Add plot view to GUI
        self.torque_plot_chartview = QChartView(self.torque_plot)
        self.torque_plot_chartview.setRenderHint(QPainter.Antialiasing)
        #self.torque_plot_chartview.setMinimumHeight(250)
        #self.torque_plot_chartview.resize(250, 250)

        self.torque_plot_box = QtWidgets.QGroupBox("Force")
        self.torque_plot_box.setFont(self.GUI_FONT)
        self.torque_plot_box.setAlignment(QtCore.Qt.AlignLeft)
        self.torque_plot_box_layout = QtWidgets.QVBoxLayout()
        self.torque_plot_box_layout.addWidget(self.torque_plot_chartview)
        self.torque_plot_box.setLayout(self.torque_plot_box_layout)

        self.charts_panel_layout.addWidget(self.torque_plot_box)
        ############################################

        ############################################
        # Add work chart
        self.work_plot = QChart()
        self.work_plot.setContentsMargins(-26, -26, -26, -26)
        self.work_plot.legend().setVisible(False)
        self.work_plot_horizontal_axis = QBarCategoryAxis()
        self.work_plot_vertical_axis = QValueAxis()
        self.work_plot.addAxis(self.work_plot_vertical_axis, QtCore.Qt.AlignLeft)
        self.work_plot.addAxis(self.work_plot_horizontal_axis, QtCore.Qt.AlignBottom)

        # Define series
        self.work_plot_series = QBarSeries()
        self.work_plot_bar_set_list = [QBarSet(str(i)) for i in range(self.WORK_PLOT_VISIBLE_STROKES)]
        self.work_plot_series.append(self.work_plot_bar_set_list)
        for bar_set in self.work_plot_bar_set_list:
            bar_set.append(0)
        self.work_plot_series.setBarWidth(1.0)

        # Compose plot
        self.work_plot.addSeries(self.work_plot_series)
        self.work_plot_series.attachAxis(self.work_plot_horizontal_axis)
        self.work_plot_series.attachAxis(self.work_plot_vertical_axis)

        # Set axes range
        self.work_plot_vertical_axis.setRange(self.WORK_PLOT_MIN_Y, self.WORK_PLOT_MAX_Y)
        self.work_plot_vertical_axis.setTickCount(8)
        self.work_plot_vertical_axis.setVisible(False)
        self.work_plot_horizontal_axis.append("1")
        self.work_plot_horizontal_axis.setVisible(False)

        # Add plot view to GUI
        self.work_plot_chartview = QChartView(self.work_plot)
        self.work_plot_chartview.setRenderHint(QPainter.Antialiasing)
        #self.work_plot_chartview.setMinimumHeight(250)
        #self.work_plot_chartview.resize(250, 250)

        self.work_plot_box = QtWidgets.QGroupBox("Work per stroke")
        self.work_plot_box.setFont(self.GUI_FONT)

        self.work_plot_box.setAlignment(QtCore.Qt.AlignLeft)
        self.work_plot_box_layout = QtWidgets.QVBoxLayout()
        self.work_plot_box_layout.addWidget(self.work_plot_chartview)
        self.work_plot_box.setLayout(self.work_plot_box_layout)

        self.charts_panel_layout.addWidget(self.work_plot_box)
        ############################################

        ############################################
        # Add boat speed chart
        self.boat_speed_plot = QChart()
        self.boat_speed_plot.setContentsMargins(-26, -26, -26, -26)
        #self.boat_speed_plot.setBackgroundRoundness(0)
        self.boat_speed_plot.legend().setVisible(False)
        self.boat_speed_plot_horizontal_axis = QBarCategoryAxis()
        self.boat_speed_plot_vertical_axis = QValueAxis()
        self.boat_speed_plot.addAxis(self.boat_speed_plot_vertical_axis, QtCore.Qt.AlignLeft)
        self.boat_speed_plot.addAxis(self.boat_speed_plot_horizontal_axis, QtCore.Qt.AlignBottom)

        # Define series
        self.boat_speed_plot_series = QBarSeries()
        self.boat_speed_plot_bar_set_list = [QBarSet(str(i)) for i in range(self.BOAT_SPEED_PLOT_VISIBLE_STROKES)]
        self.boat_speed_plot_series.append(self.boat_speed_plot_bar_set_list)
        for bar_set in self.boat_speed_plot_bar_set_list:
            bar_set.append(0)
        self.boat_speed_plot_series.setBarWidth(1.0)

        # Compose plot
        self.boat_speed_plot.addSeries(self.boat_speed_plot_series)
        self.boat_speed_plot_series.attachAxis(self.boat_speed_plot_horizontal_axis)
        self.boat_speed_plot_series.attachAxis(self.boat_speed_plot_vertical_axis)

        # Set axes range
        self.boat_speed_plot_vertical_axis.setRange(self.BOAT_SPEED_PLOT_MIN_Y, self.BOAT_SPEED_PLOT_MAX_Y)
        self.boat_speed_plot_vertical_axis.setTickCount(8)
        self.boat_speed_plot_vertical_axis.setVisible(False)
        self.boat_speed_plot_horizontal_axis.append("1")
        self.boat_speed_plot_horizontal_axis.setVisible(False)

        # Add plot view to GUI
        self.boat_speed_plot_chartview = QChartView(self.boat_speed_plot)
        self.boat_speed_plot_chartview.setRenderHint(QPainter.Antialiasing)
        #self.boat_speed_plot_chartview.setContentsMargins(0, 0, 0, 0)
        self.boat_speed_plot_box = QtWidgets.QGroupBox("Boat speed")
        self.boat_speed_plot_box.setFont(self.GUI_FONT)
        #self.boat_speed_plot_box.setFlat(True)
        #self.boat_speed_plot_box.setContentsMargins(0, 0, 0, 0)
        #self.boat_speed_plot_box.setObjectName("BoatSpeedGB")  # Changed here...
        #self.boat_speed_plot_box.setStyleSheet('QGroupBox {background-color: white;}')
        #self.main_widget.setStyleSheet('QGroupBox::title { background-color: blue }')

        self.boat_speed_plot_box.setAlignment(QtCore.Qt.AlignLeft)
        self.boat_speed_plot_box_layout = QtWidgets.QVBoxLayout()
        self.boat_speed_plot_box_layout.addWidget(self.boat_speed_plot_chartview)
        self.boat_speed_plot_box.setLayout(self.boat_speed_plot_box_layout)

        self.charts_panel_layout.addWidget(self.boat_speed_plot_box)


        ############################################

        # Set interaction behavior
        self.start_button.clicked.connect(self.start)

        # Update workout duration every second
        self.timer = QtCore.QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.timer_tick)

        self.start_timestamp = None
        self.started = False

        self.show()

    def update_torque_plot(self):
        self.torque_plot_series.append(self.xdata[-1], self.ydata[-1])
        self.torque_plot_series.remove(0)
        self.torque_plot_area_series.lowerSeries().append(self.xdata[-1], 0)
        self.torque_plot_area_series.lowerSeries().remove(0)
        self.torque_plot_horizontal_axis.setRange(self.xdata[-1] - self.PLOT_TIME_WINDOW_SECONDS, self.xdata[-1])

    def update_work_plot(self):
        # Create new bar set
        new_bar_set = QBarSet(str(self.seen_strokes))
        value = self.work_per_stroke_data[-1]
        value_rel = int(value * 255 / self.WORK_PLOT_MAX_Y)
        new_bar_set.append(value)
        new_bar_set.setColor(self.COLOR_BLUE)  # QColor(value_rel, value_rel, value_rel))
        # Append new set, and remove oldest
        self.work_plot_series.append(new_bar_set)
        self.work_plot_series.remove(self.work_plot_series.barSets()[0])

    def update_boat_speed_plot(self):
        # Create new bar set
        new_bar_set = QBarSet(str(self.seen_strokes))
        value = self.boat_speed_data[-1]
        value_rel = int(value * 255 / self.BOAT_SPEED_PLOT_MAX_Y)
        new_bar_set.append(value)
        new_bar_set.setColor(self.COLOR_BLUE) # QColor(value_rel, value_rel, value_rel))
        # Append new set, and remove oldest
        self.boat_speed_plot_series.append(new_bar_set)
        self.boat_speed_plot_series.remove(self.boat_speed_plot_series.barSets()[0])

    def start(self):
        if not self.started:
            self.start_workout()
            self.start_button.setText('Stop')
            self.started = True
        else:
            self.stop_workout()
            self.start_button.setText('Start')
            self.started = False

    def start_workout(self):
        self.timer.start()
        self.workout.start(qt_signal_emitter=self.workout_qt_emitter)

    def stop_workout(self):
        self.timer.stop()
        self.workout.stop()
        if not self.DISABLE_LOGGING and not DEV_MODE:
            self.workout.save(output_folder_path=self.log_folder_path)

    def _format_total_workout_time(self, value_seconds):
        minutes = value_seconds // 60
        seconds = value_seconds % 60
        return '%d:%02d' % (minutes, seconds)

    def _format_total_workout_distance(self, value):
        return f'{int(value):,} m'

    def _format_strokes_per_minute(self, value):
        return '%.1f spm' % value

    def _format_stroke_ratio(self, value):
        return '1:%.1f ratio' % value

    def _format_boat_speed(self, value):
        return '%0.2f m/s' % value

    def _format_boat_pace(self, value_seconds):
        return '%s /500m' % (self._format_total_workout_time(value_seconds))

    def ui_callback(self):
        # If this is the first pulse, capture the current time
        if self.start_timestamp is None:
            self.start_timestamp = QtCore.QTime.currentTime()
        # Update distance
        distance = self.workout.boat.position.values[-1]
        self.distance_label.setText(self._format_total_workout_distance(distance))
        if len(self.workout.person.torque) > 0:
            self.ydata = self.ydata[1:] + [self.workout.person.torque.values[-1]]
            self.xdata = self.xdata[1:] + [self.workout.person.torque.timestamps[-1]]
            self.update_torque_plot()
        # Update SPM
        new_stroke_info_available = len(self.workout.person.strokes) > self.seen_strokes
        if new_stroke_info_available:
            # SPM indicator
            spm = 60 / self.workout.person.strokes.values[-1].duration
            ratio = self.workout.person.strokes.values[-1].drive_to_recovery_ratio
            self.spm_label.setText(self._format_strokes_per_minute(spm))
            self.stroke_ratio_label.setText(self._format_stroke_ratio(ratio))
            # Work plot
            self.work_per_stroke_data = self.work_per_stroke_data[1:] + \
                                        [self.workout.person.strokes.values[-1].work_done_by_person]
            self.update_work_plot()
            self.seen_strokes += 1
            # Boat speed plot
            average_boat_speed = self.workout.boat.speed.get_average_value(
                start_time=self.workout.person.strokes.values[-1].start_time,
                end_time=self.workout.person.strokes.values[-1].end_time
            )
            self.boat_speed_data = self.boat_speed_data[1:] + [average_boat_speed]
            self.boat_speed_label.setText(self._format_boat_speed(average_boat_speed))
            split_time_seconds = 500.0 / average_boat_speed
            self.split_time_label.setText(self._format_boat_pace(split_time_seconds))
            self.update_boat_speed_plot()

    def timer_tick(self):
        # Do nothing if we haven't received an encoder pulse yet.
        if self.start_timestamp is None:
            return
        # Update workout time label
        time_since_start = self.start_timestamp.secsTo(QtCore.QTime.currentTime())
        self.time_label.setText(self._format_total_workout_time(time_since_start))
예제 #18
0
   def do_redrawFill(self):
      self.chart.removeAllSeries()  #删除所有序列
      pen=QPen(self.__colorLine)    #线条颜色
      pen.setWidth(2)

      seriesFullWave = QLineSeries()      #全波形
      seriesFullWave.setUseOpenGL(True)
      seriesFullWave.setPen(pen)

      seriesPositive = QLineSeries()      #正半部分曲线
      seriesPositive.setUseOpenGL(True)
      seriesPositive.setVisible(False)    #不显示

      seriesNegative = QLineSeries()      #负半部分曲线
      seriesNegative.setUseOpenGL(True)
      seriesNegative.setVisible(False)    #不显示即可

      seriesZero = QLineSeries()          #零均值线
      seriesZero.setUseOpenGL(True)
      seriesZero.setVisible(False)        #不显示即可

   ## 填充数据
      vx=0
      intv=0.001   #1000Hz采样,数据点间隔时间
      pointCount=len(self.__vectData)
      for i in range(pointCount):
         value=self.__vectData[i]
         seriesFullWave.append(vx,value)  #完整波形
         seriesZero.append(vx,0)          #零值线
         if value>0:
            seriesPositive.append(vx,value)  #正半部分波形
            seriesNegative.append(vx,0)
         else:
            seriesPositive.append(vx,0)
            seriesNegative.append(vx,value) #负半部分波形
         vx =vx+intv

      self.__axisX.setRange(0,vx)

   ##  创建QAreaSeries序列,设置上、下界的QLineSeries对象
      pen.setStyle(Qt.NoPen)  #无线条,隐藏填充区域的边线
      if self.ui.radioFill_Pos.isChecked():     #positive fill
         series = QAreaSeries(seriesPositive, seriesZero) #QAreaSeries
         series.setColor(self.__colorFill)      #填充色
         series.setPen(pen)   #不显示线条
         self.chart.addSeries(series)
         series.attachAxis(self.__axisX)
         series.attachAxis(self.__axisY)
         
      elif self.ui.radioFill_Neg.isChecked():  #negative fill
         series = QAreaSeries(seriesZero,seriesNegative)
         series.setColor(self.__colorFill)
         series.setPen(pen)   #不显示线条
         self.chart.addSeries(series)
         series.attachAxis(self.__axisX)
         series.attachAxis(self.__axisY)

      elif self.ui.radioFill_Both.isChecked():  #both fill
         series = QAreaSeries(seriesZero,seriesFullWave)
         series.setColor(self.__colorFill)
         series.setPen(pen)   #不显示线条
         self.chart.addSeries(series)
         series.attachAxis(self.__axisX)
         series.attachAxis(self.__axisY)

      series.clicked.connect(self.do_area_clicked)  #关联槽函数
         
   ## 构建QAreaSeries的两个QLineSeries序列必须添加到chart里,否则程序崩溃
      self.chart.addSeries(seriesZero)       #隐藏
      self.chart.addSeries(seriesPositive)   #隐藏
      self.chart.addSeries(seriesNegative)   #隐藏
      self.chart.addSeries(seriesFullWave)   #全波形曲线,显示

      seriesPositive.attachAxis(self.__axisX)
      seriesPositive.attachAxis(self.__axisY)

      seriesNegative.attachAxis(self.__axisX)
      seriesNegative.attachAxis(self.__axisY)

      seriesZero.attachAxis(self.__axisX)
      seriesZero.attachAxis(self.__axisY)
      
      seriesFullWave.attachAxis(self.__axisX)
      seriesFullWave.attachAxis(self.__axisY)
예제 #19
0
class Graph(QChartView):
	def __init__(self, parent=None):
		super().__init__(parent=parent)

		self.setpoint_temperature = None

		self.chart = QChart()
		self.chart.legend().hide()
		self.setChart( self.chart )
		self.setRenderHint(QPainter.Antialiasing)
		self.chart.setPlotAreaBackgroundBrush( QBrush(Qt.black) )
		self.chart.setPlotAreaBackgroundVisible( True )

		self.setpointTemperatureSeries = QLineSeries( self.chart )
		pen = self.setpointTemperatureSeries.pen()
		pen.setWidthF(2.)
		pen.setColor( Qt.green )
		self.setpointTemperatureSeries.setPen( pen )
		#self.setpointTemperatureSeries.setUseOpenGL( True )
		self.chart.addSeries( self.setpointTemperatureSeries )

		self.temperatureSeries = QLineSeries( self.chart )
		pen = self.temperatureSeries.pen()
		pen.setWidthF(2.)
		pen.setColor( Qt.red )
		self.temperatureSeries.setPen( pen )
		#self.temperatureSeries.setUseOpenGL( True )
		self.chart.addSeries( self.temperatureSeries )

		self.number_of_samples_to_keep = 2 * 5 * 60

		self.xMin = QDateTime.currentDateTime().toMSecsSinceEpoch()
		self.xMax = QDateTime.currentDateTime().toMSecsSinceEpoch()
		self.yMin = 400
		self.yMax = 0

		#self.chart.createDefaultAxes()
		#x_axis = QValueAxis()
		x_axis = QDateTimeAxis()
		x_axis.setTitleText( "Time" )
		x_axis.setFormat("HH:mm:ss")
		self.chart.addAxis( x_axis, Qt.AlignBottom )
		self.temperatureSeries.attachAxis( x_axis )
		self.setpointTemperatureSeries.attachAxis( x_axis )
		startDate = QDateTime.currentDateTime().addSecs( -5 * 60 )
		endDate = QDateTime.currentDateTime().addSecs( 5 * 60 )
		#startDate = QDateTime(QDate(2017, 1, 9), QTime(17, 25, 0))
		#endDate = QDateTime(QDate(2017, 1, 9), QTime(17, 50, 0))
		#self.chart.axisX().setRange( startDate, endDate )
		#self.chart.axisX().setRange( 0, 100 )

		y_axis = QValueAxis()
		y_axis.setTitleText( "Temperature (K)" )
		self.chart.addAxis( y_axis, Qt.AlignLeft )
		self.temperatureSeries.attachAxis( y_axis )
		self.setpointTemperatureSeries.attachAxis( y_axis )
		self.chart.axisY().setRange( 0, 400 )
		#self.chart.axisY().setRange( 260., 290. )

		self.temperatureSeries.pointAdded.connect( self.Rescale_Axes )
		#self.setpointTemperatureSeries.pointAdded.connect( self.Rescale_Axes )

		self.setRubberBand( QChartView.HorizontalRubberBand )

		# Customize chart title
		font = QFont()
		font.setPixelSize(24);
		self.chart.setTitleFont(font);
		self.chart.setTitleBrush(QBrush(Qt.white));

		## Customize chart background
		#backgroundGradient = QLinearGradient()
		#backgroundGradient.setStart(QPointF(0, 0));
		#backgroundGradient.setFinalStop(QPointF(0, 1));
		#backgroundGradient.setColorAt(0.0, QColor(0x000147));
		#backgroundGradient.setColorAt(1.0, QColor(0x000117));
		#backgroundGradient.setCoordinateMode(QGradient.ObjectBoundingMode);
		#self.chart.setBackgroundBrush(backgroundGradient);
		transparent_background = QBrush(QColor(0,0,0,0))
		self.chart.setBackgroundBrush( transparent_background )

		# Customize axis label font
		labelsFont = QFont()
		labelsFont.setPixelSize(16);
		x_axis.setLabelsFont(labelsFont)
		y_axis.setLabelsFont(labelsFont)
		x_axis.setTitleFont(labelsFont)
		y_axis.setTitleFont(labelsFont)

		# Customize axis colors
		axisPen = QPen(QColor(0xd18952))
		axisPen.setWidth(2)
		x_axis.setLinePen(axisPen)
		y_axis.setLinePen(axisPen)

		# Customize axis label colors
		axisBrush = QBrush(Qt.white)
		x_axis.setLabelsBrush(axisBrush)
		y_axis.setLabelsBrush(axisBrush)
		x_axis.setTitleBrush(axisBrush)
		y_axis.setTitleBrush(axisBrush)

	def set_title(self, title):
		self.chart.setTitle(title)

	def add_new_data_point( self, x, y ):
		x_as_millisecs = x.toMSecsSinceEpoch()
		self.temperatureSeries.append( x_as_millisecs, y )
		if( self.setpoint_temperature ):
			self.setpointTemperatureSeries.append( x_as_millisecs, self.setpoint_temperature )

		num_of_datapoints = self.temperatureSeries.count()
		#if( num_of_datapoints > self.number_of_samples_to_keep ):
		#	self.number_of_samples_to_keep.
		#print( x_as_millisecs, y )
		#self.chart.scroll( x_as_millisecs - 5 * 60 * 1000, x_as_millisecs )
		#self.temperatureSeries.append( x, float(y) )
		#self.repaint()

	def Rescale_Axes( self, index ):
		x = self.temperatureSeries.at( index ).x()
		x_rescaled = False
		if( x < self.xMin ):
			self.xMin = x
			x_rescaled = True
		if( x > self.xMax ):
			self.xMax = x
			x_rescaled = True
		if( x_rescaled ):
			full_range = min( self.xMax - self.xMin, 5 * 60 * 1000 )
			margin = full_range * 0.05

			self.chart.axisX().setRange( QDateTime.fromMSecsSinceEpoch(self.xMax - full_range - margin), QDateTime.fromMSecsSinceEpoch(self.xMax + margin) )
			
		y = self.temperatureSeries.at( index ).y()
		y_rescaled = False
		if( y < self.yMin ):
			self.yMin = y
			y_rescaled = True
		if( y > self.yMax ):
			self.yMax = y
			y_rescaled = True
		if( y_rescaled ):
			full_range = self.yMax - self.yMin
			margin = full_range * 0.05
			self.chart.axisY().setRange( self.yMin - margin, self.yMax + margin )
			
예제 #20
0
class BandwidthGraphView(BaseTimedGraph):
    bwStatsFetched = AsyncSignal(dict)

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

        self.setObjectName('BandwidthGraph')
        self.chart.setTitle(iBandwidthUsage())
        self.axisY.setTitleText(iRateKbPerSecond())

        self.bwStatsFetched.connectTo(self.onBwStats)

        penIn = QPen(QColor('red'))
        penIn.setWidth(2)
        penOut = QPen(QColor('blue'))
        penOut.setWidth(2)

        self.seriesKbIn = QLineSeries()
        self.seriesKbIn.setName(iRateInput())
        self.seriesKbIn.setPen(penIn)
        self.chart.addSeries(self.seriesKbIn)
        self.seriesKbIn.attachAxis(self.axisX)
        self.seriesKbIn.attachAxis(self.axisY)

        self.seriesKbOut = QLineSeries()
        self.seriesKbOut.setName(iRateOutput())
        self.seriesKbOut.setPen(penOut)
        self.chart.addSeries(self.seriesKbOut)
        self.seriesKbOut.attachAxis(self.axisX)
        self.seriesKbOut.attachAxis(self.axisY)

        self.setChart(self.chart)

    async def onBwStats(self, stats):
        dtNow = QDateTime.currentDateTime()
        dtMsecs = dtNow.toMSecsSinceEpoch()

        delta = 120 * 1000
        if not self.seriesPurgedT or (dtMsecs - self.seriesPurgedT) > delta:
            self.removeOldSeries(self.seriesKbIn, dtMsecs - delta)
            self.removeOldSeries(self.seriesKbOut, dtMsecs - delta)
            self.seriesPurgedT = dtMsecs

        rateIn = stats.get('RateIn', 0)
        rateOut = stats.get('RateOut', 0)
        rateInKb = int(rateIn / 1024)
        rateOutKb = int(rateOut / 1024)

        inVector = self.seriesKbIn.pointsVector()
        outVector = self.seriesKbIn.pointsVector()

        inValues = [p.y() for p in inVector]
        outValues = [p.y() for p in outVector]

        if inValues or outValues:
            self.axisY.setMax(max(max(inValues), max(outValues)))

        dateMin = QDateTime.fromMSecsSinceEpoch(dtMsecs - (30 * 1000))
        dateMax = QDateTime.fromMSecsSinceEpoch(dtMsecs + 2000)

        self.seriesKbIn.append(dtMsecs, rateInKb)
        self.seriesKbOut.append(dtMsecs, rateOutKb)
        self.axisX.setRange(dateMin, dateMax)
예제 #21
0
def run_evolution():
    range_a = float(str(form.input_a.text()))
    range_b = float(str(form.input_b.text()))
    precision = int(str(form.input_d.text()))
    generations_number = int(str(form.input_t.text()))

    app.setOverrideCursor(QtCore.Qt.WaitCursor)

    best_reals, best_binary, best_fxs, local_fxs, _, _ = evolution(range_a, range_b, precision, generations_number, form.checkBox.isChecked())

    form.best_table.item(1,0).setText(str(best_reals[len(local_fxs)-1]))
    form.best_table.item(1,1).setText(''.join(map(str, best_binary[len(local_fxs)-1])))
    form.best_table.item(1,2).setText(str(best_fxs[len(local_fxs)-1]))
    
    chart = QChart()
    bests = QLineSeries() 

    pen_best = bests.pen()
    pen_best.setWidth(1)
    pen_best.setBrush(QtGui.QColor("red"))
    bests.setPen(pen_best)

    for i in range(0, len(local_fxs)):
        if len(local_fxs[i]) - 1 == 0:
            fxs = QScatterSeries()
            fxs.append(i + 0.99, local_fxs[i][0])
            pen = fxs.pen()
            color = QtGui.QColor(random.randint(50,255), random.randint(50,255), random.randint(50,255))
            fxs.setColor(color)
            pen.setColor(color)
            fxs.setPen(pen)
            fxs.setMarkerSize(5)

        else:
            fxs = QLineSeries()
            tick = 1 / (len(local_fxs[i]) - 1)
            for j in range(len(local_fxs[i])):
                fxs.append(i + j * tick, local_fxs[i][j])
            pen = fxs.pen()
            pen.setWidth(1)
            pen.setBrush(QtGui.QColor(random.randint(50,255), random.randint(50,255), random.randint(50,255)))
            fxs.setPen(pen)
            
        bests.append(i+1, best_fxs[i])
        chart.addSeries(fxs)

    chart.addSeries(bests)

    chart.setBackgroundBrush(QtGui.QColor(41, 43, 47))
    chart.createDefaultAxes()
    chart.legend().hide()
    chart.setContentsMargins(-10, -10, -10, -10)
    chart.layout().setContentsMargins(0, 0, 0, 0)
    chart.axisX().setTickCount(11)
    chart.axisX().setLabelsColor(QtGui.QColor("white"))
    chart.axisX().setGridLineColor(QtGui.QColor("grey"))
    chart.axisX().setLabelFormat("%i")
    chart.axisY().setRange(-2,2)
    chart.axisY().setLabelsColor(QtGui.QColor("white"))
    chart.axisY().setGridLineColor(QtGui.QColor("grey"))
    form.widget.setChart(chart)

    with open('best_history.csv', 'w', newline='', encoding='utf8') as history_csvfile:
        history_writer = csv.writer(
            history_csvfile, delimiter=';', dialect=csv.excel)
        history_writer.writerow(['Parametry'])
        history_writer.writerow(['Precyzja: 10^-%d' % precision])
        history_writer.writerow(['Iteracje: %d' % generations_number])
        history_writer.writerow(['', 'real', 'bin', 'f(real)'])

        for index, generation in enumerate(range(generations_number)):
            history_writer.writerow([index,  best_reals[generation], best_binary[generation], best_fxs[generation]])

    app.restoreOverrideCursor()