move addData to charts, decimate
This commit is contained in:
parent
59cbf02075
commit
03b0591371
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <graph/plugins/plugin.h>
|
||||||
#include <graph/server/spec.h>
|
#include <graph/server/spec.h>
|
||||||
#include <qevent.h>
|
#include <qevent.h>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@ -9,6 +10,7 @@
|
|||||||
#include <QListWidgetItem>
|
#include <QListWidgetItem>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QValueAxis>
|
#include <QValueAxis>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
namespace Graph::GUI {
|
namespace Graph::GUI {
|
||||||
class ChartWidget : public QListWidgetItem {
|
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(QWidget* parent = nullptr, const chart_spec_t& spec = chart_spec_t());
|
||||||
~ChartWidget();
|
~ChartWidget();
|
||||||
|
|
||||||
|
void addData(const char* seriesName, const point_t* points, int count);
|
||||||
|
|
||||||
QChartView* getView() const { return view; }
|
QChartView* getView() const { return view; }
|
||||||
QChart* getChart() const { return chart; }
|
QChart* getChart() const { return chart; }
|
||||||
QList<QAbstractSeries*> getSeries() const { return chart->series(); }
|
QList<QAbstractSeries*> getSeries() const { return chart->series(); }
|
||||||
@ -30,6 +34,9 @@ class ChartWidget : public QListWidgetItem {
|
|||||||
QChart* chart;
|
QChart* chart;
|
||||||
QValueAxis *x, *y;
|
QValueAxis *x, *y;
|
||||||
chart_spec_t spec;
|
chart_spec_t spec;
|
||||||
|
int decimateState = 0;
|
||||||
|
|
||||||
|
mutable QMutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContextMenu : public QMenu {
|
class ContextMenu : public QMenu {
|
||||||
|
@ -15,6 +15,7 @@ struct chart_spec_t {
|
|||||||
bool legend = false;
|
bool legend = false;
|
||||||
bool keep_all = true;
|
bool keep_all = true;
|
||||||
int keep_limit;
|
int keep_limit;
|
||||||
|
int decimate;
|
||||||
struct {
|
struct {
|
||||||
axis_spec_t x, y;
|
axis_spec_t x, y;
|
||||||
} axis;
|
} axis;
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
#include <graph/server/gui/mainwindow.h>
|
#include <graph/server/gui/mainwindow.h>
|
||||||
#include <qabstractseries.h>
|
#include <qabstractseries.h>
|
||||||
#include <qlineseries.h>
|
#include <qlineseries.h>
|
||||||
|
#include <qmutex.h>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#define MIN(a, b) (a < b ? a : b)
|
||||||
|
#define MAX(a, b) (a > b ? a : b)
|
||||||
|
|
||||||
namespace Graph::GUI {
|
namespace Graph::GUI {
|
||||||
ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QListWidgetItem(), spec(spec) {
|
ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QListWidgetItem(), spec(spec) {
|
||||||
@ -53,17 +58,82 @@ ChartWidget::~ChartWidget() {
|
|||||||
// delete y;
|
// 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<double>::max();
|
||||||
|
double minY = spec.keep_all ? y->min() : std::numeric_limits<double>::max();
|
||||||
|
double maxX = spec.keep_all ? x->max() : std::numeric_limits<double>::min();
|
||||||
|
double maxY = spec.keep_all ? y->max() : std::numeric_limits<double>::min();
|
||||||
|
|
||||||
for (QAbstractSeries* series : chart->series()) {
|
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) {
|
ContextMenu::ContextMenu(QWidget* parent, ChartWidget* chartWidget) : QMenu(parent) {
|
||||||
remove = new QAction(tr("&Remove"), this);
|
remove = new QAction(tr("&Remove"), this);
|
||||||
connect(remove, &QAction::triggered, this, [chartWidget]() {
|
connect(remove, &QAction::triggered, this, [chartWidget]() { MainWindow::getInstance()->removeChart(chartWidget); });
|
||||||
MainWindow::getInstance()->removeChart(chartWidget);
|
|
||||||
});
|
|
||||||
addAction(remove);
|
addAction(remove);
|
||||||
|
|
||||||
clear = new QAction(tr("&Clear"), this);
|
clear = new QAction(tr("&Clear"), this);
|
||||||
|
@ -9,9 +9,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#define MIN(a, b) (a < b ? a : b)
|
|
||||||
#define MAX(a, b) (a > b ? a : b)
|
|
||||||
|
|
||||||
namespace Graph::GUI {
|
namespace Graph::GUI {
|
||||||
|
|
||||||
MainWindow* MainWindow::instance = nullptr;
|
MainWindow* MainWindow::instance = nullptr;
|
||||||
@ -44,42 +41,7 @@ void MainWindow::addData(unsigned int chartIndex, const char* seriesName, const
|
|||||||
if (chartIndex >= charts.size())
|
if (chartIndex >= charts.size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString name(seriesName);
|
charts[chartIndex]->addData(seriesName, points, count);
|
||||||
|
|
||||||
ChartWidget* chart = charts[chartIndex];
|
|
||||||
|
|
||||||
double minX = std::numeric_limits<double>::max(), maxX = std::numeric_limits<double>::min();
|
|
||||||
double minY = std::numeric_limits<double>::max(), maxY = std::numeric_limits<double>::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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget* parent, int argc, char** argv) : QMainWindow(parent), ui(new Ui::MainWindow), argc(argc), argv(argv) {
|
MainWindow::MainWindow(QWidget* parent, int argc, char** argv) : QMainWindow(parent), ui(new Ui::MainWindow), argc(argc), argv(argv) {
|
||||||
|
@ -46,6 +46,7 @@ chart_spec_t SpecDialog::getSpec() const {
|
|||||||
.legend = ui->legend->isChecked(),
|
.legend = ui->legend->isChecked(),
|
||||||
.keep_all = ui->keepAll->isChecked(),
|
.keep_all = ui->keepAll->isChecked(),
|
||||||
.keep_limit = ui->keep->value(),
|
.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()},
|
.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()}}};
|
.y = {.label = ui->yTitle->text(), .auto_limit = ui->yAutoRange->isChecked(), .min = ui->yMin->value(), .max = ui->yMax->value()}}};
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>266</width>
|
<width>312</width>
|
||||||
<height>334</height>
|
<height>334</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -177,6 +177,9 @@
|
|||||||
<string>
|
<string>
|
||||||
<html><head/><body><p>maximum</p></body></html></string>
|
<html><head/><body><p>maximum</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -269,6 +272,9 @@
|
|||||||
<string>
|
<string>
|
||||||
<html><head/><body><p>maximum</p></body></html></string>
|
<html><head/><body><p>maximum</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -320,39 +326,86 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="frame_5">
|
<widget class="QWidget" name="widget_3" native="true">
|
||||||
<property name="frameShape">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<enum>QFrame::StyledPanel</enum>
|
<property name="leftMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="frameShadow">
|
</property>
|
||||||
<enum>QFrame::Raised</enum>
|
<property name="topMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QFrame" name="frame_5">
|
||||||
<property name="text">
|
<property name="frameShape">
|
||||||
<string>Keep</string>
|
<enum>QFrame::StyledPanel</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Keep</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="keepAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Keep All</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="keep">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>2147483647</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item alignment="Qt::AlignTop">
|
||||||
<widget class="QCheckBox" name="keepAll">
|
<widget class="QFrame" name="frame_6">
|
||||||
<property name="text">
|
<property name="frameShape">
|
||||||
<string>Keep All</string>
|
<enum>QFrame::StyledPanel</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked">
|
<property name="frameShadow">
|
||||||
<bool>true</bool>
|
<enum>QFrame::Raised</enum>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSpinBox" name="keep">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2147483647</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1000</number>
|
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Decimate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="decimate">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>9999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
34
test/test.py
34
test/test.py
@ -4,7 +4,7 @@ import requests
|
|||||||
from math import sin
|
from math import sin
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import json
|
import pyaudio
|
||||||
|
|
||||||
def sine():
|
def sine():
|
||||||
x = 0.0
|
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]}")
|
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():
|
def main():
|
||||||
#sine()
|
#sine()
|
||||||
sine_array()
|
# sine_array()
|
||||||
#star()
|
#star()
|
||||||
|
audio()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user