Esempio n. 1
0
 def _init_chart(self) -> None:
     series = QBarSeries()
     axis_x = QBarCategoryAxis()
     axis_y = QValueAxis()
     data_set = defaultdict(int)
     for title, money in self.base:
         data_set[title] += money
     for title, money in data_set.items():
         bar = QBarSet(title)
         axis_x.append(title)
         bar.append(money)
         series.append(bar)
     #
     self.chart = QChart()
     self.chart.addSeries(series)
     self.chart.setAnimationOptions(QChart.SeriesAnimations)
     #
     series.attachAxis(axis_x)
     self.chart.addAxis(axis_x, Qt.AlignBottom)
     axis_y.setRange(0, max(data_set.values()))
     axis_y.setTickCount(11)
     self.chart.addAxis(axis_y, Qt.AlignLeft)
     series.attachAxis(axis_y)
     #
     self.chart.legend().setVisible(True)
     self.chart.legend().setAlignment(Qt.AlignBottom)
Esempio n. 2
0
    def draw(self, chart_data: PieChartData) -> None:
        # series = QPieSeries()
        # for project, duration in chart_data.data.items():
        #   series.append("{} ({} s)".format(project, int(duration)), duration)
        # self.chart_view.setRenderHint(QPainter.Antialiasing)
        # self.chart_view.chart().removeAllSeries()
        # self.chart_view.chart().addSeries(series)

        # TODO redo with stacked bar chart
        series = QBarSeries()
        bar_set = QBarSet('Default')
        categories = []
        for project, duration in chart_data.data.items():
            if project == self.config.projects.none_project:
                project = 'None'
            categories.append(project)
            bar_set.append(duration)
        series.append(bar_set)
        axis_x = QBarCategoryAxis()
        axis_x.append(categories)

        self.chart.removeAllSeries()
        self.chart.addSeries(series)
        self.chart.setAxisX(axis_x)
        series.attachAxis(axis_x)

        self.initialized = True
Esempio n. 3
0
    def __actualizar_grafico_barras(self):
        self.grafico.legend().setVisible(True)

        medias = [
            math.floor(np.mean(datos)) if len(datos) > 0 else 0
            for datos in self.datos.values()
        ]
        mejores = [
            np.min(datos) if len(datos) > 0 else 0
            for datos in self.datos.values()
        ]
        peores = [
            np.max(datos) if len(datos) > 0 else 0
            for datos in self.datos.values()
        ]
        self.eje_y.setRange(1, max(max(medias), max(peores)))

        barset_media = QBarSet('Media')
        barset_media.append(medias)
        barset_mejor = QBarSet('Mejor')
        barset_mejor.append(mejores)
        barset_peor = QBarSet('Peor')
        barset_peor.append(peores)
        series = QBarSeries()
        series.append(barset_media)
        series.append(barset_mejor)
        series.append(barset_peor)
        series.setLabelsVisible(True)
        self.grafico.addSeries(series)
        series.attachAxis(self.eje_y)
        self.init_grafico()
    def show_diagram(self):
        self.student_diagram_ui.label_4.setText(self.label_2.text())
        self.student_diagram_ui.label_7.setText(self.label_8.text())
        self.student_diagram_ui.label_8.setText(self.label_6.text())
        self.student_diagram_ui.label_10.setText(self.label_4.text())

        max_value = 0
        series = QBarSeries()
        for i in self.result:
            set0 = QBarSet(i[0])
            set0.append(float(i[1]))
            series.append(set0)
            if max_value < (float(i[1])):
                max_value = float(i[1])

        axisY = QValueAxis()
        axisY.setRange(0, max_value)

        chart = QChart()
        series.attachAxis(axisY)
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)

        chart.addAxis(axisY, Qt.AlignLeft)
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
        centralwidget = self.student_diagram_ui.centralwidget
        self.student_diagram_ui.chartview = QChartView(chart, centralwidget)
        self.student_diagram_ui.chartview.setGeometry(QtCore.QRect(10, 110, 880, 371))
        self.student_diagram_ui.pushButton_3.show()
        self.student_diagram_ui.update(self.dark_theme)
        self.student_diagram_window.show()
Esempio n. 5
0
    def ALL(self):
        self.ind = 0
        set0 = QBarSet('Daya Tarik')
        set1 = QBarSet('Aksesbilitas')
        set2 = QBarSet('Kebersihan')
        set3 = QBarSet('Fasilitas')

        set0.setColor(QtGui.QColor("blue"))
        set1.setColor(QtGui.QColor("red"))
        set2.setColor(QtGui.QColor("green"))
        set3.setColor(QtGui.QColor("orange"))
        gf = Grafik_2()

        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            set0.append((hasil[i] / jml_pantai[i]) * 100)

        hasil2 = gf.hasil_aksesbilitas()
        for i in range(len(hasil2)):
            set1.append((hasil2[i] / jml_pantai[i]) * 100)

        hasil3 = gf.hasil_kebersihan()
        for i in range(len(hasil3)):
            set2.append((hasil3[i] / jml_pantai[i]) * 100)

        hasil4 = gf.hasil_fasilitas()
        for i in range(len(hasil4)):
            set3.append((hasil4[i] / jml_pantai[i]) * 100)

        series = QBarSeries()
        series.append(set0)
        series.append(set1)
        series.append(set2)
        series.append(set3)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)
        series.setLabelsAngle(-90)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 6])
        self.onAxisSliderMoved(self.verticalScrollBar.value())
Esempio n. 6
0
    def __init__(self, parent=None):
        super().__init__(parent)

        self.m_model = CustomTableModel()

        tableView = QTableView()
        tableView.setModel(self.m_model)
        tableView.setMinimumWidth(300)
        tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        tableView.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.m_model.setParent(tableView)

        chart = QChart()
        chart.setAnimationOptions(QChart.AllAnimations)

        series = QBarSeries()

        first = 3
        count = 5
        mapper = QVBarModelMapper(self)
        mapper.setFirstBarSetColumn(1)
        mapper.setLastBarSetColumn(4)
        mapper.setFirstRow(first)
        mapper.setRowCount(count)
        mapper.setSeries(series)
        mapper.setModel(self.m_model)
        chart.addSeries(series)

        seriesColorHex = "#000000"

        barsets = series.barSets()
        for i, barset in enumerate(barsets):
            seriesColorHex = barset.brush().color().name()
            self.m_model.addMapping(
                seriesColorHex, QRect(1 + i, first, 1, barset.count())
            )

        categories = ("April", "May", "June", "July", "August")
        axisX = QBarCategoryAxis()
        axisX.append(categories)
        chart.addAxis(axisX, Qt.AlignBottom)
        series.attachAxis(axisX)
        axisY = QValueAxis()
        chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)

        chartView = QChartView(chart)
        chartView.setRenderHint(QPainter.Antialiasing)
        chartView.setMinimumSize(640, 480)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(tableView, 1, 0)
        mainLayout.addWidget(chartView, 1, 1)
        mainLayout.setColumnStretch(1, 1)
        mainLayout.setColumnStretch(0, 0)
Esempio n. 7
0
def main():
    import sys

    app = QApplication(sys.argv)

    set0 = QBarSet("Jane")
    set1 = QBarSet("John")
    set2 = QBarSet("Axel")
    set3 = QBarSet("Mary")
    set4 = QBarSet("Samantha")

    set0 << 1 << 2 << 3 << 4 << 5 << 6
    set1 << 5 << 0 << 0 << 4 << 0 << 7
    set2 << 3 << 5 << 8 << 13 << 8 << 5
    set3 << 5 << 6 << 7 << 3 << 4 << 5
    set4 << 9 << 7 << 5 << 3 << 1 << 2

    series = QBarSeries()
    series.append(set0)
    series.append(set1)
    series.append(set2)
    series.append(set3)
    series.append(set4)

    chart = QChart()
    chart.addSeries(series)
    chart.setTitle("Simple barchart example")
    chart.setAnimationOptions(QChart.SeriesAnimations)

    categories = ("Jan", "Feb", "Mar", "Apr", "May", "Jun")
    axisX = QBarCategoryAxis()
    axisX.append(categories)
    chart.addAxis(axisX, Qt.AlignBottom)
    series.attachAxis(axisX)

    axisY = QValueAxis()
    axisY.setRange(0, 15)
    chart.addAxis(axisY, Qt.AlignLeft)
    series.attachAxis(axisY)

    chart.legend().setVisible(True)
    chart.legend().setAlignment(Qt.AlignBottom)

    chartView = QChartView(chart)
    chartView.setRenderHint(QPainter.Antialiasing)

    window = QMainWindow()
    window.setCentralWidget(chartView)
    window.resize(420, 300)
    window.show()

    sys.exit(app.exec_())
Esempio n. 8
0
class Chart(QChartView):
    def __init__(self, barCount: int):
        super().__init__()

        self.chart = QChart()
        self.setChart(self.chart)
        self.setRenderHint(QPainter.Antialiasing)
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setBackgroundVisible(True)
        self.chart.legend().setVisible(False)

        self.series = QBarSeries()
        self.chart.addSeries(self.series)

        self.barValues = QBarSet('')
        self.series.append(self.barValues)
        for i in range(barCount):
            self.barValues << 0.

        self.xAxis = QBarCategoryAxis()
        self.chart.addAxis(self.xAxis, Qt.AlignBottom)
        self.series.attachAxis(self.xAxis)
        self.xAxis.setTitleText('yPlus ranges')

        self.yAxis = QValueAxis()
        self.chart.addAxis(self.yAxis, Qt.AlignLeft)
        self.series.attachAxis(self.yAxis)
        self.yAxis.setTitleText('% of surface area')
        self.yAxis.setRange(0, 100)

    def setBarRanges(self, pois: List[float]):
        for i in range(len(pois)):
            if i == 0:
                tag = 'lt ' + str(pois[0])
            elif i == len(pois) - 1:
                tag = 'gt ' + str(pois[-1])
            else:
                tag = str(pois[i]) + ' - ' + str(pois[i + 1])

            if not self.xAxis.count():
                self.xAxis.append(tag)
            else:
                self.xAxis.replace(self.xAxis.at(i), tag)

    def setBarValues(self, values: List[float]):
        assert len(values) == self.barValues.count()

        for i in range(len(values)):
            if not self.barValues.count():
                self.barValues.insert(i, 0.)
            else:
                self.barValues.replace(i, values[i])
Esempio n. 9
0
    def DT(self):
        self.ind = 1
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_dayatarik()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)
        index = np.argsort(value)[::-1]
        label_sorting = []
        for i in index:
            label_sorting.append(self.label_pantai[i])

        set0 = QBarSet('Daya Tarik')
        set0.setColor(QtGui.QColor("blue"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)
        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        axisX = QBarCategoryAxis()
        axisX.setLabelsAngle(-90)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        self.chart.addAxis(axisX, Qt.AlignBottom)
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        axisY.applyNiceNumbers()
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())
Esempio n. 10
0
    def update_graph(self, index):
        if index == 2:
            self.graph_chart.removeAllSeries()

            axis_x = QBarCategoryAxis()
            axis_x.setTitleText("日期")
            if self.graph_chart.axisX():
                self.graph_chart.removeAxis(self.graph_chart.axisX())
            self.graph_chart.addAxis(axis_x, Qt.AlignBottom)

            axis_y = QValueAxis()
            axis_y.setLabelFormat("%i")
            axis_y.setTitleText("售出量")
            if self.graph_chart.axisY():
                self.graph_chart.removeAxis(self.graph_chart.axisY())
            self.graph_chart.addAxis(axis_y, Qt.AlignLeft)

            max_num = 0
            total_date = 0
            set_dict = {}
            for key, data in sorted(self.graph_series.items(),
                                    key=lambda i: int(i[0])):
                axis_x.append(
                    QDateTime.fromSecsSinceEpoch(
                        int(key)).toString("yyyy年MM月dd日"))
                for set_name, value in data.items():
                    if set_name not in set_dict:
                        set_dict[set_name] = QBarSet(set_name)
                        for _ in range(total_date):
                            set_dict[set_name].append(0)
                    set_dict[set_name].append(value)
                    max_num = max(max_num, value)
                total_date += 1
                for _, bar_set in set_dict.items():
                    if bar_set.count() < total_date:
                        bar_set.append(0)
            bar_series = QBarSeries()
            for _, bar_set in set_dict.items():
                bar_series.append(bar_set)
            bar_series.hovered.connect(self.graph_tooltip)
            axis_y.setMax(max_num + 1)
            axis_y.setMin(0)
            self.graph_chart.addSeries(bar_series)
            bar_series.attachAxis(axis_x)
            bar_series.attachAxis(axis_y)
Esempio n. 11
0
    def KB(self):
        self.ind = 3
        gf = Grafik_2()
        jml = gf.jumlah_per_pantai()
        jml_pantai = []
        for i in range(len(jml)):
            jml_pantai.append(jml[i])

        value = []
        hasil = gf.hasil_kebersihan()
        for i in range(len(hasil)):
            value.append((hasil[i] / jml_pantai[i]) * 100)
        sorting = sorted(value, reverse=True)

        set0 = QBarSet('Kebersihan')
        set0.setColor(QtGui.QColor("green"))
        for i in range(len(hasil)):
            set0.append(sorting)

        series = QBarSeries()
        series.append(set0)
        series.setLabelsVisible(True)
        series.setLabelsPosition(QAbstractBarSeries.LabelsInsideEnd)

        self.chart = QChart()
        self.chart.addSeries(series)
        self.chart.setTitle('Grafik Prosentase Ulasan Pantai')
        self.chart.setAnimationOptions(QChart.SeriesAnimations)

        axisY = QValueAxis()
        axisY.setTitleText("Prosentase (%)")
        axisY.applyNiceNumbers()
        self.chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)
        self.chart.legend().setVisible(True)
        self.chart.legend().setAlignment(Qt.AlignBottom)
        self.chart.createDefaultAxes()
        self.graphicsView.setChart(self.chart)
        self.adjust_axes(0, 2)
        self.lims = np.array([0, 10])
        self.onAxisSliderMoved(self.verticalScrollBar.value())
Esempio n. 12
0
class BandPowerGraph(QWidget):

	def __init__(self, name: str):
		super().__init__()

		self.band_power_chart = QChart()
		self.band_power_chart.setAnimationOptions(QChart.SeriesAnimations)

		self.channel_band_power_set = QBarSet("Band Power")
		self.channel_band_power_set.append(1)
		self.channel_band_power_set.append(1)
		self.channel_band_power_set.append(1)
		self.channel_band_power_set.append(1)
		self.channel_band_power_set.append(1)

		self.bands_axis = QBarCategoryAxis()
		self.bands_axis.append("Delta (1 - 3 Hz)")
		self.bands_axis.append("Theta (4 - 7 Hz)")
		self.bands_axis.append("Alpha (8 - 13 Hz)")
		self.bands_axis.append("Beta (13 - 30 Hz)")
		self.bands_axis.append("Gamma (30 - 100)")

		self.power_axis = QValueAxis()

		self.chart_series = QBarSeries()
		self.chart_series.append(self.channel_band_power_set)

		self.band_power_chart.addSeries(self.chart_series)
		self.band_power_chart.setTitle(f"<h1>Band Power For {name}</h1>")
		self.band_power_chart.addAxis(self.bands_axis, Qt.AlignBottom)
		self.band_power_chart.addAxis(self.power_axis, Qt.AlignLeft)

		self.chart_series.attachAxis(self.bands_axis)
		self.chart_series.attachAxis(self.power_axis)

		self.chart_view = QChartView(self.band_power_chart)
		self.chart_view.setRenderHint(QPainter.Antialiasing)

		self.root_layout = QStackedLayout()
		self.setLayout(self.root_layout)

		self.root_layout.addWidget(self.chart_view)

	def set_name(self, name: str):
		self.band_power_chart.setTitle(f"<h1>Band Power For {name}</h1>")

	def update_values(self, data: np.ndarray, fft_window_size: float = 0):
		eeg_data = utils.EegData(data)

		feature_extractor = eeg_data.feature_extractor(0, global_config.SAMPLING_RATE)

		self.channel_band_power_set.replace(
			0, feature_extractor.average_band_amplitude(utils.FrequencyBand.delta_freq_band(), fft_window_size)
		)

		self.channel_band_power_set.replace(
			1, feature_extractor.average_band_amplitude(utils.FrequencyBand.theta_freq_band(), fft_window_size)
		)

		self.channel_band_power_set.replace(
			2, feature_extractor.average_band_amplitude(utils.FrequencyBand.alpha_freq_band(), fft_window_size)
		)

		self.channel_band_power_set.replace(
			3, feature_extractor.average_band_amplitude(utils.FrequencyBand.beta_freq_band(), fft_window_size)
		)

		self.channel_band_power_set.replace(
			4, feature_extractor.average_band_amplitude(utils.FrequencyBand.gama_freq_band(), fft_window_size)
		)

	def auto_adjust_axis(self):
		utils.auto_adjust_axis(self.power_axis, [self.channel_band_power_set], 0.1)
Esempio n. 13
0
def bars_stacked(name, table_df, x_bottom_cols, y_left_cols, y_right_cols,
                 legend_labels, tick_count):
    """
    柱形堆叠图
    :param name: 图表名称
    :param table_df: 用于画图的pandas DataFrame对象
    :param x_bottom_cols:  下轴列索引列表
    :param y_left_cols: 左轴列索引列表
    :param y_right_cols: 右轴列索引列表
    :param legend_labels: 图例名称标签列表
    :param tick_count: 横轴刻度标签数
    :return: QChart实例
    """
    """ 过滤轴 """
    for y_left_col in y_left_cols:
        if is_datetime64_any_dtype(table_df[y_left_col]):  # 如果是时间轴
            y_left_cols.remove(y_left_col)
    for y_right_col in y_right_cols:
        if is_datetime64_any_dtype(table_df[y_right_col]):  # 如果是时间轴
            y_right_cols.remove(y_right_col)
    # 将x轴转为字符串
    x_bottom = x_bottom_cols[0]  # x轴列
    if is_datetime64_any_dtype(table_df[x_bottom]):  # 如果x轴是时间轴
        table_df[x_bottom] = table_df[x_bottom].apply(
            lambda x: x.strftime('%Y-%m-%d'))
    else:  # x轴非时间轴
        table_df[x_bottom] = table_df[x_bottom].apply(lambda x: str(x))
    font = QFont()  # 轴文字风格
    font.setPointSize(7)  # 轴标签文字大小
    chart = QChart()  # 图表实例
    chart.layout().setContentsMargins(0, 0, 0, 0)  # chart的外边距
    chart.setMargins(QMargins(15, 5, 15, 0))  # chart内边距
    chart.setTitle(name)  # chart名称
    """ x轴 """
    axis_x_bottom = QCategoryAxis(
        chart, labelsPosition=QCategoryAxis.AxisLabelsPositionOnValue)
    axis_x_bottom.setLabelsAngle(-90)  # 逆时针旋转90度
    axis_x_bottom.setLabelsFont(font)  # 设置字体样式
    axis_x_bottom.setGridLineVisible(False)  # 竖向连接线不可见
    # chart.addAxis(axis_x_bottom, Qt.AlignBottom)  # 加入坐标x轴
    has_x_labels = False  # 收集x轴刻度的开关
    chart.x_labels = list()  # 绑定chart一个x轴的刻度列表
    """ 左Y轴 """
    axis_y_left = QValueAxis()
    axis_y_left.setLabelsFont(font)
    axis_y_left.setLabelFormat('%i')
    chart.addAxis(axis_y_left, Qt.AlignLeft)  # 图表加入左轴
    """ 右Y轴 """
    axis_y_right = QValueAxis()
    axis_y_right.setLabelsFont(font)
    axis_y_right.setLabelFormat('%.2f')
    chart.addAxis(axis_y_right, Qt.AlignRight)
    # 记录各轴的最值
    x_bottom_min, x_bottom_max = 0, table_df.shape[0]
    y_left_min, y_left_max = 0, 0
    y_right_min, y_right_max = 0, 0
    # 柱形图
    left_bars = QBarSeries()
    """ 根据左轴画柱形 """
    for y_left_col in y_left_cols:  # 根据左轴画折线
        # 计算做轴的最值用于设置范围
        table_df[y_left_col] = table_df[y_left_col].apply(
            covert_float)  # y轴列转为浮点数值
        # 获取最值
        y_min, y_max = table_df[y_left_col].min(), table_df[y_left_col].max()
        if y_min < y_left_min:
            y_left_min = y_min
        if y_max > y_left_max:
            y_left_max = y_max
        # 取得图表的源数据作柱形
        left_bar_data = table_df.iloc[:, [x_bottom, y_left_col]]
        bar = QBarSet(legend_labels[y_left_col])
        bar.setPen(QPen(Qt.transparent))  # 设置画笔轮廓线透明(数据量大会出现空白遮住柱形)
        for index, point_item in enumerate(left_bar_data.values.tolist()):
            bar.append(point_item[1])
            if not has_x_labels:
                chart.x_labels.append(point_item[0])
        has_x_labels = True  # 关闭添加轴标签
        left_bars.append(bar)  # 柱形加入系列
    left_bars.attachAxis(axis_y_left)
    # 左轴的范围
    axis_y_left.setRange(y_left_min, y_left_max)
    """ 根据右轴画柱形 """
    right_bars = QBarSeries()
    for y_right_col in y_right_cols:  # 根据右轴画柱形
        # 计算做轴的最值用于设置范围
        table_df[y_right_col] = table_df[y_right_col].apply(
            covert_float)  # y轴列转为浮点数值
        # 获取最值
        y_min, y_max = table_df[y_right_col].min(), table_df[y_right_col].max()
        if y_min < y_right_min:
            y_right_min = y_min
        if y_max > y_right_max:
            y_right_max = y_max
        # 取得图线的源数据作折线图
        right_bar_data = table_df.iloc[:, [x_bottom, y_right_col]]
        bar = QBarSet(legend_labels[y_right_col])
        bar.setPen(QPen(Qt.transparent))
        for position_index, point_item in enumerate(
                right_bar_data.values.tolist()):
            bar.append(point_item[1])  # 取出源数据后一条线就2列数据
        right_bars.append(bar)
        right_bars.attachAxis(axis_x_bottom)
        right_bars.attachAxis(axis_y_right)
    # 右轴范围
    axis_y_right.setRange(y_right_min, y_right_max)
    chart.addSeries(left_bars)  # 左轴的柱形图加入图表
    # print(right_bars.count())
    if right_bars.count() != 0:  # 为空时加入会导致空位
        chart.addSeries(right_bars)
    chart.setAxisX(axis_x_bottom, left_bars)  # 关联设置x轴
    # 横轴标签设置
    x_bottom_interval = int(x_bottom_max / (tick_count - 1))
    if x_bottom_interval == 0:
        for i in range(0, x_bottom_max):
            axis_x_bottom.append(chart.x_labels[i], i)
    else:
        for i in range(0, x_bottom_max, x_bottom_interval):
            axis_x_bottom.append(chart.x_labels[i], i)
    chart.legend().setAlignment(Qt.AlignBottom)
    return chart
class SENSOR_TEST(QWidget):
    
    bars = None
    series = None
    chart = None
    labelWidgets = []
    comms = None
    commsStatus = False
    deviceID = "HARP"

    def __init__(self):
        QWidget.__init__(self)

        # ADD GUI WIDGETS
        self.setupLayout()

        # LAUNCH GUI
        self.show()
        self.resize(800,600)

    def setupLayout(self):
        parentLayout = QVBoxLayout()
        parentLayout.setContentsMargins(20,20,20,20)

        buttonLayout = QHBoxLayout()

        # CREATE SERIAL COMMUNICATION CONNECT BUTTON
        self.connectButton = QPushButton("CONNECT")
        self.connectButton.setFixedSize(150, 40)
        self.connectButton.setCheckable(True)
        self.connectButton.setStyleSheet("QPushButton {background-color: #66BB6A; color: black; border-radius: 20px}" 
                                    "QPushButton:hover {background-color: #4CAF50; color: black; border-radius: 20px}"
                                    "QPushButton:checked {background-color: #EF5350; color: white; border-radius: 20px}"
                                    "QPushButton:checked:hover {background-color: #F44336; color: white; border-radius: 20px}")

        # CREATE SENSORS CALIBRATION BUTTON
        self.calibrateButton = QPushButton("CALIBRATE")
        self.calibrateButton.setFixedSize(150, 40)
        self.calibrateButton.setStyleSheet("QPushButton {background-color: #E0E0E0; color: black; border-radius: 20px}" 
                                    "QPushButton:hover {background-color: #BDBDBD; color: black; border-radius: 20px}" 
                                    "QPushButton:pressed {background-color: #D5D5D5; color: black; border-radius: 20px}")

        # ADD BUTTONS TO HORIZONTAL LAYOUT
        buttonLayout.addWidget(self.connectButton, alignment = Qt.AlignLeft)
        buttonLayout.addWidget(self.calibrateButton, alignment = Qt.AlignRight)
        
        # CREATE BAR CHART TO DISPLAY SENSOR READINGS
        self.bars = QBarSet('Sensor Readings')
        self.bars.append([0 for i in range(5)])
        self.chart = QChart()
        self.chart.setBackgroundRoundness(20)
        self.chart.layout().setContentsMargins(0, 0, 0, 0)
        self.series = QBarSeries()
        self.series.append(self.bars)
        self.chart.addSeries(self.series)
        self.chart.setTitle('Sensor Readings')

        # CREATE X-AXIS AS SENSOR LABELS
        xAxis = QBarCategoryAxis()
        labels = ["Sensor {}".format(i+1) for i in range(5)]
        xAxis.append(labels)
        
        # CREATE Y-AXIS AND SENSOR READINGS
        yAxis = QValueAxis()
        yAxis.setRange(-100, 100)
        yAxis.setTickCount(11)
        yAxis.setTitleText("Pressure (%)")
        
        # ADD AXES TO CHART
        self.chart.addAxis(xAxis, Qt.AlignBottom)
        self.chart.addAxis(yAxis, Qt.AlignLeft)
        self.chart.legend().setVisible(False)

        # ATTACH AXES TO SERIES
        self.series.attachAxis(xAxis)
        self.series.attachAxis(yAxis)
        
        # ADD CHART TO A VIEW
        chartView = QChartView(self.chart)

        labelLayout = QFrame()
        labelLayout.setStyleSheet("background-color: white; border-radius: 20px")
        layout1 = QVBoxLayout()
        labelLayout.setLayout(layout1)
        layout2 = QHBoxLayout()
        layout3 = QHBoxLayout()
        
        for i in range(5):
            label = QLabel("Sensor {}".format(i+1))
            label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            label.setStyleSheet("font-weight: bold;")
            layout2.addWidget(label)

            value = QLabel("0 mV")
            value.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.labelWidgets.append(value)
            layout3.addWidget(value)

        layout1.addLayout(layout2, 1)
        layout1.addLayout(layout3, 1)

        parentLayout.addLayout(buttonLayout)
        parentLayout.addWidget(chartView, 5)
        parentLayout.addWidget(labelLayout, 1)

        # LINK WIDGETS
        self.connectButton.clicked.connect(self.serialToggle)
        self.calibrateButton.clicked.connect(self.sensorCalibrate)

        self.setLayout(parentLayout)

    def getSensorReadings(self):
        """
        PURPOSE

        Requests sensor readings from ROV and updates GUI.

        INPUT

        NONE

        RETURNS

        NONE
        """
        # SENSOR POLLING RATE (HZ)
        refreshRate = 100

        # START QTIMER TO REPEATEDLY UPDATE SENSORS AT THE DESIRED POLLING RATE 
        self.timer = QTimer()
        self.timer.setTimerType(Qt.PreciseTimer)
        self.timer.timeout.connect(self.getSensorReadings)
        self.timer.start(int(1000*1/refreshRate))
        
        # STOP REQUESTING SENSOR VALUES IF ROV IS DISCONNECTED
        if self.commsStatus == False:
            self.timer.stop()
        
        else:
            # REQEST SINGLE READING
            sensorReadings = self.getSensors()

            # UPDATE VOLTAGE READINGS
            self.updateVoltageReadings(sensorReadings)

            # SCALE SENSOR READINGS
            scaledReadings = self.mapPressureReadings(sensorReadings)
            
            try:
                # UPDATE GUI 
                self.series.remove(self.bars)
                self.bars = QBarSet("")
                self.bars.append([float(item) for item in scaledReadings])
                self.series.append(self.bars)
            except:
                self.teensyDisconnect()

    def mapPressureReadings(self, values):
        mappedValues = []

        for value in values:
            try:
                mappedValues.append((200/1023)*float(value) - 100)
            except:
                pass

        return mappedValues

    def updateVoltageReadings(self, values):
        voltageValues = [round((3300/1023)*float(i)) for i in values]
        for i, label in enumerate(self.labelWidgets):
            label.setText(str(voltageValues[i]) + " mV")

    def serialToggle(self, buttonState):
        """
        PURPOSE

        Determines whether to connect or disconnect from the ROV serial interface.

        INPUT

        - buttonState = the state of the button (checked or unchecked).

        RETURNS

        NONE
        """
        # CONNECT
        if buttonState:
            self.teensyConnect()

        # DISCONNECT
        else:
            self.teensyDisconnect()

    def sensorCalibrate(self):
        """
        PURPOSE

        INPUT

        RETURNS

        """
        self.calibrateSensors()

    ########################
    ### SERIAL FUNCTIONS ###
    ########################
    def teensyConnect(self):
        """
        PURPOSE

        Attempts to connect to the ROV using the comms library.
        Changes the appearance of the connect buttons.
        If connection is successful, the ROV startup procedure is initiated.

        INPUT

        NONE

        RETURNS

        NONE
        """
        # DISABLE BUTTONS TO AVOID DOUBLE CLICKS
        self.connectButton.setEnabled(False)
            
        # FIND ALL AVAILABLE COM PORTS
        availableComPorts, comPort, identity = self.findComPorts(115200, self.deviceID)
        print(availableComPorts, comPort, identity)
        
        # ATTEMPT CONNECTION TO ROV COM PORT
        status, message = self.serialConnect(comPort, 115200)
        print(status, message)

        # IF CONNECTION IS SUCCESSFUL
        if status == True:
            # MODIFY BUTTON STYLE
            self.connectButton.setText('DISCONNECT')

            # START READING SENSOR VALUES
            self.getSensorReadings()
        
        # IF CONNECTION IS UNSUCCESSFUL
        else:
            self.teensyDisconnect()
            
        # RE-ENABLE CONNECT BUTTONS
        self.connectButton.setEnabled(True)

    def teensyDisconnect(self):
        """
        PURPOSE

        Disconnects from the ROV using the comms library.
        Changes the appearance of the connect buttons

        INPUT

        NONE

        RETURNS

        NONE
        """
        # MODIFY BUTTON STYLE
        self.connectButton.setText('CONNECT')
        self.connectButton.setChecked(False)
        
        # CLOSE COM PORT
        if self.commsStatus:
            self.comms.close()
            self.commsStatus = False

    def findComPorts(self, baudRate, identity):
        """
        PURPOSE

        Find all available COM ports and requests the devices identity.

        INPUT

        - menuObject = pointer to the drop down menu to display the available COM ports.
        - baudRate = baud rate of the serial interface.
        - identity = string containing the required device identity to connect to.

        RETURNS

        - availableComPorts = list of all the available COM ports.
        - rovComPort = the COM port that belongs to the device.
        - identity = the devices response from an identity request.
        """
        # CREATE LIST OF ALL POSSIBLE COM PORTS
        ports = ['COM%s' % (i + 1) for i in range(256)] 

        deviceIdentity = ""
        comPort = None
        availableComPorts = []
        
        # CHECK WHICH COM PORTS ARE AVAILABLE
        for port in ports:
            try:
                comms = serial.Serial(port, baudRate, timeout = 1)
                availableComPorts.append(port)

                # REQUEST IDENTITY FROM COM PORT
                self.commsStatus = True
                deviceIdentity = self.getIdentity(comms, identity)
                comms.close()
                self.commsStatus = False
                
                # FIND WHICH COM PORT IS THE ROV
                if deviceIdentity == identity:
                    comPort = port
                    break
                    
            # SKIP COM PORT IF UNAVAILABLE
            except (OSError, serial.SerialException):
                pass

        return availableComPorts, comPort, deviceIdentity

    def getIdentity(self, serialInterface, identity):
        """
        PURPOSE

        Request identity from a defined COM port.

        INPUT

        - serialInterface = pointer to the serial interface object.
        - identity = the desired identity response from the device connected to the COM port.

        RETURNS

        - identity = the devices response.
        """
        identity = ""
        startTime = datetime.now()
        elapsedTime = 0
        # REPEATIDELY REQUEST IDENTIFICATION FROM DEVICE FOR UP TO 3 SECONDS
        while (identity == "") and (elapsedTime < 3):
            self.serialSend("?I", serialInterface)
            identity = self.serialReceive(serialInterface)
            elapsedTime = (datetime.now() - startTime).total_seconds()

        return identity

    def serialConnect(self, comPort, baudRate):
        """
        PURPOSE

        Attempts to initialise a serial communication interface with a desired COM port.

        INPUT

        - rovComPort = the COM port of the ROV.
        - baudRate = the baud rate of the serial interface.

        RETURNS

        NONE
        """
        self.commsStatus = False
        if comPort != None:
            try: 
                self.comms = serial.Serial(comPort, baudRate, timeout = 1)
                message = "Connection to ROV successful."
                self.commsStatus = True
            except:
                message = "Failed to connect to {}.".format(comPort)
        else:
            message = "Failed to recognise device identity."

        return self.commsStatus, message

    def serialSend(self, command, serialInterface):
        """
        PURPOSE

        Sends a string down the serial interface to the ROV.

        INPUT

        - command = the command to send.
        - serialInterface = pointer to the serial interface object.

        RETURNS

        NONE
        """
        if self.commsStatus:
            try:
                serialInterface.write((command + '\n').encode('ascii'))
            except:
                self.teensyDisconnect()
                print("Failed to send command.")

    def serialReceive(self, serialInterface):
        """
        PURPOSE

        Waits for data until a newline character is received.

        INPUT

        - serialInterface = pointer to the serial interface object.

        RETURNS

        NONE
        """
        received = ""
        try:
            received = serialInterface.readline().decode('ascii').strip()
        except:
            self.teensyDisconnect()
            print("Failed to receive data.")
            
        return(received)

    def getSensors(self):
        """
        PURPOSE

        Send request to device to return sensor readings.
        
        INPUT

        NONE

        RETURNS

        - results = array containing the sensor readings.
        """
        results = []

        # REQUEST SENSOR READINGS
        command = "?S"
        self.serialSend(command, self.comms)
        
        # READ RESPONSE INTO AN ARRAY
        results = self.serialReceive(self.comms).split(",")
        print(results)
        return results

    def calibrateSensors(self):
        """
        """
        # REQUEST SENSOR READINGS
        command = "?C"
        self.serialSend(command, self.comms)
Esempio n. 15
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))
Esempio n. 16
0
    def createUnlinkedBar(self):
        max_count = 0
        unlinked_bag_list = []
        try:
            df = self.unlinked['Beam Diff'].dropna()
            unlinked_bag_list = df.values.tolist()
        except AttributeError:
            self.statusbar.showMessage('Data not ready')

        count = [0] * 4
        for num in unlinked_bag_list:
            if -1000 <= num and num <= -51:
                count[0] += 1
            elif -50 <= num and num <= -1:
                count[1] += 1
            elif 151 <= num and num <= 200:
                count[2] += 1
            elif 201 <= num:
                count[3] += 1

        # print(count)
        max_count = max(count)

        setBar = QBarSet('Beam Difference Occurrence')
        setBar.append(count)

        series = QBarSeries()
        series.append(setBar)
        
        brush = QBrush(QColor(0xfdb157))
        pen = QPen(QColor(0xfdb157))
        pen.setWidth(2)
        setBar.setPen(pen)  
        setBar.setBrush(brush)

        chart = QChart()
        font = QFont()
        font.setPixelSize(18)
        chart.setTitleFont(font)

        chart.setTitle('Unlinked Bags Summary')
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)

        labels = ['Not useful(-50 to -1000)', 'Pushed by operator(-1 to -50)', 'Slipping on belt(151 to 200)', 'Not useful 201+']
        axisX = QBarCategoryAxis()
        axisX.append(labels)
        # chart.setAxisX(axisX, series)
        chart.addAxis(axisX, Qt.AlignBottom)
        # chart.ChartAreas[0].AxisX.LabelAutoFitStyle = LabelAutoFitStyle.WrodWrap
        series.attachAxis(axisX)

        axisY = QValueAxis()
        axisY.setRange(0, max_count+1)
        # chart.setAxisY(axisY, series)
        chart.addAxis(axisY, Qt.AlignLeft)
        series.attachAxis(axisY)

        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)

        chartView = QChartView(chart)
        chartView.setRenderHint(QPainter.Antialiasing)

        # MainWindow.setCentralWidget(chartView)
        return chartView
class LastMonthsHistogram(QChartView):
    """
    Chart that displays the balance
    from the whole portfolio from the last months
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.chart = QChart()

    def setupChartWithData(self):
        """
        Chart gets updated displaying the new data.

        Data has to be expressed on a dictionary form:
            - keys are timestamps
            - values are total balance for that timestamp
        """
        self.chart = QChart()
        self.chart.setTheme(QChart.ChartThemeDark)
        self.chart.setAnimationOptions(QChart.SeriesAnimations)
        self.chart.setBackgroundBrush(QBrush(QColor("transparent")))

        # Series
        self.barseries = QBarSeries()

        currentyear, currentmonth = datetime.today().year, datetime.today(
        ).month
        dates, amounts = [], []
        # Get 5 previous month numbers
        for _ in range(5):
            dates.append((currentmonth, currentyear))
            currentmonth -= 1
            if currentmonth == 0:
                currentmonth = 12
                currentyear -= 1
        # Get amounts for each month
        for d in dates:
            month, year = d
            amounts.append(
                dbhandler.get_total_wealth_on_month(month, year=year))

        # Iterate months and amount and insert them into the histogram appropiately
        barset = QBarSet('Total wealth')
        labelsfont = QFont()
        labelsfont.setFamily('Inter')
        labelsfont.setBold(True)
        barset.setLabelFont(labelsfont)
        barset.setColor(QColor("#D3EABD"))
        x_values = []
        for d, a in zip(reversed(dates), reversed(amounts)):
            if a > 0:
                barset.append(int(a))
                x_values.append(calendar.month_name[d[0]])

        self.barseries.append(barset)
        self.barseries.setName("Last Months")
        self.barseries.setLabelsVisible(True)
        self.barseries.setBarWidth(0.2)
        self.barseries.setLabelsPosition(QAbstractBarSeries.LabelsOutsideEnd)
        self.chart.addSeries(self.barseries)

        # Axis X (Dates)
        self.x_axis = QBarCategoryAxis()
        self.x_axis.setTitleText(self.tr('Date'))
        labelsfont = QFont()
        labelsfont.setFamily('Roboto')
        labelsfont.setLetterSpacing(QFont.AbsoluteSpacing, 1)
        labelsfont.setWeight(QFont.Light)
        labelsfont.setPointSize(9)
        self.x_axis.setLabelsFont(labelsfont)
        self.x_axis.setGridLineVisible(False)
        self.x_axis.setLineVisible(False)
        self.x_axis.setLinePenColor(QColor("#D3EABD"))
        self.x_axis.setTitleVisible(False)

        self.x_axis.append(x_values)
        self.chart.addAxis(self.x_axis, Qt.AlignBottom)

        # Axis Y (Balances)
        self.y_axis = QValueAxis()
        self.y_axis.setMax(max(amounts) * 1.3)
        self.y_axis.setMin(min(amounts) * 0.95)
        self.y_axis.hide()

        labelsfont = QFont()
        labelsfont.setPointSize(4)
        self.y_axis.setLabelsFont(labelsfont)
        self.chart.addAxis(self.y_axis, Qt.AlignLeft)

        # Attach axis to series
        self.barseries.attachAxis(self.x_axis)
        self.barseries.attachAxis(self.y_axis)

        # Legend
        self.chart.legend().hide()

        # Set up chart on ChartView
        self.setChart(self.chart)
        self.setRenderHint(QPainter.Antialiasing)
        self.setStyleSheet("border: 0px; background-color: rgba(0,0,0,0)")
class ResonanceFrequencyFinder(QMainWindow):

	# AVAILABLE_WINDOW_SIZES = ["5 Sec", "8 Sec", "10 Sec", "15 Sec", "20 Sec"]

	DEFAULT_GRAPH_PADDING = 2

	DEFAULT_FFT_WINDOW_SIZE = 5

	DEFAULT_SAMPLE_PADDING = 2

	DEFAULT_RECORDING_DURATION = 30 + DEFAULT_SAMPLE_PADDING

	DEFAULT_MIN_FREQUENCY = 17

	DEFAULT_MAX_FREQUENCY = 35

	DEFAULT_FREQUENCY_STEP = 2

	# Used to create a band for which the average frequency amplitude is computed
	DEFAULT_FREQUENCY_PADDING = 0.2

	DEFAULT_BANDPASS_MIN = 8

	DEFAULT_BANDPASS_MAX = 40

	DEFAULT_C3_CHANNEL_INDEX = 4

	DEFAULT_CZ_CHANNEL_INDEX = 2

	DEFAULT_C4_CHANNEL_INDEX = 0

	def __init__(self, board: BoardShim):
		super().__init__()
		self.setGeometry(0, 0, 1800, 900)
		self.setWindowTitle("Resonance-Like Frequency")

		self.board = board

		self.recording_progress_dialog = None
		self.eeg_data_buffer = utils.EegData()
		self.reading_timer = QTimer()
		self.recording = False

		self.recording_reference = False
		self.reference_eeg_data = utils.EegData()

		self.index_generator = utils.FrequencyIndexGenerator(global_config.SAMPLING_RATE)
		self.eeg_sample_count = 0

		self.root_widget = QWidget()
		self.root_layout = QGridLayout()
		self.root_widget.setLayout(self.root_layout)
		self.setCentralWidget(self.root_widget)

		title = QLabel("<h1>Resonance Frequency Finder</h1>")
		title.setAlignment(Qt.AlignCenter)
		self.root_layout.addWidget(title, 0, 0, 1, 3)

		# window_size_label = QLabel("window size: ")
		# window_size_label.setAlignment(Qt.AlignRight)

		# self.window_size_combo_box = QComboBox()
		# self.window_size_combo_box.addItems(self.AVAILABLE_WINDOW_SIZES)

		self.root_directory_label = QLabel()
		self.select_root_directory = QPushButton("Select/Change")
		self.select_root_directory.clicked.connect(self.pick_root_directory)

		self.record_btn = QPushButton("Record")
		self.record_btn.setEnabled(False)
		self.record_btn.clicked.connect(self.record_clicked)

		self.record_reference_btn = QPushButton("Record Reference")
		self.record_reference_btn.clicked.connect(self.record_reference_clicked)

		# self.root_layout.addWidget(utils.construct_horizontal_box([
		# 	window_size_label, self.window_size_combo_box, self.record_btn
		# ]), 1, 0, 1, 3)

		self.load_results_btn = QPushButton("Load Existing Data")
		self.load_results_btn.clicked.connect(self.load_existing_data)

		self.root_layout.addWidget(utils.construct_horizontal_box([
			self.record_btn, self.record_reference_btn, self.root_directory_label,
			self.select_root_directory, self.load_results_btn
		]), 1, 0, 1, 3)

		self.current_freq_label = QLabel()

		self.root_layout.addWidget(utils.construct_horizontal_box([self.current_freq_label]), 2, 0, 1, 3)

		self.frequency_slider = QSlider()
		self.frequency_slider.setRange(self.DEFAULT_MIN_FREQUENCY, self.DEFAULT_MAX_FREQUENCY)
		self.frequency_slider.setSingleStep(self.DEFAULT_FREQUENCY_STEP)
		self.frequency_slider.setTickInterval(self.DEFAULT_FREQUENCY_STEP)
		self.frequency_slider.valueChanged.connect(self.update_freq_label)
		self.frequency_slider.setTickPosition(QSlider.TicksBelow)
		self.frequency_slider.setOrientation(Qt.Horizontal)

		min_freq_label = QLabel(f"<b>{self.DEFAULT_MIN_FREQUENCY} Hz</b>")
		max_freq_label = QLabel(f"<b>{self.DEFAULT_MAX_FREQUENCY} Hz</b>")

		self.root_layout.addWidget(utils.construct_horizontal_box([
			min_freq_label, self.frequency_slider, max_freq_label
		]), 3, 0, 1, 3)

		self.c3_amplitude_bar_set = QBarSet("Electrode C3")
		self.cz_amplitude_bar_set = QBarSet("Electrode Cz")
		self.c4_amplitude_bar_set = QBarSet("Electrode C4")

		self.frequencies = []

		for freq in range(self.DEFAULT_MIN_FREQUENCY, self.DEFAULT_MAX_FREQUENCY + 1, self.DEFAULT_FREQUENCY_STEP):
			self.frequencies.append(f"{freq} Hz")
			self.c3_amplitude_bar_set.append(1)
			self.cz_amplitude_bar_set.append(1)
			self.c4_amplitude_bar_set.append(1)

		self.freq_axis = QBarCategoryAxis()
		self.freq_axis.append(self.frequencies)

		self.amplitude_axis = QValueAxis()
		self.amplitude_axis.setRange(0, 4)

		self.freq_chart = QChart()
		self.freq_chart.setAnimationOptions(QChart.SeriesAnimations)

		self.electrodes_data_series = QBarSeries()
		self.electrodes_data_series.append(self.c3_amplitude_bar_set)
		self.electrodes_data_series.append(self.cz_amplitude_bar_set)
		self.electrodes_data_series.append(self.c4_amplitude_bar_set)

		self.freq_chart.addSeries(self.electrodes_data_series)
		self.freq_chart.setTitle("<h1>Frequency Amplitude Increase</h1>")
		self.freq_chart.addAxis(self.freq_axis, Qt.AlignBottom)
		self.freq_chart.addAxis(self.amplitude_axis, Qt.AlignLeft)

		self.electrodes_data_series.attachAxis(self.amplitude_axis)
		self.electrodes_data_series.attachAxis(self.freq_axis)

		self.frequency_amplitude_graph = QChartView(self.freq_chart)
		self.frequency_amplitude_graph.setRenderHint(QPainter.Antialiasing)

		self.root_layout.addWidget(self.frequency_amplitude_graph, 4, 0, 15, 3)

		self.auto_adjust_axis()

	def update_freq_label(self):
		self.current_freq_label.setText("Selected Frequency: {} Hz".format(self.frequency_slider.value()))

	def pick_root_directory(self):
		path = QFileDialog.getExistingDirectory(self, "Root Directory...")
		self.root_directory_label.setText(path)

	def record_clicked(self, reference: bool = False):
		# selected_window_text = self.window_size_combo_box.currentText()
		# window_size_text = selected_window_text.replace(" Sec", "")

		# window_size = -1
		#
		# if utils.is_integer(window_size_text):
		# 	window_size = int(window_size_text)
		# else:
		# 	print("Invalid window size...")
		# 	return

		# window_size_in_samples = window_size * SAMPLING_RATE

		recording_duration_in_samples = self.DEFAULT_RECORDING_DURATION * global_config.SAMPLING_RATE

		if not reference and (self.frequency_slider.value() - self.DEFAULT_MIN_FREQUENCY) % self.DEFAULT_FREQUENCY_STEP != 0:
			err = QErrorMessage(self)
			err.showMessage("Invalid Frequency Selected")
			err.exec()
			return

		self.recording_progress_dialog = \
			QProgressDialog("Reading EEG data from board...", "Stop Recording", 0, int(recording_duration_in_samples), self)
		self.recording_progress_dialog.setWindowTitle("Reading Data, Please Wait...")
		self.recording_progress_dialog.setWindowModality(Qt.WindowModal)
		self.recording_progress_dialog.show()

		if reference:
			self.recording_reference = True
		else:
			self.recording = True
			self.eeg_data_buffer.clear()

		self.board.start_stream()

		self.reading_timer = QTimer()
		self.reading_timer.timeout.connect(self.read_data)
		self.reading_timer.start(100)

	def record_reference_clicked(self):
		print("Record reference clicked")
		if self.reference_eeg_data.get_channel_data(0).shape[0] > 0:
			self.reference_eeg_data.clear()
		self.record_clicked(reference=True)

	def read_data(self):
		if not self.recording and not self.recording_reference:
			return

		recording_duration_in_samples = self.recording_progress_dialog.maximum()

		if self.recording_reference:
			if self.reference_eeg_data.get_channel_data(0).shape[0] > recording_duration_in_samples or\
					self.recording_progress_dialog.wasCanceled():
				self.stop_recording(True)
				return

		if self.recording:
			if self.recording_progress_dialog.wasCanceled() or\
					self.eeg_data_buffer.get_channel_data(0).shape[0] > recording_duration_in_samples:
				self.stop_recording(self.recording_reference)
				return

		if self.board.get_board_data_count() > 0:
			raw_data = self.board.get_board_data()
			raw_eeg_data = utils.extract_eeg_data(raw_data, global_config.BOARD_ID)

			self.eeg_sample_count += raw_eeg_data.shape[1]

			path = self.root_directory_label.text()

			if path != "":
				full_path = path + "/" + global_config.RESONANCE_DATA_FILE_NAME
				DataFilter.write_file(raw_eeg_data, full_path, "a")

			# c3 = raw_eeg_data[self.DEFAULT_C3_CHANNEL_INDEX, :]
			# cz = raw_eeg_data[self.DEFAULT_CZ_CHANNEL_INDEX, :]
			# c4 = raw_eeg_data[self.DEFAULT_C4_CHANNEL_INDEX, :]

			if self.recording_reference:
				self.reference_eeg_data.append_data(raw_eeg_data)
				print(f"reference size: {self.reference_eeg_data.sample_count()}")
				self.recording_progress_dialog.setValue(self.reference_eeg_data.get_channel_data(0).shape[0])
			else:
				self.eeg_data_buffer.append_data(raw_eeg_data)
				print(f"data size: {self.eeg_data_buffer.sample_count()}")
				self.recording_progress_dialog.setValue(self.eeg_data_buffer.get_channel_data(0).shape[0])

	def load_existing_data(self):
		path = QFileDialog.getExistingDirectory(self, "Root Directory...")

		if path == "":
			return

		filter_settings = utils.FilterSettings(global_config.SAMPLING_RATE, self.DEFAULT_BANDPASS_MIN, self.DEFAULT_BANDPASS_MAX)

		frequencies, eeg_data, reference_data = utils.load_slice_and_filter_resonance_data(path, filter_settings)

		print(frequencies)

		size = len(frequencies)

		x = np.arange(size)

		x_ticks = []

		plot_data = np.zeros((3, size))

		for i in range(size):
			current_eeg_data = eeg_data[i]
			freq = frequencies[i]
			x_ticks.append(f"{freq} Hz")
			freq_band = utils.FrequencyBand(
				freq - self.DEFAULT_FREQUENCY_PADDING,
				freq + self.DEFAULT_FREQUENCY_PADDING)

			reference_c3_extractor = reference_data.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_cz_extractor = reference_data.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_c4_extractor = reference_data.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c3_extractor = current_eeg_data.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_cz_extractor = current_eeg_data.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c4_extractor = current_eeg_data.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			c3_diff, cz_diff, c4_diff = self.amplitude_diff(freq_band, reference_c3_extractor, reference_cz_extractor,
															reference_c4_extractor, data_c3_extractor,
															data_cz_extractor, data_c4_extractor)

			plot_data[0, i] = c3_diff
			plot_data[1, i] = cz_diff
			plot_data[2, i] = c4_diff

		plt.figure()
		plt.title("Amplitude Increase")

		plt.bar(x, plot_data[0], width=0.25, label="C3 amplitude increase")
		plt.bar(x + 0.25, plot_data[1], width=0.25, label="Cz amplitude increase")
		plt.bar(x + 0.50, plot_data[2], width=0.25, label="C4 amplitude increase")

		plt.xticks(x + 0.25, x_ticks)
		plt.ylabel("Average Band Amplitude")

		plt.legend(loc="best")
		plt.show()

	def amplitude_diff(self, freq_band, ref_c3_extractor, ref_cz_extractor, ref_c4_extractor, data_c3_extractor, data_cz_extractor, data_c4_extractor):
		ref_c3_amplitude = ref_c3_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		ref_cz_amplitude = ref_cz_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		ref_c4_amplitude = ref_c4_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)

		data_c3_amplitude = data_c3_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		data_cz_amplitude = data_cz_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)
		data_c4_amplitude = data_c4_extractor.average_band_amplitude(freq_band, self.DEFAULT_FFT_WINDOW_SIZE)

		c3_diff = data_c3_amplitude - ref_c3_amplitude
		cz_diff = data_cz_amplitude - ref_cz_amplitude
		c4_diff = data_c4_amplitude - ref_c4_amplitude

		return c3_diff, cz_diff, c4_diff
		# return data_c3_amplitude, data_cz_amplitude, data_c4_amplitude

	def stop_recording(self, reference: bool = False):
		if self.reading_timer is not None:
			self.reading_timer.deleteLater()

		self.board.stop_stream()
		self.recording = False
		self.recording_reference = False
		self.recording_progress_dialog.setValue(self.recording_progress_dialog.maximum())

		recording_duration_in_samples = self.recording_progress_dialog.maximum()
		selected_freq = self.frequency_slider.value()

		if reference:
			sample_count = min(self.reference_eeg_data.get_channel_data(0).shape[0], recording_duration_in_samples)
			sample_count -= global_config.SAMPLING_RATE * self.DEFAULT_SAMPLE_PADDING
			self.index_generator.add_slice(0, self.eeg_sample_count - sample_count, self.eeg_sample_count)
		else:
			sample_count = min(self.eeg_data_buffer.get_channel_data(0).shape[0], recording_duration_in_samples)
			sample_count -= global_config.SAMPLING_RATE * self.DEFAULT_SAMPLE_PADDING
			self.index_generator.add_slice(selected_freq, self.eeg_sample_count - sample_count, self.eeg_sample_count)

		if self.root_directory_label.text() != "":
			self.index_generator.write_to_file(self.root_directory_label.text())

		QApplication.beep()

		start = self.DEFAULT_SAMPLE_PADDING * global_config.SAMPLING_RATE

		if reference:
			print(f"reference size: {self.reference_eeg_data.sample_count()}")
			self.record_btn.setEnabled(True)
			# self.record_reference_btn.setEnabled(False)
			self.reference_eeg_data.filter_all_channels(
				global_config.SAMPLING_RATE, self.DEFAULT_BANDPASS_MIN, self.DEFAULT_BANDPASS_MAX, True
			)
			self.reference_eeg_data = utils.EegData(self.reference_eeg_data.to_row_array()[:, start:])
			print("Reference data saved...")
		else:
			print("Stopping the recording...")

			print("Filtering data...")

			self.eeg_data_buffer.filter_all_channels(
				global_config.SAMPLING_RATE, self.DEFAULT_BANDPASS_MIN, self.DEFAULT_BANDPASS_MAX, subtract_average=True
			)

			self.eeg_data_buffer = utils.EegData(self.eeg_data_buffer.to_row_array()[:, start:])

			print(f"data size: {self.eeg_data_buffer.sample_count()}")

			reference_c3_extractor = self.reference_eeg_data.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_cz_extractor = self.reference_eeg_data.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			reference_c4_extractor = self.reference_eeg_data.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c3_extractor = self.eeg_data_buffer.feature_extractor(
				self.DEFAULT_C3_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_cz_extractor = self.eeg_data_buffer.feature_extractor(
				self.DEFAULT_CZ_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			data_c4_extractor = self.eeg_data_buffer.feature_extractor(
				self.DEFAULT_C4_CHANNEL_INDEX, global_config.SAMPLING_RATE
			)

			for i in range(self.c3_amplitude_bar_set.count()):
				current_freq = int(self.frequencies[i].replace(" Hz", ""))
				if current_freq == selected_freq:
					freq_band = utils.FrequencyBand(
						current_freq - self.DEFAULT_FREQUENCY_PADDING,
						current_freq + self.DEFAULT_FREQUENCY_PADDING)

					c3_diff, cz_diff, c4_diff = self.amplitude_diff(freq_band, reference_c3_extractor,reference_cz_extractor, reference_c4_extractor,
																	data_c3_extractor, data_cz_extractor, data_c4_extractor)

					print(f"C3 diff = {c3_diff}")
					print(f"Cz diff = {cz_diff}")
					print(f"C4 diff = {c4_diff}")

					self.c3_amplitude_bar_set.replace(i, c3_diff)
					self.cz_amplitude_bar_set.replace(i, cz_diff)
					self.c4_amplitude_bar_set.replace(i, c4_diff)

			utils.auto_adjust_axis(self.amplitude_axis,
								[self.c3_amplitude_bar_set, self.cz_amplitude_bar_set, self.c4_amplitude_bar_set], self.DEFAULT_GRAPH_PADDING)

	def auto_adjust_axis(self):
		# Adjust the range so that everything is visible and add some gaps

		c3_min = sys.maxsize
		cz_min = sys.maxsize
		c4_min = sys.maxsize

		c3_max = -sys.maxsize
		cz_max = -sys.maxsize
		c4_max = -sys.maxsize

		for i in range(self.c3_amplitude_bar_set.count()):
			c3_min = min(c3_min, self.c3_amplitude_bar_set.at(i))
			cz_min = min(cz_min, self.cz_amplitude_bar_set.at(i))
			c4_min = min(c4_min, self.c4_amplitude_bar_set.at(i))

			c3_max = max(c3_max, self.c3_amplitude_bar_set.at(i))
			cz_max = max(cz_max, self.cz_amplitude_bar_set.at(i))
			c4_max = max(c4_max, self.c4_amplitude_bar_set.at(i))

		print("c3 min = {}, cz min = {}, c4 min = {}".format(c3_min, cz_min, c4_min))
		print("c3 max = {}, cz max = {}, c4 max = {}".format(c3_max, cz_max, c4_max))

		axis_min = min(0, c3_min, cz_min, c4_min) - self.DEFAULT_GRAPH_PADDING
		axis_max = max(0, c3_max, cz_max, c4_max) + self.DEFAULT_GRAPH_PADDING

		print("axis min = {}, axis max = {}".format(axis_min, axis_max))

		self.amplitude_axis.setMin(axis_min)
		self.amplitude_axis.setMax(axis_max)