dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
scatterplotscopeconfig.cpp
Go to the documentation of this file.
1 
15 /*
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24  * for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, see <http://www.gnu.org/licenses/>
28  *
29  * Additional note on redistribution: The copyright and license notices above
30  * must be maintained in each individual source file that is a derivative work
31  * of this source file; otherwise redistribution is prohibited.
32  */
33 
34 #include "scatterplotdata.h"
36 #include "scopegadgetoptionspage.h"
37 
41 #include "uavobjects/uavobject.h"
42 #include "coreplugin/icore.h"
44 
49 {
50  scatterplot2dType = TIMESERIES2D;
51  m_refreshInterval = 50;
52  timeHorizon = 60;
53 }
54 
60 {
62  scatterplot2dType = (Scatterplot2dType)qSettings->value("scatterplot2dType").toUInt();
63  timeHorizon = qSettings->value("timeHorizon").toDouble();
64 
65  int dataSourceCount = qSettings->value("dataSourceCount").toInt();
66  for (int i = 0; i < dataSourceCount; i++) {
67  // Start reading XML block
68  qSettings->beginGroup(QString("scatterplotDataSource") + QString().number(i));
69 
71 
72  plotCurveConf->uavObjectName = qSettings->value("uavObject").toString();
73  plotCurveConf->uavFieldName = qSettings->value("uavField").toString();
74  plotCurveConf->color = qSettings->value("color").value<QRgb>();
75  plotCurveConf->yScalePower = qSettings->value("yScalePower").toInt();
76  plotCurveConf->mathFunction = qSettings->value("mathFunction").toString();
77  plotCurveConf->yMeanSamples = qSettings->value("yMeanSamples").toUInt();
78 
79  // Stop reading XML block
80  qSettings->endGroup();
81 
82  m_scatterplotSourceConfigs.append(plotCurveConf);
83  }
84 }
85 
90 Scatterplot2dScopeConfig::Scatterplot2dScopeConfig(Ui::ScopeGadgetOptionsPage *options_page)
91 {
92  bool parseOK = false;
93 
94  timeHorizon = options_page->spnDataSize->value();
95  scatterplot2dType = (Scatterplot2dType)options_page->cmbXAxisScatterplot2d
96  ->itemData(options_page->cmbXAxisScatterplot2d->currentIndex())
97  .toInt();
98 
99  for (int iIndex = 0; iIndex < options_page->lst2dCurves->count(); iIndex++) {
100  QListWidgetItem *listItem = options_page->lst2dCurves->item(iIndex);
101 
102  // Store some additional data for the plot curve on the list item
103  Plot2dCurveConfiguration *newPlotCurveConfigs = new Plot2dCurveConfiguration();
104  newPlotCurveConfigs->uavObjectName =
105  listItem->data(Qt::UserRole + ScopeGadgetOptionsPage::UR_UAVOBJECT).toString();
106  newPlotCurveConfigs->uavFieldName =
107  listItem->data(Qt::UserRole + ScopeGadgetOptionsPage::UR_UAVFIELD).toString();
108  newPlotCurveConfigs->yScalePower =
109  listItem->data(Qt::UserRole + ScopeGadgetOptionsPage::UR_SCALE).toInt(&parseOK);
110  if (!parseOK)
111  newPlotCurveConfigs->yScalePower = 0;
112 
113  QVariant varColor = listItem->data(Qt::UserRole + ScopeGadgetOptionsPage::UR_COLOR);
114  int rgb = varColor.toInt(&parseOK);
115  if (!parseOK)
116  newPlotCurveConfigs->color = QColor(Qt::black).rgb();
117  else
118  newPlotCurveConfigs->color = (QRgb)rgb;
119 
120  newPlotCurveConfigs->yMeanSamples =
121  listItem->data(Qt::UserRole + ScopeGadgetOptionsPage::UR_MEAN).toUInt(&parseOK);
122  if (!parseOK)
123  newPlotCurveConfigs->yMeanSamples = 1;
124 
125  newPlotCurveConfigs->mathFunction =
126  listItem->data(Qt::UserRole + ScopeGadgetOptionsPage::UR_MATHFUNCTION).toString();
127 
128  m_scatterplotSourceConfigs.append(newPlotCurveConfigs);
129  }
130 }
131 
133 
140 {
141  Scatterplot2dScopeConfig *originalScatterplot2dScopeConfig =
142  dynamic_cast<Scatterplot2dScopeConfig *>(originalScope);
144 
145  cloneObj->m_refreshInterval = originalScatterplot2dScopeConfig->m_refreshInterval;
146  cloneObj->timeHorizon = originalScatterplot2dScopeConfig->timeHorizon;
147  cloneObj->scatterplot2dType = originalScatterplot2dScopeConfig->scatterplot2dType;
148 
149  int scatterplotSourceCount =
150  originalScatterplot2dScopeConfig->m_scatterplotSourceConfigs.size();
151 
152  for (int i = 0; i < scatterplotSourceCount; i++) {
153  Plot2dCurveConfiguration *currentScatterplotSourceConf =
154  originalScatterplot2dScopeConfig->m_scatterplotSourceConfigs.at(i);
155  Plot2dCurveConfiguration *newScatterplotSourceConf = new Plot2dCurveConfiguration();
156 
157  newScatterplotSourceConf->uavObjectName = currentScatterplotSourceConf->uavObjectName;
158  newScatterplotSourceConf->uavFieldName = currentScatterplotSourceConf->uavFieldName;
159  newScatterplotSourceConf->color = currentScatterplotSourceConf->color;
160  newScatterplotSourceConf->yScalePower = currentScatterplotSourceConf->yScalePower;
161  newScatterplotSourceConf->yMeanSamples = currentScatterplotSourceConf->yMeanSamples;
162  newScatterplotSourceConf->mathFunction = currentScatterplotSourceConf->mathFunction;
163 
164  cloneObj->m_scatterplotSourceConfigs.append(newScatterplotSourceConf);
165  }
166 
167  return cloneObj;
168 }
169 
175 {
176  // Stop writing XML blocks
177  qSettings->beginGroup(QString("plot2d"));
178 
179  qSettings->setValue("timeHorizon", timeHorizon);
180  qSettings->setValue("plot2dType", SCATTERPLOT2D);
181  qSettings->setValue("scatterplot2dType", scatterplot2dType);
182 
183  int dataSourceCount = m_scatterplotSourceConfigs.size();
184  qSettings->setValue("dataSourceCount", dataSourceCount);
185 
186  // For each curve source in the plot
187  for (int i = 0; i < dataSourceCount; i++) {
188  Plot2dCurveConfiguration *plotCurveConf = m_scatterplotSourceConfigs.at(i);
189  qSettings->beginGroup(QString("scatterplotDataSource") + QString().number(i));
190 
191  qSettings->setValue("uavObject", plotCurveConf->uavObjectName);
192  qSettings->setValue("uavField", plotCurveConf->uavFieldName);
193  qSettings->setValue("color", plotCurveConf->color);
194  qSettings->setValue("mathFunction", plotCurveConf->mathFunction);
195  qSettings->setValue("yScalePower", plotCurveConf->yScalePower);
196  qSettings->setValue("yMeanSamples", plotCurveConf->yMeanSamples);
197 
198  // Stop writing XML blocks
199  qSettings->endGroup();
200  }
201  // Stop writing XML blocks
202  qSettings->endGroup();
203 }
204 
211  QList<Plot2dCurveConfiguration *> scatterplotSourceConfigs)
212 {
213  m_scatterplotSourceConfigs.clear();
214  m_scatterplotSourceConfigs.append(scatterplotSourceConfigs);
215 }
216 
223 {
224  preparePlot(scopeGadgetWidget);
225  scopeGadgetWidget->setScope(this);
226  scopeGadgetWidget->startTimer(m_refreshInterval);
227 
228  // Configure each data source
229  foreach (Plot2dCurveConfiguration *plotCurveConfig, m_scatterplotSourceConfigs) {
230  QString uavObjectName = plotCurveConfig->uavObjectName;
231  QString uavFieldName = plotCurveConfig->uavFieldName;
232  QRgb color = plotCurveConfig->color;
233 
234  ScatterplotData *scatterplotData = NULL;
235 
236  switch (scatterplot2dType) {
237  case SERIES2D:
238  scatterplotData = new SeriesPlotData(uavObjectName, uavFieldName);
239  break;
240  case TIMESERIES2D:
241  scatterplotData = new TimeSeriesPlotData(uavObjectName, uavFieldName);
242  break;
243  }
244 
245  scatterplotData->setXWindowSize(timeHorizon);
246  scatterplotData->setScalePower(plotCurveConfig->yScalePower);
247  scatterplotData->setMeanSamples(plotCurveConfig->yMeanSamples);
248  scatterplotData->setMathFunction(plotCurveConfig->mathFunction);
249 
250  // Generate the curve name
251  QString curveName =
252  (scatterplotData->getUavoName()) + "." + (scatterplotData->getUavoFieldName());
253  if (scatterplotData->getHaveSubFieldFlag())
254  curveName = curveName.append("." + scatterplotData->getUavoSubFieldName());
255 
256  // Get the uav object
257  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
258  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
259  UAVDataObject *obj =
260  dynamic_cast<UAVDataObject *>(objManager->getObject((scatterplotData->getUavoName())));
261  if (!obj) {
262  qDebug() << "Object " << scatterplotData->getUavoName() << " is missing";
263  return;
264  }
265 
266  // Get the units
267  QString units = getUavObjectFieldUnits(scatterplotData->getUavoName(),
268  scatterplotData->getUavoFieldName());
269 
270  // Generate name with scaling factor appeneded
271  QString curveNameScaled;
272  if (plotCurveConfig->yScalePower == 0)
273  curveNameScaled = curveName + "(" + units + ")";
274  else
275  curveNameScaled = curveName + "(x10^" + QString::number(plotCurveConfig->yScalePower)
276  + " " + units + ")";
277 
278  QString curveNameScaledMath;
279  if (plotCurveConfig->mathFunction == "None")
280  curveNameScaledMath = curveNameScaled;
281  else if (plotCurveConfig->mathFunction == "Boxcar average") {
282  curveNameScaledMath = curveNameScaled + " (avg)";
283  } else if (plotCurveConfig->mathFunction == "Standard deviation") {
284  curveNameScaledMath = curveNameScaled + " (std)";
285  } else {
286  // Shouldn't be able to get here. Perhaps a new math function was added without
287  // updating this list?
288  Q_ASSERT(0);
289  }
290 
291  while (scopeGadgetWidget->getDataSources().keys().contains(curveNameScaledMath))
292  curveNameScaledMath = curveNameScaledMath + "*";
293 
294  // Create the curve plot
295  QwtPlotCurve *plotCurve = new QwtPlotCurve(curveNameScaledMath);
296  plotCurve->setPen(QPen(QBrush(QColor(color), Qt::SolidPattern), (qreal)1, Qt::SolidLine,
297  Qt::SquareCap, Qt::BevelJoin));
298  plotCurve->setSamples(*(scatterplotData->getXData()), *(scatterplotData->getYData()));
299  plotCurve->attach(scopeGadgetWidget);
300  scatterplotData->setCurve(plotCurve);
301 
302  // Keep the curve details for later
303  scopeGadgetWidget->insertDataSources(curveNameScaledMath, scatterplotData);
304 
305  // Connect the UAVO
306  scopeGadgetWidget->connectUAVO(obj);
307  }
308  scopeGadgetWidget->replot();
309 }
310 
316 void Scatterplot2dScopeConfig::setGuiConfiguration(Ui::ScopeGadgetOptionsPage *options_page)
317 {
318  // Set the tab widget to 2D
319  options_page->tabWidget2d3d->setCurrentWidget(options_page->tabPlot2d);
320 
321  // Set the plot type
322  options_page->cmb2dPlotType->setCurrentIndex(
323  options_page->cmb2dPlotType->findData(SCATTERPLOT2D));
324 
325  // add the configured 2D curves
326  options_page->lst2dCurves->clear(); // Clear list first
327 
328  foreach (Plot2dCurveConfiguration *plotData, m_scatterplotSourceConfigs) {
329  options_page->cmbXAxisScatterplot2d->setCurrentIndex(scatterplot2dType);
330  options_page->spnDataSize->setValue(timeHorizon);
331 
332  QString uavObjectName = plotData->uavObjectName;
333  QString uavFieldName = plotData->uavFieldName;
334  int scale = plotData->yScalePower;
335  unsigned int mean = plotData->yMeanSamples;
336  QString mathFunction = plotData->mathFunction;
337  QVariant varColor = plotData->color;
338 
339  QString listItemDisplayText = uavObjectName + "." + uavFieldName; // Generate the name
340  options_page->lst2dCurves->addItem(listItemDisplayText); // Add the name to the list
341  int itemIdx =
342  options_page->lst2dCurves->count() - 1; // Get the index number for the new value
343  QListWidgetItem *listWidgetItem =
344  options_page->lst2dCurves->item(itemIdx); // Find the widget item
345 
346  bool parseOK = false;
347  QRgb rgbColor;
348 
349  if (uavObjectName != "") {
350  // Set the properties of the newly added list item
351  listItemDisplayText = uavObjectName + "." + uavFieldName;
352  rgbColor = (QRgb)varColor.toInt(&parseOK);
353  if (!parseOK)
354  rgbColor = qRgb(255, 0, 0);
355  } else {
356  listItemDisplayText = "New graph";
357  rgbColor = qRgb(255, 0, 0);
358  }
359 
360  QColor color = QColor(rgbColor);
361  listWidgetItem->setText(listItemDisplayText);
362  listWidgetItem->setTextColor(color);
363 
364  // Store some additional data for the plot curve on the list item
365  listWidgetItem->setData(Qt::UserRole + ScopeGadgetOptionsPage::UR_UAVOBJECT,
366  QVariant(uavObjectName));
367  listWidgetItem->setData(Qt::UserRole + ScopeGadgetOptionsPage::UR_UAVFIELD,
368  QVariant(uavFieldName));
369  listWidgetItem->setData(Qt::UserRole + ScopeGadgetOptionsPage::UR_SCALE, QVariant(scale));
370  listWidgetItem->setData(Qt::UserRole + ScopeGadgetOptionsPage::UR_COLOR, varColor);
371  listWidgetItem->setData(Qt::UserRole + ScopeGadgetOptionsPage::UR_MEAN, QVariant(mean));
372  listWidgetItem->setData(Qt::UserRole + ScopeGadgetOptionsPage::UR_MATHFUNCTION,
373  QVariant(mathFunction));
374 
375  // Select the row with the new name
376  options_page->lst2dCurves->setCurrentRow(itemIdx);
377  }
378 
379  // Select row 1st row in list
380  options_page->lst2dCurves->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
381 }
382 
388 {
389  scopeGadgetWidget->setMinimumSize(64, 64);
390  scopeGadgetWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
391 
392  scopeGadgetWidget->setCanvasBackground(QColor(64, 64, 64));
393 
394  // Add grid lines
395  scopeGadgetWidget->m_grid->enableX(true);
396  scopeGadgetWidget->m_grid->enableY(true);
397  scopeGadgetWidget->m_grid->enableXMin(false);
398  scopeGadgetWidget->m_grid->enableYMin(false);
399  scopeGadgetWidget->m_grid->setMajorPen(QPen(Qt::gray, 0, Qt::DashLine));
400  scopeGadgetWidget->m_grid->setMinorPen(QPen(Qt::lightGray, 0, Qt::DotLine));
401  scopeGadgetWidget->m_grid->setPen(QPen(Qt::darkGray, 1, Qt::DotLine));
402  scopeGadgetWidget->m_grid->attach(scopeGadgetWidget);
403 
404  // Add the legend
405  scopeGadgetWidget->addLegend();
406 
407  // Configure axes
408  configureAxes(scopeGadgetWidget);
409 }
410 
416 {
417  switch (scatterplot2dType) {
418  case TIMESERIES2D: {
419  // Configure axes
420  scopeGadgetWidget->setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw());
421  uint NOW = QDateTime::currentDateTime().toTime_t();
422  scopeGadgetWidget->setAxisScale(QwtPlot::xBottom, NOW - timeHorizon / 1000, NOW);
423  break;
424  }
425  case SERIES2D:
426  default:
427  scopeGadgetWidget->setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw());
428  scopeGadgetWidget->setAxisScale(QwtPlot::xBottom, 0, timeHorizon);
429  break;
430  }
431 
432  scopeGadgetWidget->setAxisAutoScale(QwtPlot::yLeft, true);
433  scopeGadgetWidget->setAxisLabelRotation(QwtPlot::xBottom, 0.0);
434  scopeGadgetWidget->setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
435  scopeGadgetWidget->axisWidget(QwtPlot::yRight)->setColorBarEnabled(false);
436  scopeGadgetWidget->enableAxis(QwtPlot::yRight, false);
437 
438  // Reduce the gap between the scope canvas and the axis scale
439  QwtScaleWidget *scaleWidget = scopeGadgetWidget->axisWidget(QwtPlot::xBottom);
440  scaleWidget->setMargin(0);
441 
442  // Reduce the axis font size
443  QFont fnt(scopeGadgetWidget->axisFont(QwtPlot::xBottom));
444  fnt.setPointSize(7);
445  scopeGadgetWidget->setAxisFont(QwtPlot::xBottom, fnt); // x-axis
446  scopeGadgetWidget->setAxisFont(QwtPlot::yLeft, fnt); // y-axis
447  scopeGadgetWidget->setAxisFont(QwtPlot::yRight, fnt); // y-axis
448 
449  /*
450  In situations, when there is a label at the most right position of the
451  scale, additional space is needed to display the overlapping part
452  of the label would be taken by reducing the width of scale and canvas.
453  To avoid this "jumping canvas" effect, we add a permanent margin.
454  We don't need to do the same for the left border, because there
455  is enough space for the overlapping label below the left scale.
456  */
457  /*
458  const int fmh = QFontMetrics(scaleWidget->font()).height();
459  scaleWidget->setMinBorderDist(0, fmh / 2);
460 
461  const int fmw = QFontMetrics(scaleWidget->font()).width(" 00:00:00 ");
462  const int fmw = QFontMetrics(scaleWidget->font()).width(" ");
463  scaleWidget->setMinBorderDist(0, fmw);
464  */
465 }
This class is used to render the time values on the horizontal axis for the ChronoPlot.
virtual ScopeConfig * cloneScope(ScopeConfig *Scatterplot2dScopeConfig)
Scatterplot2dScopeConfig::cloneScope Clones scope from existing GUI configuration.
The Scatterplot2dScopeConfig class The scatterplot scope configuration.
void connectUAVO(UAVDataObject *obj)
ScopeGadgetWidget::connectUAVO Connects UAVO update signal, but only if it hasn't yet been connected...
void setXWindowSize(double val)
Definition: plotdata.h:55
void setMathFunction(QString val)
Definition: plotdata.h:58
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
void setScalePower(int val)
Definition: plotdata.h:56
QString getUavoName()
Definition: plotdata.h:67
virtual void preparePlot(ScopeGadgetWidget *)
Scatterplot2dScopeConfig::preparePlot Prepares the Qwt plot colors and axes.
QString getUavoFieldName()
Definition: plotdata.h:68
void setScope(ScopeConfig *val)
for i
Definition: OPPlots.m:140
QVector< double > * getYData()
Definition: plotdata.h:77
void replaceScatterplotDataSource(QList< Plot2dCurveConfiguration * > scatterplotSourceConfigs)
Scatterplot2dScopeConfig::replaceScatterplotDataSource Replaces the list of scatterplot data sources...
Scatterplot2dType
The Scatterplot2dType enum Defines the different type of plots.
QString getUavoSubFieldName()
Definition: plotdata.h:69
Scatterplot2dScopeConfig()
Scatterplot2dScopeConfig::Scatterplot2dScopeConfig Default constructor.
void setMeanSamples(int val)
Definition: plotdata.h:57
virtual void saveConfiguration(QSettings *qSettings)
Scatterplot2dScopeConfig::saveConfiguration Saves configuration to XML file.
void addLegend()
ScopeGadgetWidget::addLegend Add legend to plot.
The TimeSeriesPlotData class The chrono plot has a variable sized buffer of data, where the data is f...
The SeriesPlotData class The sequential plot have a fixed size buffer of data. All the curves in one ...
QVector< double > * getXData()
Definition: plotdata.h:76
virtual void setGuiConfiguration(Ui::ScopeGadgetOptionsPage *options_page)
Scatterplot2dScopeConfig::setGuiConfigurationSet the GUI elements based on values from the XML settin...
void configureAxes(ScopeGadgetWidget *)
Scatterplot2dScopeConfig::configureAxes Configure the axes.
The ScopeConfig class The parent class for scope configuration classes data sources.
Definition: scopesconfig.h:56
int m_refreshInterval
Definition: scopesconfig.h:73
void insertDataSources(QString stringVal, PlotData *dataVal)
QString getUavObjectFieldUnits(QString uavObjectName, QString uavObjectFieldName)
Definition: scopesconfig.h:77
QMap< QString, PlotData * > getDataSources()
void startTimer(int)
ScopeGadgetWidget::startTimer Starts timer.
void setCurve(QwtPlotCurve *val)
bool getHaveSubFieldFlag()
Definition: plotdata.h:70
virtual void loadConfiguration(ScopeGadgetWidget *scopeGadgetWidget)
Scatterplot2dScopeConfig::loadConfiguration loads the plot configuration into the scope gadget widget...
UAVObject * getObject(const QString &name, quint32 instId=0)
The Scatterplot2dData class Base class that keeps the data for each curve in the plot.
QwtPlotGrid * m_grid