plotdata.h
Go to the documentation of this file.
1 #ifndef PLOTDATA_RAW_H
2 #define PLOTDATA_RAW_H
3 
4 #include <vector>
5 #include <memory>
6 #include <string>
7 #include <map>
8 #include <mutex>
9 #include <deque>
10 #include "PlotJuggler/optional.hpp"
11 #include "PlotJuggler/any.hpp"
12 #include <QDebug>
13 #include <QColor>
14 #include <type_traits>
15 #include <cmath>
16 #include <cstdlib>
17 #include <unordered_map>
18 
19 namespace PJ {
20 
21 struct Range
22 {
23  double min;
24  double max;
25 };
26 
28 
29 
30 template <typename Value>
32 {
33 public:
34 
35  class Point
36  {
37  public:
38  double x;
40  Point(double _x, Value _y) : x(_x), y(_y)
41  {
42  }
43  Point() = default;
44  };
45 
46  enum
47  {
48  MAX_CAPACITY = 1024 * 1024,
49  ASYNC_BUFFER_CAPACITY = 1024
50  };
51 
52  typedef double TypeX;
53 
54  typedef Value TypeY;
55 
56  typedef typename std::deque<Point>::iterator Iterator;
57 
58  typedef typename std::deque<Point>::const_iterator ConstIterator;
59 
60  PlotDataBase(const std::string& name):
61  _color_hint(Qt::black),
62  _name(name),
63  _range_x_dirty(true),
64  _range_y_dirty(true)
65  {}
66 
67  PlotDataBase(const PlotDataBase& other) = delete;
68 
70  {
71  (*this) = std::move(other);
72  }
73 
74  void swapData(PlotDataBase& other)
75  {
76  std::swap(_points, other._points);
77  std::swap(_range_x, other._range_x);
78  std::swap(_range_y, other._range_y);
79  std::swap(_range_x_dirty, other._range_x_dirty);
80  std::swap(_range_y_dirty, other._range_y_dirty);
81  }
82 
83  PlotDataBase& operator=(const PlotDataBase& other) = delete;
84 
85  virtual ~PlotDataBase() = default;
86 
87  const std::string& name() const
88  {
89  return _name;
90  }
91 
92  virtual size_t size() const
93  {
94  return _points.size();
95  }
96 
97  const Point& at(size_t index) const
98  {
99  return _points[index];
100  }
101 
102  Point& at(size_t index)
103  {
104  return _points[index];
105  }
106 
107  const Point& operator[](size_t index) const
108  {
109  return at(index);
110  }
111 
112  Point& operator[](size_t index)
113  {
114  return at(index);
115  }
116 
117  void clear()
118  {
119  _points.clear();
120  _range_x_dirty = true;
121  _range_y_dirty = true;
122  }
123 
124  QColor getColorHint() const
125  {
126  return _color_hint;
127  }
128 
129  void setColorHint(QColor color)
130  {
131  _color_hint = color;
132  }
133 
134  const Point& front() const
135  {
136  return _points.front();
137  }
138 
139  const Point& back() const
140  {
141  return _points.back();
142  }
143 
144  ConstIterator begin() const
145  {
146  return _points.begin();
147  }
148 
149  ConstIterator end() const
150  {
151  return _points.end();
152  }
153 
154  Iterator begin()
155  {
156  return _points.begin();
157  }
158 
159  Iterator end()
160  {
161  return _points.end();
162  }
163 
164  virtual RangeOpt rangeX() const
165  {
166  if( _points.empty() ){
167  return nonstd::nullopt;
168  }
169  if( _range_x_dirty )
170  {
171  _range_x.min = front().x;
172  _range_x.max = _range_x.min;
173  for(const auto& p: _points)
174  {
175  _range_x.min = std::min(_range_x.min, p.x);
176  _range_x.max = std::max(_range_x.max, p.x);
177  }
178  _range_x_dirty = false;
179  }
180  return _range_x;
181  }
182 
183  RangeOpt rangeY() const
184  {
185  if( _points.empty() ){
186  return nonstd::nullopt;
187  }
188  if( _range_y_dirty )
189  {
190  _range_y.min = front().y;
191  _range_y.max = _range_y.min;
192  for(const auto& p: _points)
193  {
194  _range_y.min = std::min(_range_y.min, p.y);
195  _range_y.max = std::max(_range_y.max, p.y);
196  }
197  _range_y_dirty = false;
198  }
199  return _range_y;
200  }
201 
202  void pushBack(const Point &p)
203  {
204  auto temp = p;
205  pushBack(std::move(temp));
206  }
207 
208  virtual void pushBack(Point&& p)
209  {
210  if( _points.empty() )
211  {
212  _range_x_dirty = false;
213  _range_x.min = p.x;
214  _range_x.max = p.x;
215 
216  _range_y.min = p.y;
217  _range_y.max = p.y;
218  }
219  if( !_range_x_dirty )
220  {
221  if( p.x > _range_x.max ){
222  _range_x.max = p.x;
223  }
224  else if( p.x < _range_x.min ){
225  _range_x.min = p.x;
226  }
227  else{
228  _range_x_dirty = true;
229  }
230  }
231 
232  if( !_range_y_dirty )
233  {
234  if( p.y > _range_y.max ){
235  _range_y.max = p.y;
236  }
237  else if( p.y < _range_y.min ){
238  _range_y.min = p.y;
239  }
240  else{
241  _range_y_dirty = true;
242  }
243  }
244  _points.emplace_back(p);
245  }
246 
247  virtual void popFront()
248  {
249  const auto& p = _points.front();
250 
251  if( !_range_x_dirty && (p.x == _range_x.max || p.x == _range_x.min) )
252  {
253  _range_x_dirty = true;
254  }
255  if( !_range_y_dirty && (p.y == _range_y.max || p.y == _range_y.min) )
256  {
257  _range_y_dirty = true;
258  }
259  _points.pop_front();
260  }
261 
262 protected:
263  std::string _name;
264  QColor _color_hint;
265 
266  // when everything is mutable, nothing is const :(
267  std::deque<Point> _points;
268  mutable Range _range_x;
269  mutable Range _range_y;
270  mutable bool _range_x_dirty;
271  mutable bool _range_y_dirty;
272 };
273 
274 
275 //-----------------------------------
276 
277 template <typename Value>
278 class TimeseriesBase: public PlotDataBase<Value>
279 {
280 protected:
281  double _max_range_x;
282 
288 
289 public:
291 
292  TimeseriesBase(const std::string& name):
293  PlotDataBase<Value>(name),
294  _max_range_x( std::numeric_limits<double>::max() )
295  {
296  _range_x_dirty = false;
297  }
298 
299  void setMaximumRangeX(double max_range)
300  {
301  _max_range_x = max_range;
302  trimRange();
303  }
304 
305  double maximumRangeX() const
306  {
307  return _max_range_x;
308  }
309 
310  int getIndexFromX(double x) const;
311 
312  nonstd::optional<Value> getYfromX(double x) const;
313 
314  void popFront() override
315  {
316  const auto& p = _points.front();
317 
318  if( !_range_y_dirty && (p.y == _range_y.max || p.y == _range_y.min) )
319  {
320  _range_y_dirty = true;
321  }
322  _points.pop_front();
323 
324  if( !_points.empty() )
325  {
326  _range_x.min = _points.front().x;
327  }
328  }
329 
330  void pushBack(const Point &p)
331  {
332  auto temp = p;
333  pushBack(std::move(temp));
334  }
335 
336  void pushBack(Point&& p) override
337  {
338  if (std::isinf(p.y) || std::isnan(p.y))
339  {
340  return; // skip
341  }
342  bool need_sorting = false;
343 
344  if( _points.empty() )
345  {
346  _range_x_dirty = false;
347  _range_x.min = p.x;
348  _range_x.max = p.x;
349 
350  _range_y.min = p.y;
351  _range_y.max = p.y;
352  }
353  else{
354  if( p.x < this->back().x ){
355  need_sorting = true;
356  }
357  }
358 
359  if( need_sorting ) {
360  auto it = std::upper_bound(_points.begin(), _points.end(), p,
361  [](const Point& a, const Point& b) { return a.x < b.x; });
362 
363  _points.insert(it, p);
364  }
365  else{
366  _points.emplace_back(p);
367  }
368 
369  _range_x.max = p.x;
370 
371  if( !_range_y_dirty )
372  {
373  if( p.y > _range_y.max ){
374  _range_y.max = p.y;
375  }
376  else if( p.y < _range_y.min ){
377  _range_y.min = p.y;
378  }
379  else{
380  _range_y_dirty = true;
381  }
382  }
383 
384  trimRange();
385  }
386 
387  RangeOpt rangeX() const override
388  {
389  if( _points.empty() ){
390  return nonstd::nullopt;
391  }
392  if( _range_x_dirty )
393  {
394  _range_x.min = _points.front().x;
395  _range_x.max = _points.back().x;
396  _range_x_dirty = false;
397  }
398  return _range_x;
399  }
400 
401 private:
402  void trimRange()
403  {
404  while (_points.size() > 2 && (_points.back().x - _points.front().x) > _max_range_x)
405  {
406  this->popFront();
407  }
408  }
409 
410 };
411 
412 // ----------- template specializations ----------
413 template <>
415 {
416  _points.pop_front();
417 
418  if( !_points.empty() )
419  {
420  _range_x.min = _points.front().x;
421  }
422 }
423 
424 template <>
426 {
427  const auto& p = _points.front();
428  if( !_range_x_dirty && (p.x == _range_x.max || p.x == _range_x.min) )
429  {
430  _range_x_dirty = true;
431  }
432  _points.pop_front();
433 }
434 
435 template <>
436 inline RangeOpt PlotDataBase<nonstd::any>::rangeY() const
437 {
438  return nonstd::nullopt;
439 }
440 
441 template <>
443 {
444  if( _points.empty() )
445  {
446  _range_x_dirty = false;
447  _range_x.min = p.x;
448  _range_x.max = p.x;
449  }
450  if( !_range_x_dirty )
451  {
452  if( p.x > _range_x.max ){
453  _range_x.max = p.x;
454  }
455  else if( p.x < _range_x.min ){
456  _range_x.min = p.x;
457  }
458  else{
459  _range_x_dirty = true;
460  }
461  }
462  _points.emplace_back(p);
463 }
464 
465 template <>
467 {
468  if( _points.empty() )
469  {
470  _range_x_dirty = false;
471  _range_x.min = p.x;
472  _range_x.max = p.x;
473  }
474  else {
475  if( p.x < this->back().x ){
476  _range_x_dirty = true;
477  }
478  if( !_range_x_dirty ){
479  _range_x.max = p.x;
480  }
481  }
482 
483  _points.emplace_back(p);
484  trimRange();
485 }
486 
487 
488 
489 //-----------------------------------
492 
494 {
495  std::unordered_map<std::string, PlotData> numeric;
496  std::unordered_map<std::string, PlotDataAny> user_defined;
497 
498  std::unordered_map<std::string, PlotData>::iterator addNumeric(const std::string& name)
499  {
500  return numeric.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(name)).first;
501  }
502 
503  std::unordered_map<std::string, PlotDataAny>::iterator addUserDefined(const std::string& name)
504  {
505  return user_defined.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(name))
506  .first;
507  }
508 
509 };
510 
511 //-----------------------------------
512 template <typename Value>
513 inline void AddPrefixToPlotData(const std::string& prefix,
514  std::unordered_map<std::string, Value>& data)
515 {
516  if (prefix.empty()){
517  return;
518  }
519 
520  std::unordered_map<std::string, Value> temp;
521 
522  for (auto& it : data)
523  {
524  std::string key;
525  key.reserve(prefix.size() + 2 + it.first.size());
526  if (it.first.front() == '/')
527  {
528  key = prefix + it.first;
529  }
530  else
531  {
532  key = prefix + "/" + it.first;
533  }
534 
535  auto new_plot =
536  temp.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(key)).first;
537 
538  new_plot->second.swapData(it.second);
539  }
540  std::swap(data, temp);
541 }
542 
543 
544 template <typename Value>
545 inline int TimeseriesBase<Value>::getIndexFromX(double x) const
546 {
547  if (_points.size() == 0)
548  {
549  return -1;
550  }
551  auto lower = std::lower_bound(_points.begin(), _points.end(), Point(x, 0),
552  [](const Point& a, const Point& b) { return a.x < b.x; });
553  auto index = std::distance(_points.begin(), lower);
554 
555  if (index >= _points.size())
556  {
557  return _points.size() - 1;
558  }
559  if (index < 0)
560  {
561  return 0;
562  }
563 
564  if (index > 0)
565  {
566  if (std::abs(_points[index - 1].x - x) < std::abs(_points[index].x - x))
567  {
568  return index - 1;
569  }
570  else
571  {
572  return index;
573  }
574  }
575  return index;
576 }
577 
578 template <typename Value>
580 {
581  int index = getIndexFromX(x);
582  if (index == -1)
583  {
584  return {};
585  }
586  return _points.at(index).y;
587 }
588 
589 } // end namespace
590 
591 #endif // PLOTDATA_H
const Point & back() const
Definition: plotdata.h:139
RangeOpt rangeY() const
Definition: plotdata.h:183
RangeOpt rangeX() const override
Definition: plotdata.h:387
const Point & at(size_t index) const
Definition: plotdata.h:97
double max
Definition: plotdata.h:24
const Point & front() const
Definition: plotdata.h:134
TimeseriesBase(const std::string &name)
Definition: plotdata.h:292
nonstd::optional< Range > RangeOpt
Definition: plotdata.h:27
std::string _name
Definition: plotdata.h:263
std::unordered_map< std::string, PlotData > numeric
Definition: plotdata.h:495
virtual void popFront()
Definition: plotdata.h:247
std::deque< Point > _points
Definition: plotdata.h:267
Definition: json.hpp:4042
void swapData(PlotDataBase &other)
Definition: plotdata.h:74
void setColorHint(QColor color)
Definition: plotdata.h:129
std::deque< Point >::iterator Iterator
Definition: plotdata.h:56
ConstIterator end() const
Definition: plotdata.h:149
Definition: lobject.h:47
std::unordered_map< std::string, PlotDataAny >::iterator addUserDefined(const std::string &name)
Definition: plotdata.h:503
Point(double _x, Value _y)
Definition: plotdata.h:40
double maximumRangeX() const
Definition: plotdata.h:305
ConstIterator begin() const
Definition: plotdata.h:144
QColor getColorHint() const
Definition: plotdata.h:124
PlotDataBase(const std::string &name)
Definition: plotdata.h:60
#define min(A, B)
Definition: Log.c:64
#define max(A, B)
Definition: Socket.h:88
nonstd::optional< Value > getYfromX(double x) const
Definition: plotdata.h:579
Point & at(size_t index)
Definition: plotdata.h:102
int getIndexFromX(double x) const
Definition: plotdata.h:545
void pushBack(Point &&p) override
Definition: plotdata.h:336
void setMaximumRangeX(double max_range)
Definition: plotdata.h:299
Point & operator[](size_t index)
Definition: plotdata.h:112
virtual size_t size() const
Definition: plotdata.h:92
const Point & operator[](size_t index) const
Definition: plotdata.h:107
const T & move(const T &v)
Definition: backward.hpp:394
QColor _color_hint
Definition: plotdata.h:264
Iterator begin()
Definition: plotdata.h:154
bool _range_y_dirty
Definition: plotdata.h:271
const std::string & name() const
Definition: plotdata.h:87
std::unordered_map< std::string, PlotDataAny > user_defined
Definition: plotdata.h:496
void pushBack(const Point &p)
Definition: plotdata.h:330
virtual RangeOpt rangeX() const
Definition: plotdata.h:164
bool _range_x_dirty
Definition: plotdata.h:270
double min
Definition: plotdata.h:23
PlotDataBase(PlotDataBase &&other)
Definition: plotdata.h:69
void AddPrefixToPlotData(const std::string &prefix, std::unordered_map< std::string, Value > &data)
Definition: plotdata.h:513
std::unordered_map< std::string, PlotData >::iterator addNumeric(const std::string &name)
Definition: plotdata.h:498
double _max_range_x
Definition: plotdata.h:281
void popFront() override
Definition: plotdata.h:314
double TypeX
Definition: plotdata.h:52
char lower
Definition: utf-8.c:49
void pushBack(const Point &p)
Definition: plotdata.h:202
dictionary data
Definition: mqtt_test.py:22
std::deque< Point >::const_iterator ConstIterator
Definition: plotdata.h:58
virtual void pushBack(Point &&p)
Definition: plotdata.h:208
const nullopt_t nullopt((nullopt_t::init()))
bool isnan(T)
Definition: chrono.h:659
Iterator end()
Definition: plotdata.h:159
typename PlotDataBase< Value >::Point Point
Definition: plotdata.h:290


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10