SedSat3 1.1.6
Sediment Source Apportionment Tool - Advanced statistical methods for environmental pollution research
Loading...
Searching...
No Matches
generalplotter.cpp
Go to the documentation of this file.
1#include <QRubberBand>
2#include "generalplotter.h"
3#include "Utilities.h"
4
5template<typename T>
6static inline QVector<T> fromStdVector(const std::vector<T> &vector)
7{
8 return QVector<T>(vector.begin(), vector.end());
9}
10
11QVector<QCPScatterStyle::ScatterShape> GeneralPlotter::shapes = Make_Shapes();
12
14 : QCustomPlot(parent)
15 , mZoomMode(true)
16 , mRubberBand(new QRubberBand(QRubberBand::Rectangle, this))
17{
18 x_max_min_range.push_back(1e12);x_max_min_range.push_back(-1e12);
19 y_max_min_range.push_back(1e12);y_max_min_range.push_back(-1e12);
20
21
22}
23
28
33
34void GeneralPlotter::mousePressEvent(QMouseEvent * event)
35{
36 if (mZoomMode)
37 {
38 if (event->button() == Qt::LeftButton)
39 {
40 mOrigin = event->pos();
41 mRubberBand->setGeometry(QRect(mOrigin, QSize()));
42 mRubberBand->show();
43 }
44 }
45 QCustomPlot::mousePressEvent(event);
46}
47
48void GeneralPlotter::mouseMoveEvent(QMouseEvent * event)
49{
50 if (mRubberBand->isVisible())
51 {
52 mRubberBand->setGeometry(QRect(mOrigin, event->pos()).normalized());
53 }
54 //QCustomPlot::mouseMoveEvent(event);
55}
56void GeneralPlotter::wheelEvent(QWheelEvent *event)
57{
58 double scale = pow((double)2, event->angleDelta().y() / 360.0);
59 xAxis->scaleRange(scale, xAxis->range().center());
60 yAxis->scaleRange(scale, yAxis->range().center());
61 replot();
62
63}
64void GeneralPlotter::mouseReleaseEvent(QMouseEvent * event)
65{
66 if (mRubberBand->isVisible())
67 {
68 if (mRubberBand->geometry().height() > 5 && mRubberBand->geometry().width() > 5)
69 {
70 const QRect & zoomRect = mRubberBand->geometry();
71 int xp1, yp1, xp2, yp2;
72 zoomRect.getCoords(&xp1, &yp1, &xp2, &yp2);
73 auto x1 = xAxis->pixelToCoord(xp1);
74 auto x2 = xAxis->pixelToCoord(xp2);
75 auto y1 = yAxis->pixelToCoord(yp1);
76 auto y2 = yAxis->pixelToCoord(yp2);
77
78 xAxis->setRange(x1, x2);
79 yAxis->setRange(y1, y2);
80 }
81 mRubberBand->hide();
82 replot();
83 }
84
85 QCustomPlot::mouseReleaseEvent(event);
86}
87
88void GeneralPlotter::axisDoubleClick(QCPAxis * axis, QCPAxis::SelectablePart part, QMouseEvent * event)
89{
90 rescaleAxes(true);
91 /*
92 if (!graphCount())
93 return;
94 if (axis == xAxis)
95 {
96 qreal min = *std::min_element(graph(0)->data()->keys().begin(), graph(0)->data()->keys().end());
97 qreal max = *std::max_element(graph(0)->data()->keys().begin(), graph(0)->data()->keys().end());
98 for (int i = 0; i < graphCount(); i++)
99 {
100 if (min > *std::min_element(graph(i)->data()->keys().begin(), graph(i)->data()->keys().end()))
101 min = *std::min_element(graph(i)->data()->keys().begin(), graph(i)->data()->keys().end());
102 if (max < *std::max_element(graph(i)->data()->keys().begin(), graph(i)->data()->keys().end()))
103 max = *std::max_element(graph(i)->data()->keys().begin(), graph(i)->data()->keys().end());
104 }
105 axis->setRange(min, max);
106 }
107 else if (axis == yAxis)
108 {
109 qreal min = *std::min_element(graph(0)->data()->values().begin(), graph(0)->data()->values().end());
110 qreal max = *std::max_element(graph(0)->data()->values().begin(), graph(0)->data()->values().end());
111 for (int i = 0; i < graphCount(); i++)
112 {
113 if (min > *std::min_element(graph(i)->data() .begin(), graph(i)->data()->values().end()))
114 min = *std::min_element(graph(i)->data()->values().begin(), graph(i)->data()->values().end());
115 if (max < *std::max_element(graph(i)->data()->values().begin(), graph(i)->data()->values().end()))
116 max = *std::max_element(graph(i)->data()->values().begin(), graph(i)->data()->values().end());
117 }
118 axis->setRange(min, max);
119 }
120 axis->rang*/
121}
122
123bool GeneralPlotter::AddScatter(const string &name, const vector<double> &x, const vector<double> &y, const QCPScatterStyle &symbol)
124{
125 x_max_min_range[0] = min(x_max_min_range[0],aquiutils::Min(x));
126 x_max_min_range[1] = max(x_max_min_range[1],aquiutils::Max(x));
127 y_max_min_range[0] = min(y_max_min_range[0],aquiutils::Min(y));
128 y_max_min_range[1] = max(y_max_min_range[1],aquiutils::Max(y));
129 if (x.size()!=y.size())
130 return false;
131
132 QCPGraph *graph = new QCPGraph(xAxis, yAxis);
133
134 graph->setName(QString::fromStdString(name));
135 graph->setPen(QPen(QColor(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256))));
136 graph->setLineStyle(QCPGraph::lsNone);
137 graph->setScatterStyle(symbol);
138
139 QVector<double> xvals = fromStdVector<double>(x);
140 QVector<double> yvals = fromStdVector<double>(y);
141
142 graph->setData(xvals, yvals);
145 replot();
146 return true;
147}
148bool GeneralPlotter::AddScatter(const string &name, const vector<string> &x, const vector<double> &y, const QCPScatterStyle &symbol)
149{
150 x_max_min_range[0] = min(x_max_min_range[0],double(0));
151 x_max_min_range[1] = max(x_max_min_range[1],double(x.size())*1.1);
152 y_max_min_range[0] = min(y_max_min_range[0],aquiutils::Min(y));
153 y_max_min_range[1] = max(y_max_min_range[1],aquiutils::Max(y));
154 if (x.size()!=y.size())
155 return false;
156
157 QCPGraph *graph = new QCPGraph(xAxis, yAxis);
158
159 graph->setName(QString::fromStdString(name));
160 graph->setPen(QPen(QColor(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256)), 2));
161 graph->setLineStyle(QCPGraph::lsNone);
162 graph->setScatterStyle(symbol);
163
164 QVector<double> yvals = fromStdVector<double>(y);
165
166 QVector<double> ticks;
167 QVector<QString> labels;
168 QVector<double> qvals = fromStdVector<double>(y);
169 for (int i=0; i<y.size(); i++)
170 { ticks << i+1;
171 labels << QString::fromStdString(x[i]);
172 }
173 QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
174 textTicker->addTicks(ticks, labels);
175 xAxis->setTicker(textTicker);
176 xAxis->setTickLabelRotation(60);
177 xAxis->setSubTicks(false);
178 xAxis->setTickLength(0, 4);
179
180 graph->setData(ticks, yvals);
183 replot();
184 return true;
185}
186
193
194bool GeneralPlotter::AddScatters(const vector<string> names, const vector<vector<double>> &x,const vector<vector<double>> &y)
195{
196 if (names.size()!=x.size())
197 return false;
198 if (names.size()!=y.size())
199 return false;
200 for (int i=0; i<names.size(); i++)
201 {
202 AddScatter(names[i],x[i],y[i],shapes[i%shapes.size()]);
203 }
204 replot();
205 return true;
206}
207bool GeneralPlotter::AddScatters(const vector<string> names, const vector<string> &x,const vector<vector<double>> &y)
208{
209 if (names.size()!=y.size())
210 return false;
211 for (int i=0; i<names.size(); i++)
212 {
213 if (y[i].size()!=x.size())
214 return false;
215 AddScatter(names[i],x,y[i],shapes[i%shapes.size()]);
216 }
217 replot();
218 return true;
219}
220bool GeneralPlotter::AddTimeSeries(const string &name, const vector<double> &x, const vector<double> &y)
221{
222 x_max_min_range[0] = min(x_max_min_range[0],aquiutils::Min(x));
223 x_max_min_range[1] = max(x_max_min_range[1],aquiutils::Max(x)*1.1);
224 y_max_min_range[0] = min(y_max_min_range[0],aquiutils::Min(y));
225 y_max_min_range[1] = max(y_max_min_range[1],aquiutils::Max(y));
226 if (x.size()!=y.size())
227 return false;
228
229 QCPGraph *graph = new QCPGraph(xAxis, yAxis);
230
231 graph->setName(QString::fromStdString(name));
232 QPen Pen = QPen(QColor(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256)));
233 Pen.setWidth(3);
234 graph->setPen(Pen);
235 graph->setLineStyle(QCPGraph::lsLine);
236
237 QVector<double> yvals = fromStdVector<double>(y);
238 QVector<double> xvals = fromStdVector<double>(x);
239
240 xAxis->setTickLabelRotation(60);
241 xAxis->setSubTicks(false);
242 xAxis->setTickLength(0, 4);
243
244 graph->setData(xvals, yvals);
247 replot();
248 return true;
249
250}
251bool GeneralPlotter::AddTimeSeriesSet(const string &name, const vector<vector<double>> &x, const vector<vector<double>> &y)
252{
253 return true;
254}
256{
257 if (axisscale==AxisScale::log)
258 {
259 QSharedPointer<QCPAxisTickerLog> logTicker(new QCPAxisTickerLog);
260 logTicker->setLogBase(10);
261 logTicker->setSubTickCount(10);
262 yAxis->setTicker(logTicker);
263 yAxis->setScaleType(QCPAxis::ScaleType::stLogarithmic);
264 }
265 else
266 {
267 yAxis->setScaleType(QCPAxis::ScaleType::stLinear);
268 }
269 return true;
270}
271
272void GeneralPlotter::SetRange(const vector<double> &range, const Axis &whichaxis)
273{
274 if (range.size()!=2)
275 {
276 return;
277 }
278 if (whichaxis==Axis::x)
279 {
280 xAxis->setRange(range[0],range[1]);
281 }
282 if (whichaxis==Axis::y)
283 {
284 yAxis->setRange(range[0],range[1]);
285 }
286}
287
289{
290 legend->setVisible(onoff);
291 if (onoff)
292 { axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop|Qt::AlignHCenter);
293 legend->setBrush(QColor(255, 255, 255, 100));
294 legend->setBorderPen(Qt::NoPen);
295 QFont legendFont = font();
296 legendFont.setPointSize(10);
297 legend->setFont(legendFont);
298 setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
299 }
300}
301
303{
304 clearPlottables();
305 clearGraphs();
306}
307
308bool GeneralPlotter::AddNonUniformScatter(const map<string,vector<double>> &data, int shape_counter)
309{
310 x_max_min_range[0] = double(0);
311 x_max_min_range[1] = double(data.size()*1.1);
312
313
314 QCPGraph *points = new QCPGraph(xAxis, yAxis);
315 points->setLineStyle(QCPGraph::lsNone);
316 points->setScatterStyle(shapes[shape_counter]);
317 points->setPen(QPen(QColor(QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256), QRandomGenerator::global()->bounded(256)),2));
318 int x_val=1;
319 QMap<double,QString> ticks;
320 for (map<string,vector<double>>::const_iterator set=data.begin(); set!=data.end(); set++ )
321 {
322 for (int i=0; i<set->second.size(); i++)
323 points->addData(x_val,set->second[i]);
324
325 ticks[x_val]=QString::fromStdString(set->first);
326 x_val++;
327 y_max_min_range[0] = min(y_max_min_range[0],aquiutils::Min(set->second));
328 y_max_min_range[1] = max(y_max_min_range[1],aquiutils::Max(set->second));
329 }
330
331 QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
332 textTicker->addTicks(ticks);
333 xAxis->setTicker(textTicker);
334 xAxis->setTickLabelRotation(60);
335 xAxis->setSubTicks(false);
336 xAxis->setTickLength(0, 4);
337
340 replot();
341 return true;
342}
343
344
345QVector<QCPScatterStyle::ScatterShape> Make_Shapes()
346{
347 QVector<QCPScatterStyle::ScatterShape> shapes;
348 shapes << QCPScatterStyle::ssCross;
349 shapes << QCPScatterStyle::ssPlus;
350 shapes << QCPScatterStyle::ssCircle;
351 shapes << QCPScatterStyle::ssDisc;
352 shapes << QCPScatterStyle::ssSquare;
353 shapes << QCPScatterStyle::ssDiamond;
354 shapes << QCPScatterStyle::ssStar;
355 shapes << QCPScatterStyle::ssTriangle;
356 shapes << QCPScatterStyle::ssTriangleInverted;
357 shapes << QCPScatterStyle::ssCrossSquare;
358 shapes << QCPScatterStyle::ssPlusSquare;
359 shapes << QCPScatterStyle::ssCrossCircle;
360 shapes << QCPScatterStyle::ssPlusCircle;
361 shapes << QCPScatterStyle::ssPeace;
362 shapes << QCPScatterStyle::ssCross;
363 shapes << QCPScatterStyle::ssPlus;
364 shapes << QCPScatterStyle::ssCircle;
365 shapes << QCPScatterStyle::ssDisc;
366 shapes << QCPScatterStyle::ssSquare;
367 shapes << QCPScatterStyle::ssDiamond;
368 shapes << QCPScatterStyle::ssStar;
369 shapes << QCPScatterStyle::ssTriangle;
370 shapes << QCPScatterStyle::ssTriangleInverted;
371 shapes << QCPScatterStyle::ssCrossSquare;
372 shapes << QCPScatterStyle::ssPlusSquare;
373 shapes << QCPScatterStyle::ssCrossCircle;
374 shapes << QCPScatterStyle::ssPlusCircle;
375 shapes << QCPScatterStyle::ssPeace;
376 return shapes;
377}
QRubberBand * mRubberBand
bool AddScatters(const vector< string > names, const vector< vector< double > > &x, const vector< vector< double > > &y)
static QVector< QCPScatterStyle::ScatterShape > shapes
void setZoomMode(bool mode)
void axisDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event)
bool SetYAxisScaleType(AxisScale axisscale)
virtual ~GeneralPlotter()
void mouseReleaseEvent(QMouseEvent *event) override
void SetLegend(bool onoff)
bool AddScatter(const string &name, const vector< double > &x, const vector< double > &y, const QCPScatterStyle &symbol=QCPScatterStyle::ssDisc)
void mouseMoveEvent(QMouseEvent *event) override
bool AddTimeSeriesSet(const string &name, const vector< vector< double > > &x, const vector< vector< double > > &y)
bool AddNonUniformScatter(const map< string, vector< double > > &data, int shape_counter=0)
void SetRange(const vector< double > &range, const Axis &whichaxis)
bool AddTimeSeries(const string &name, const vector< double > &x, const vector< double > &y)
vector< double > x_max_min_range
void wheelEvent(QWheelEvent *event)
vector< double > y_max_min_range
GeneralPlotter(QWidget *parent=0)
void mousePressEvent(QMouseEvent *event) override
static QVector< T > fromStdVector(const std::vector< T > &vector)
QVector< QCPScatterStyle::ScatterShape > Make_Shapes()
AxisScale