mutex, move series creation to chart, remove unused functions

This commit is contained in:
Benedek László 2024-05-18 22:18:17 +02:00
parent 03b0591371
commit 966db4f4e1
7 changed files with 97 additions and 78 deletions

View File

@ -21,12 +21,7 @@ class ChartWidget : public QListWidgetItem {
void addData(const char* seriesName, const point_t* points, int count); 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; }
QList<QAbstractSeries*> getSeries() const { return chart->series(); } QList<QAbstractSeries*> getSeries() const { return chart->series(); }
QValueAxis* getX() const { return x; }
QValueAxis* getY() const { return y; }
const chart_spec_t& getSpec() const { return spec; }
void clear(); void clear();
private: private:
@ -36,7 +31,7 @@ class ChartWidget : public QListWidgetItem {
chart_spec_t spec; chart_spec_t spec;
int decimateState = 0; int decimateState = 0;
mutable QMutex mutex; QMutex mutex;
}; };
class ContextMenu : public QMenu { class ContextMenu : public QMenu {

View File

@ -21,8 +21,6 @@ class SpecDialog : public QDialog {
static SpecDialog* getInstance(); static SpecDialog* getInstance();
static void close(); static void close();
QStringList getList() const { return series->stringList(); }
chart_spec_t getSpec() const; chart_spec_t getSpec() const;
private: private:

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <QList>
#include <QString> #include <QString>
struct axis_spec_t { struct axis_spec_t {
@ -19,4 +20,5 @@ struct chart_spec_t {
struct { struct {
axis_spec_t x, y; axis_spec_t x, y;
} axis; } axis;
QList<QString> series;
}; };

View File

@ -38,6 +38,14 @@ ChartWidget::ChartWidget(QWidget* parent, const chart_spec_t& spec) : QListWidge
chart->addAxis(x, Qt::AlignBottom); chart->addAxis(x, Qt::AlignBottom);
chart->addAxis(y, Qt::AlignLeft); chart->addAxis(y, Qt::AlignLeft);
for (const QString& title : spec.series) {
QLineSeries* series = new QLineSeries(view);
series->setName(title);
chart->addSeries(series);
series->attachAxis(x);
series->attachAxis(y);
}
view->setRenderHint(QPainter::Antialiasing); view->setRenderHint(QPainter::Antialiasing);
view->setChart(chart); view->setChart(chart);
view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@ -61,6 +69,8 @@ ChartWidget::~ChartWidget() {
void ChartWidget::addData(const char* seriesName, const point_t* points, int count) { void ChartWidget::addData(const char* seriesName, const point_t* points, int count) {
QMutexLocker locker(&mutex); QMutexLocker locker(&mutex);
std::cout << "locked: " << locker.isLocked() << std::endl;
QString name(seriesName); QString name(seriesName);
double minX = spec.keep_all ? x->min() : std::numeric_limits<double>::max(); double minX = spec.keep_all ? x->min() : std::numeric_limits<double>::max();
@ -74,10 +84,12 @@ void ChartWidget::addData(const char* seriesName, const point_t* points, int cou
if (count >= spec.keep_limit) { if (count >= spec.keep_limit) {
((QLineSeries*)series)->clear(); ((QLineSeries*)series)->clear();
} else if (((QLineSeries*)series)->count() + count > spec.keep_limit) { } else if (((QLineSeries*)series)->count() + count > spec.keep_limit) {
std::cout << "count: " << count << ", size: " << ((QLineSeries*)series)->count() << ", remove: " << ((QLineSeries*)series)->count() - (spec.keep_limit - count) << std::endl;
((QLineSeries*)series)->removePoints(0, ((QLineSeries*)series)->count() - (spec.keep_limit - count)); ((QLineSeries*)series)->removePoints(0, ((QLineSeries*)series)->count() - (spec.keep_limit - count));
} }
for (QPointF point : ((QLineSeries*)series)->points()) { std::cout << "starting min/max" << std::endl;
for (const QPointF& point : ((QLineSeries*)series)->points()) {
if (spec.axis.x.auto_limit) { if (spec.axis.x.auto_limit) {
minX = MIN(minX, point.x()); minX = MIN(minX, point.x());
maxX = MAX(maxX, point.x()); maxX = MAX(maxX, point.x());
@ -87,8 +99,12 @@ void ChartWidget::addData(const char* seriesName, const point_t* points, int cou
maxY = MAX(maxY, point.y()); maxY = MAX(maxY, point.y());
} }
} }
std::cout << "got min/max" << std::endl;
} }
std::cout << "start adding" << std::endl;
QList<QPointF> newPoints;
for (int i = spec.keep_all ? 0 : MAX(0, count - spec.keep_limit); i < count; i++) { for (int i = spec.keep_all ? 0 : MAX(0, count - spec.keep_limit); i < count; i++) {
if (decimateState >= spec.decimate) if (decimateState >= spec.decimate)
decimateState = 0; decimateState = 0;
@ -104,19 +120,20 @@ void ChartWidget::addData(const char* seriesName, const point_t* points, int cou
maxY = MAX(maxY, points[i].y); maxY = MAX(maxY, points[i].y);
} }
*((QLineSeries*)series) << QPointF(points[i].x, points[i].y); newPoints.append(QPointF(points[i].x, points[i].y));
} }
std::cout << "adding" << std::endl;
((QLineSeries*)series)->append(newPoints);
if (spec.axis.x.auto_limit) if (spec.axis.x.auto_limit)
x->setRange(minX, maxX); x->setRange(MIN(x->min(), minX), MAX(x->max(), maxX));
if (spec.axis.y.auto_limit) if (spec.axis.y.auto_limit)
y->setRange(minY, maxY); y->setRange(MIN(y->min(), minY), MAX(y->max(), maxY));
break; break;
} }
} }
view->update();
} }
void ChartWidget::clear() { void ChartWidget::clear() {
@ -128,7 +145,6 @@ void ChartWidget::clear() {
x->setRange(spec.axis.x.min, spec.axis.x.max); x->setRange(spec.axis.x.min, spec.axis.x.max);
y->setRange(spec.axis.y.min, spec.axis.y.max); y->setRange(spec.axis.y.min, spec.axis.y.max);
decimateState = 0; decimateState = 0;
view->update();
} }
ContextMenu::ContextMenu(QWidget* parent, ChartWidget* chartWidget) : QMenu(parent) { ContextMenu::ContextMenu(QWidget* parent, ChartWidget* chartWidget) : QMenu(parent) {

View File

@ -85,15 +85,6 @@ void MainWindow::on_action_Add_triggered() {
ui->graphsListWidget->addItem(chart); ui->graphsListWidget->addItem(chart);
ui->graphsListWidget->setItemWidget(chart, chart->getView()); ui->graphsListWidget->setItemWidget(chart, chart->getView());
for (QString title : dialog->getList()) {
QLineSeries* series = new QLineSeries();
series->setName(title);
chart->getChart()->addSeries(series);
for (QAbstractAxis* axis : chart->getChart()->axes()) {
series->attachAxis(axis);
}
}
} }
void MainWindow::on_action_Load_triggered() { void MainWindow::on_action_Load_triggered() {

View File

@ -48,6 +48,7 @@ chart_spec_t SpecDialog::getSpec() const {
.keep_limit = ui->keep->value(), .keep_limit = ui->keep->value(),
.decimate = ui->decimate->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()}},
.series = series->stringList()};
} }
} // namespace Graph::GUI } // namespace Graph::GUI

View File

@ -4,33 +4,40 @@ 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 pyaudio from argparse import ArgumentParser
# import pyaudio
def sine(): def sine(args):
x = 0.0 x = 0.0
while True: while True:
requests.get(f"http://localhost:8080/add?chart=0&series=R1&x={x}&y={sin(x)}") try:
requests.get(f"http://{args.address}:{args.port}/add?chart={args.chart}&series={args.series}&x={x}&y={sin(x)}")
x += 0.01 x += 0.01
sleep(0.01) sleep(0.01)
except KeyboardInterrupt:
break
def sine_array(): def sine_array(args):
start = 0 start = 0
while True: while True:
try:
x = np.linspace(start, start+0.5, 100) x = np.linspace(start, start+0.5, 100)
y = np.sin(x) y = np.sin(x)
start += 0.5 start += 0.5
data = { data = {
"chart": 0, "chart": args.chart,
"series": "R1", "series": args.series,
"points": [ {"x": i[0], "y":i[1]} for i in zip(x,y) ] "points": [ {"x": i[0], "y":i[1]} for i in zip(x,y) ]
} }
r = requests.post("http://0.0.0.0:8080/add", json=data, headers={"Connection":"close"}) r = requests.post(f"http://{args.address}:{args.port}/add", json=data)
sleep(0.25) sleep(0.25)
except KeyboardInterrupt:
break
def star(): def star(args):
points = [ points = [
(2,2), (2,2),
(3,0), (3,0),
@ -40,43 +47,52 @@ def star():
(2,2) (2,2)
] ]
for point in points: for point in points:
requests.get(f"http://localhost:8080/add?chart=0&series=R1&x={point[0]}&y={point[1]}") requests.get(f"http://{args.address}:{args.port}/add?chart={args.chart}&series={args.series}&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
def audio(): # stream.stop_stream()
p = pyaudio.PyAudio() # stream.close()
stream = p.open( # p.terminate()
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()
#star()
audio()
if __name__ == "__main__": if __name__ == "__main__":
main() parser = ArgumentParser()
parser.add_argument("-t", action="store", dest="test", help="test type", type=str, choices=["sine", "sine_array", "star"], required=False, default="sin")
parser.add_argument("-n", action="store", dest="num", help="sin_array size/iteration", type=int, required=False, default=100)
parser.add_argument("-d", action="store", dest="delay", help="delay between iteration", type=float, required=False, default=0.25)
parser.add_argument("-c", action="store", dest="chart", help="chart id", type=int, required=True)
parser.add_argument("-s", action="store", dest="series", help="series name", type=str, required=True)
parser.add_argument("-p", action="store", dest="port", help="server port", type=int, required=False, default=8080)
parser.add_argument("-a", action="store", dest="address", help="server address", type=str, required=False, default="localhost")
args = parser.parse_args()
if args.test == "sine":
sine(args)
elif args.test == "sine_array":
sine_array(args)
elif args.test == "star":
star(args)