From 03b0591371238f0488e335ea76875627788267c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benedek=20L=C3=A1szl=C3=B3?= Date: Fri, 17 May 2024 21:14:05 +0200 Subject: [PATCH] move addData to charts, decimate --- inc/graph/server/gui/chart/chart.h | 7 ++ inc/graph/server/spec.h | 1 + src/graph/server/gui/chart/chart.cpp | 80 ++++++++++++- src/graph/server/gui/mainwindow.cpp | 40 +------ .../server/gui/specdialog/specdialog.cpp | 1 + src/graph/server/gui/specdialog/specdialog.ui | 109 +++++++++++++----- test/test.py | 34 +++++- 7 files changed, 198 insertions(+), 74 deletions(-) diff --git a/inc/graph/server/gui/chart/chart.h b/inc/graph/server/gui/chart/chart.h index 0cbf6da..4da78e1 100644 --- a/inc/graph/server/gui/chart/chart.h +++ b/inc/graph/server/gui/chart/chart.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include namespace Graph::GUI { class ChartWidget : public QListWidgetItem { @@ -16,6 +18,8 @@ class ChartWidget : public QListWidgetItem { ChartWidget(QWidget* parent = nullptr, const chart_spec_t& spec = chart_spec_t()); ~ChartWidget(); + void addData(const char* seriesName, const point_t* points, int count); + QChartView* getView() const { return view; } QChart* getChart() const { return chart; } QList getSeries() const { return chart->series(); } @@ -30,6 +34,9 @@ class ChartWidget : public QListWidgetItem { QChart* chart; QValueAxis *x, *y; chart_spec_t spec; + int decimateState = 0; + + mutable QMutex mutex; }; class ContextMenu : public QMenu { diff --git a/inc/graph/server/spec.h b/inc/graph/server/spec.h index 1fd0356..04d61dd 100644 --- a/inc/graph/server/spec.h +++ b/inc/graph/server/spec.h @@ -15,6 +15,7 @@ struct chart_spec_t { bool legend = false; bool keep_all = true; int keep_limit; + int decimate; struct { axis_spec_t x, y; } axis; diff --git a/src/graph/server/gui/chart/chart.cpp b/src/graph/server/gui/chart/chart.cpp index ab718d8..7149c03 100644 --- a/src/graph/server/gui/chart/chart.cpp +++ b/src/graph/server/gui/chart/chart.cpp @@ -2,8 +2,13 @@ #include #include #include +#include #include #include +#include + +#define MIN(a, b) (a < b ? a : b) +#define MAX(a, b) (a > b ? a : b) namespace Graph::GUI { ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QListWidgetItem(), spec(spec) { @@ -53,17 +58,82 @@ ChartWidget::~ChartWidget() { // delete y; } -void ChartWidget::clear() { +void ChartWidget::addData(const char* seriesName, const point_t* points, int count) { + QMutexLocker locker(&mutex); + + QString name(seriesName); + + double minX = spec.keep_all ? x->min() : std::numeric_limits::max(); + double minY = spec.keep_all ? y->min() : std::numeric_limits::max(); + double maxX = spec.keep_all ? x->max() : std::numeric_limits::min(); + double maxY = spec.keep_all ? y->max() : std::numeric_limits::min(); + for (QAbstractSeries* series : chart->series()) { - ((QLineSeries*)series)->removePoints(0, ((QLineSeries*)series)->count()); + if (series->name() == name) { + if (!spec.keep_all) { + if (count >= spec.keep_limit) { + ((QLineSeries*)series)->clear(); + } else if (((QLineSeries*)series)->count() + count > spec.keep_limit) { + ((QLineSeries*)series)->removePoints(0, ((QLineSeries*)series)->count() - (spec.keep_limit - count)); + } + + for (QPointF point : ((QLineSeries*)series)->points()) { + if (spec.axis.x.auto_limit) { + minX = MIN(minX, point.x()); + maxX = MAX(maxX, point.x()); + } + if (spec.axis.y.auto_limit) { + minY = MIN(minY, point.y()); + maxY = MAX(maxY, point.y()); + } + } + } + + for (int i = spec.keep_all ? 0 : MAX(0, count - spec.keep_limit); i < count; i++) { + if (decimateState >= spec.decimate) + decimateState = 0; + if (decimateState++ % spec.decimate != 0) + continue; + + if (spec.axis.x.auto_limit) { + minX = MIN(minX, points[i].x); + maxX = MAX(maxX, points[i].x); + } + if (spec.axis.y.auto_limit) { + minY = MIN(minY, points[i].y); + maxY = MAX(maxY, points[i].y); + } + + *((QLineSeries*)series) << QPointF(points[i].x, points[i].y); + } + + if (spec.axis.x.auto_limit) + x->setRange(minX, maxX); + if (spec.axis.y.auto_limit) + y->setRange(minY, maxY); + + break; + } } + + view->update(); +} + +void ChartWidget::clear() { + QMutexLocker locker(&mutex); + + for (QAbstractSeries* series : chart->series()) { + ((QLineSeries*)series)->clear(); + } + x->setRange(spec.axis.x.min, spec.axis.x.max); + y->setRange(spec.axis.y.min, spec.axis.y.max); + decimateState = 0; + view->update(); } ContextMenu::ContextMenu(QWidget* parent, ChartWidget* chartWidget) : QMenu(parent) { remove = new QAction(tr("&Remove"), this); - connect(remove, &QAction::triggered, this, [chartWidget]() { - MainWindow::getInstance()->removeChart(chartWidget); - }); + connect(remove, &QAction::triggered, this, [chartWidget]() { MainWindow::getInstance()->removeChart(chartWidget); }); addAction(remove); clear = new QAction(tr("&Clear"), this); diff --git a/src/graph/server/gui/mainwindow.cpp b/src/graph/server/gui/mainwindow.cpp index ea96c66..e068427 100644 --- a/src/graph/server/gui/mainwindow.cpp +++ b/src/graph/server/gui/mainwindow.cpp @@ -9,9 +9,6 @@ #include #include -#define MIN(a, b) (a < b ? a : b) -#define MAX(a, b) (a > b ? a : b) - namespace Graph::GUI { MainWindow* MainWindow::instance = nullptr; @@ -44,42 +41,7 @@ void MainWindow::addData(unsigned int chartIndex, const char* seriesName, const if (chartIndex >= charts.size()) return; - QString name(seriesName); - - ChartWidget* chart = charts[chartIndex]; - - double minX = std::numeric_limits::max(), maxX = std::numeric_limits::min(); - double minY = std::numeric_limits::max(), maxY = std::numeric_limits::min(); - - chart_spec_t spec = chart->getSpec(); - - for (QAbstractSeries* series : chart->getSeries()) { - if (series->name() == name) { - for (int i = 0; i < count; i++) { - *((QLineSeries*)series) << QPointF(points[i].x, points[i].y); - } - - if (!spec.keep_all && ((QLineSeries*)series)->count() > spec.keep_limit) { - ((QLineSeries*)series)->removePoints(0, ((QLineSeries*)series)->count() - spec.keep_limit); - } - - for (QPointF point : ((QLineSeries*)series)->points()) { - minX = MIN(minX, point.x()); - maxX = MAX(maxX, point.x()); - minY = MIN(minY, point.y()); - maxY = MAX(maxY, point.y()); - } - - if (spec.axis.x.auto_limit) - chart->getX()->setRange(minX, maxX); - if (spec.axis.y.auto_limit) - chart->getY()->setRange(minY, maxY); - - break; - } - } - - chart->getView()->update(); + charts[chartIndex]->addData(seriesName, points, count); } MainWindow::MainWindow(QWidget* parent, int argc, char** argv) : QMainWindow(parent), ui(new Ui::MainWindow), argc(argc), argv(argv) { diff --git a/src/graph/server/gui/specdialog/specdialog.cpp b/src/graph/server/gui/specdialog/specdialog.cpp index fdc805b..ef1da2f 100644 --- a/src/graph/server/gui/specdialog/specdialog.cpp +++ b/src/graph/server/gui/specdialog/specdialog.cpp @@ -46,6 +46,7 @@ chart_spec_t SpecDialog::getSpec() const { .legend = ui->legend->isChecked(), .keep_all = ui->keepAll->isChecked(), .keep_limit = ui->keep->value(), + .decimate = ui->decimate->value(), .axis = {.x = {.label = ui->xTitle->text(), .auto_limit = ui->xAutoRange->isChecked(), .min = ui->xMin->value(), .max = ui->xMax->value()}, .y = {.label = ui->yTitle->text(), .auto_limit = ui->yAutoRange->isChecked(), .min = ui->yMin->value(), .max = ui->yMax->value()}}}; } diff --git a/src/graph/server/gui/specdialog/specdialog.ui b/src/graph/server/gui/specdialog/specdialog.ui index 5574b93..28cbd0a 100644 --- a/src/graph/server/gui/specdialog/specdialog.ui +++ b/src/graph/server/gui/specdialog/specdialog.ui @@ -6,7 +6,7 @@ 0 0 - 266 + 312 334 @@ -177,6 +177,9 @@ <html><head/><body><p>maximum</p></body></html> + + 1.000000000000000 + @@ -269,6 +272,9 @@ <html><head/><body><p>maximum</p></body></html> + + 1.000000000000000 + @@ -320,39 +326,86 @@ - - - QFrame::StyledPanel - - - QFrame::Raised - - + + + + 0 + + + 0 + + + 0 + + + 0 + - - - Keep + + + QFrame::StyledPanel + + QFrame::Raised + + + + + + Keep + + + + + + + Keep All + + + true + + + + + + + 2147483647 + + + 1000 + + + + - - - - Keep All + + + + QFrame::StyledPanel - - true - - - - - - - 2147483647 - - - 1000 + + QFrame::Raised + + + + + Decimate + + + + + + + 1 + + + 9999 + + + + diff --git a/test/test.py b/test/test.py index f171350..439f25f 100755 --- a/test/test.py +++ b/test/test.py @@ -4,7 +4,7 @@ import requests from math import sin from time import sleep import numpy as np -import json +import pyaudio def sine(): x = 0.0 @@ -43,10 +43,40 @@ def star(): requests.get(f"http://localhost:8080/add?chart=0&series=R1&x={point[0]}&y={point[1]}") +def audio(): + p = pyaudio.PyAudio() + stream = p.open( + input=True, + input_device_index=0, + format=pyaudio.paInt16, + channels=1, + rate=44100, + frames_per_buffer=1024 + ) + stream.start_stream() + while True: + try: + data = stream.read(1024, False) + requests.post( + "http://0.0.0.0:8080/add", + json={ + "chart": 0, + "series": "audio", + "points": [ {"x": i, "y": v} for (i, v) in enumerate(data) ] + }, + headers={"Connection":"close"}) + except KeyboardInterrupt: + break + + stream.stop_stream() + stream.close() + p.terminate() + def main(): #sine() - sine_array() + # sine_array() #star() + audio() if __name__ == "__main__": main()