29 #include <QVBoxLayout> 40 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
42 _layout =
new QVBoxLayout(
this);
43 _layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
47 _plot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
48 _plot->setMinimumHeight(225);
69 connect(
_plot, SIGNAL(mouseDoubleClick(QMouseEvent*)),
this, SLOT(
rescaleAxes()));
72 _plot->setContextMenuPolicy(Qt::CustomContextMenu);
79 setMouseTracking(
true);
94 QFont legend_font = font();
95 legend_font.setPointSize(8);
100 border_pen.setColor(QColor(
"white"));
128 if (event->mimeData()->hasFormat(
"text/plain")) event->acceptProposedAction();
133 QString message =
event->mimeData()->text();
140 event->acceptProposedAction();
145 if (event->button() == Qt::LeftButton)
154 if (!(event->buttons() & Qt::LeftButton))
157 if (event->y() >= height() - 5)
160 setCursor(Qt::SizeVerCursor);
166 setCursor(Qt::ArrowCursor);
174 if (event->y() <=
_plot->minimumHeight() +
_layout->margin() + 20)
return;
180 QPoint window_coords = mapFrom(window(), QPoint(0, window()->height()));
181 if (event->y() < window_coords.y() - 3)
184 setFixedHeight(event->y());
190 setFixedHeight(height() + 2);
206 addSignal(signal_key, value_idx, *signal);
209 PRINT_WARNING(
"ScopeWidget::addSignal(): signal " << signal_key.toStdString() <<
" not found.");
234 switch (signal_data.
signal->getType())
256 QMessageBox::warning(
this, tr(
"Cannot plot Signal"),
"Signal type not supported yet.");
262 bool zero_order_hold,
bool replot)
271 QVector<double> time;
274 QVector<double> values;
276 for (
int t = 0; t < values_mat.cols(); ++t)
278 values.push_back(values_mat(value_idx, t));
283 graph->
setPen(QPen(color));
287 graph->
setData(time, values,
true);
332 QVector<double> time;
335 QVector<double> values;
337 for (
int t = 0; t < values_mat.cols(); ++t)
339 values.push_back(values_mat(data.
value_idx, t));
352 if (graph->
data()->isEmpty())
366 for (
int i = 0; i < active_signals.size(); ++i)
369 if (active_signals[i].value().plottable ==
nullptr)
379 QCPGraph* graph =
dynamic_cast<QCPGraph*
>(active_signals[i].value().plottable);
380 if (!graph)
continue;
382 if (active_signals[i].value().value_idx < measurement->getValues().size())
384 updateTimeSeriesGraph(active_signals[i].value(), measurement->getTime(), measurement->getValues()[active_signals[i].value().value_idx],
392 "Received values for plotting a time-series to scope, but the dimension is smaller than the values " 427 auto found_it = std::find_if(data.
ts_sequence->getSequence().rbegin(), data.
ts_sequence->getSequence().rend(),
429 if (found_it != data.
ts_sequence->getSequence().rend())
432 current_ts = *found_it;
439 PRINT_ERROR(
"ScopeWidget::updateTimeSeriesSequenceGraph(): time series sequence is empty.");
442 current_ts = data.
ts_sequence->getSequence().front();
461 if (indexed_values_set.
isEmpty())
return nullptr;
465 for (
const auto& item : indexed_values_set.
getData())
468 std::vector<double> data = item.second;
471 double minimum = *std::min_element(data.begin(), data.end());
472 double maximum = *std::max_element(data.begin(), data.end());
474 int num_quartile1 = data.size() / 4;
475 int num_quartile2 = data.size() / 2;
476 int num_quartile3 = num_quartile1 + num_quartile2;
478 std::nth_element(data.begin(), data.begin() + num_quartile1, data.end());
479 std::nth_element(data.begin() + num_quartile1 + 1, data.begin() + num_quartile2, data.end());
480 std::nth_element(data.begin() + num_quartile2 + 1, data.begin() + num_quartile3, data.end());
482 double lower_quartile = data[num_quartile1];
483 double median = data[num_quartile2];
484 double upper_quartile = data[num_quartile3];
486 box->
addData(item.first, minimum, lower_quartile, median, upper_quartile, maximum);
515 removed = (
int)iterators.size();
539 if (prev_task_id == task_id - 1)
581 QVector<QHash<QString, ScopeWidget::SignalData>::iterator> active_list;
594 found = (signal_key.compare(key) == 0);
601 found = (token_active.back().compare(token_source.back()) == 0);
606 PRINT_WARNING(
"ScopeWidget::findActiveSignal(): selected search type not implemented.");
609 if (found) active_list.push_back(it);
623 PRINT_WARNING_COND(tokens.size() > 2,
"QString::fromValueEnvodedKey: more than 2 tokens found...");
627 key = tokens.front();
628 if (tokens.size() > 1)
631 value_idx = tokens.back().toInt(&ok);
634 PRINT_ERROR(
"QString::fromValueEnvodedKey: cannot detect value index in " << value_encoded_key.toStdString());
643 PRINT_WARNING(
"QString::fromValueEnvodedKey: no value_idx found in " << value_encoded_key.toStdString() <<
". Setting value_idx to 0");
690 if (graph_item->
selectTest(point,
false) >= 0)
692 QAction* remove_action =
new QAction(tr(
"Remove signal"),
this);
693 connect(remove_action, &QAction::triggered, [
this, it]() {
697 menu.addAction(remove_action);
706 QAction* rescale_axes =
new QAction(tr(
"Rescale axes"),
this);
707 connect(rescale_axes, &QAction::triggered, [
this]() {
rescaleAxes(); });
708 menu.addAction(rescale_axes);
712 bool signal_options =
false;
716 signal_options =
true;
721 signal_options =
true;
724 if (signal_options) menu.addSeparator();
726 QAction* close_scope =
new QAction(tr(
"Close scope"),
this);
727 connect(close_scope, &QAction::triggered, [
this]() { deleteLater(); });
728 menu.addAction(close_scope);
732 menu.exec(
_plot->mapToGlobal(point));
742 if (it.value().plottable && it.value().plottable->selected())
759 if (!graph)
return false;
761 QVariant active = graph->property(
"active");
763 if (active.isValid() && active.toBool())
return true;
777 graph->setProperty(
"active", active);
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes) ...
#define PRINT_ERROR_NAMED(msg)
Signal for a sequence of time series objects.
static QString name2Key(const QString &name, int id)
Time Series (trajectory resp. sequence of values w.r.t. time)
void setName(const QString &name)
Q_SLOT void setSelectableParts(const SelectableParts &selectableParts)
void setRangeDrag(Qt::Orientations orientations)
#define PRINT_WARNING(msg)
Print msg-stream.
Queues the entire replot for the next event loop iteration. This way multiple redundant replots can b...
void setInteractions(const QCP::Interactions &interactions)
A matrix or vector expression mapping an existing array of data.
const double & getTimeFromStart() const
Get time from start (offset to all time stamps in time())
Columns are filled first, and a new element is wrapped to the next row if the column count would exce...
void setBrush(const QBrush &brush)
void setColumnStretchFactor(int column, double factor)
Represents the visual appearance of scatter points.
The axis backbone and tick marks.
constexpr const char SIGNAL_NAMESPACE_PREFIX_DELIMITER[]
Q_SLOT void replot(QCustomPlot::RefreshPriority refreshPriority=QCustomPlot::rpRefreshHint)
A plottable representing a single statistical box in a plot.
bool addElement(int row, int column, QCPLayoutElement *element)
SignalInterface::Ptr signal
int getValueDimension() const
Return dimension of the value vector.
0x004 The user can select multiple objects by holding the modifier set by QCustomPlot::setMultiSelect...
std::shared_ptr< const SignalHelper > ConstPtr
The central class of the library. This is the QWidget which displays the plot and interacts with the ...
static constexpr const int ALL_VALUES
ValuesMatConstMap getValuesMatrixView() const
Read access to the complete values matrix in Eigen matrix format [getValueDimension() x getTimeDimens...
line is drawn as steps where the step height is the value of the left data point
constexpr const char SIGNAL_NAMESPACE_SUFFIX_DELIMITER[]
A layout that arranges child elements in a grid.
Qt::Orientation orientation() const
The abstract base class for all objects that form the layout system.
bool isEmpty() const
Check if the underlying map is empty.
int plottableCount() const
void setPen(const QPen &pen)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const Q_DECL_OVERRIDE
0x010 Axes are selectable (or parts of them, see QCPAxis::setSelectableParts)
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const Q_DECL_OVERRIDE
#define PRINT_WARNING_COND(cond, msg)
Print msg-stream only if cond == true.
QCPGraph * addGraph(QCPAxis *keyAxis=0, QCPAxis *valueAxis=0)
0x008 Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable) ...
std::shared_ptr< const Measurement > ConstPtr
void setTextColor(const QColor &color)
void setIconSize(const QSize &size)
const std::vector< double > & getTime() const
Read access to the underlying time values [getTimeDimension() x 1].
A legend item representing a plottable with an icon and the plottable name.
void setAntialiasedFill(bool enabled)
void rescaleAxes(bool onlyEnlarge=false) const
static const QColor & getColor(int index)
SelectableParts selectedParts() const
void setLineStyle(LineStyle ls)
{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle) ...
void addData(const QVector< double > &keys, const QVector< double > &values, bool alreadySorted=false)
QCPPlottableLegendItem * itemWithPlottable(const QCPAbstractPlottable *plottable) const
void setRangeZoom(Qt::Orientations orientations)
Time Series signal (trajectory resp. sequence of values w.r.t. time)
void setData(QSharedPointer< QCPGraphDataContainer > data)
static bool key2Name(const QString &key, QString &name, int &id)
Q_SLOT void rescaleAxes(bool onlyVisiblePlottables=false)
void setFont(const QFont &font)
void setMargins(const QMargins &margins)
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom, QCPAxisRect::setRangeZoomAxes)
QCPLayoutGrid * plotLayout() const
QList< QCPGraph * > selectedGraphs() const
bool ok()
global method to check whether to proceed or cancel the current action
void setScatterStyle(const QCPScatterStyle &style)
void addData(const QVector< double > &keys, const QVector< double > &minimum, const QVector< double > &lowerQuartile, const QVector< double > &median, const QVector< double > &upperQuartile, const QVector< double > &maximum, bool alreadySorted=false)
A plottable representing a graph in a plot.
std::shared_ptr< TimeSeries > Ptr
const Map & getData() const
Read access to the underlying map object.
void setFillOrder(FillOrder order, bool rearrange=true)
The abstract base class for all data representing objects in a plot.
std::shared_ptr< const TimeSeries > ConstPtr
void setBorderPen(const QPen &pen)
0x002 Legend items individually (see selectedItems)
QCPAxisRect * axisRect(int index=0) const
Signal containing values indexed by an integer (int to double[] map)
QSharedPointer< QCPGraphDataContainer > data() const
void setRowStretchFactor(int row, double factor)
#define PRINT_ERROR(msg)
Print msg-stream as error msg.