openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
asciiPlotter.hpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
28 #ifndef _ASCII_PLOTTER
29 #define _ASCII_PLOTTER
30 
31 #include<stdio.h>
32 #include<stdlib.h>
33 #include<math.h>
34 
35 #include<iostream>
36 #include<vector>
37 #include<string>
38 #include<algorithm>
39 
40 #include<assert.h>
41 
42 
43 
44 template<class V>
46 {
47  private:
48  const std::vector<V> & _xval;
49  const std::vector<V> & _yval;
50 
51  public:
52  piecewiseLinear_function(const std::vector<V> & xval, const std::vector<V> & yval): _xval(xval), _yval(yval)
53  {
54  assert(_xval.size() == _yval.size());
55  assert(_xval.size() > 1);
56  }
57 
58  bool operator()(const V x, V & y)
59  {
60  V xs = _xval[0], xe = _xval[1], ys = _yval[0], ye = _yval[1];
61 
62  if( (x < _xval[0]) || (x > _xval[_xval.size()-1]) )
63  return false;
64 
65  size_t size = _xval.size();
66  unsigned int i=1;
67  while(x > xe && i < size-1) {
68  xs = _xval[i], xe = _xval[i+1];
69  ys = _yval[i], ye = _yval[i+1];
70  i++;
71  }
72 
73  V fctr = (x - xs) / (xe - xs);
74  y = ys + (ye - ys)*fctr;
75 
76  return true;
77  }
78 };
79 
80 
85 {
86  private:
87  std::vector< std::vector<char> > _canvas;
88  unsigned int _rows;
89  unsigned int _cols;
90  double _x_min, _x_max, _x_div;
91  double _y_min, _y_max, _y_div;
92 
94  void reset()
95  {
96  for(unsigned int i=0; i<_rows; i++) {
97  _canvas[i].assign(_cols + 1, ' ');
98  _canvas[i][_cols] = '\0';
99  }
100  _x_min = -1;
101  _x_max = -1;
102  _x_div = -1;
103  _y_min = -1;
104  _y_max = -1;
105  _y_div = -1;
106  }
107 
109  template<class V>
110  void compute_xrange(const std::vector<V> & x)
111  {
112  _x_min = x[0], _x_max = x[x.size()-1];
113  _x_div = (_x_max - _x_min) / (_cols - 1);
114  }
116  template<class V>
117  void compute_yrange(const std::vector<V> & func)
118  {
119  _y_min = func[0], _y_max = func[0];
120  for(size_t i=0; i<func.size(); i++) {
121  if(_y_min > func[i]) _y_min = func[i];
122  if(_y_max < func[i]) _y_max = func[i];
123  }
124  _y_div = (_y_max - _y_min) / (_rows - 1);
125  }
126 
128  template<class V>
129  void draw_graph(const std::vector<V> & x, const std::vector<V> & y, char c)
130  {
131  piecewiseLinear_function<V> func(x,y);
132  size_t dpd = 10; // draws per division
133 
134  for(size_t i=0; i<_cols*dpd; i++) {
135  size_t xidx = i/dpd;
136  V xval = _x_min + float(i)/float(dpd)*_x_div;
137  V yval;
138  if(func(xval, yval))
139  {
140  unsigned int yidx = (yval - _y_min) / _y_div;
141  if(yidx < _rows)
142  _canvas[_rows-1 - yidx][xidx] = c;
143  }
144  }
145  }
146 
148  void print_topline()
149  {
150  printf(" ");
151  for(size_t i=0; i<_cols+2; i++) printf("-");
152  printf("\n");
153  }
155  void print_botline()
156  {
157  printf(" ");
158  for(size_t i=0; i<_cols+2; i++) printf("-");
159  printf("\n");
160 
161  unsigned int bsize = 8;
162  unsigned int nblocks = _cols / bsize;
163  printf(" ");
164  for(size_t i=0; i<=nblocks; i++) {
165  if(i%2 == 0) printf("%8.1lf", _x_min + i*bsize*_x_div);
166  else printf(" ");
167  }
168  printf("\n");
169  }
170 
171 
172  public:
175  _rows(0),
176  _cols(0),
177  _x_min(-1),
178  _x_max(-1),
179  _x_div(-1),
180  _y_min(-1),
181  _y_max(-1),
182  _y_div(-1)
183  {}
188  asciiPlotter(const unsigned int rows, const unsigned int cols) :
189  _rows(0),
190  _cols(0)
191  {
192  this->setSize(rows, cols);
193  }
194 
196  void setSize(const unsigned int rows, const unsigned int cols)
197  {
198  _rows = rows;
199  _cols = cols;
200 
201  _canvas.resize(_rows);
202  this->reset();
203  }
204 
212  template<class V>
213  void add_graph(const std::vector<V> & func, char c)
214  {
215  assert(_cols > 0 && _rows > 0);
216 
217  std::vector<V> x(func.size());
218  for(size_t i=0; i<func.size(); i++) x[i] = i;
219 
220  if(_x_div < 0) compute_xrange(x);
221  if(_y_div < 0) compute_yrange(func);
222 
223  draw_graph(x, func, c);
224  }
231  template<class V>
232  void add_graph(const std::vector<V> & x, const std::vector<V> & y, char c)
233  {
234  assert(_cols > 0 && _rows > 0);
235  assert(x.size() == y.size());
236 
237  if(_x_div < 0) compute_xrange(x);
238  if(_y_div < 0) compute_yrange(y);
239 
240  draw_graph(x, y, c);
241  }
242 
244  void print()
245  {
246  print_topline();
247  for(size_t i=0; i<_rows; i++) {
248  if( (i == 0) || (_rows-1-i)%4 == 0 )
249  printf("%+8.2lf |%s|\n", _y_max - i*_y_div, _canvas[i].data());
250  else
251  printf(" |%s|\n", _canvas[i].data());
252  }
253  print_botline();
254  }
255 
257  template<class V>
258  void set_xrange(const std::vector<V> & x)
259  {
260  this->compute_xrange(x);
261  }
263  template<class V>
264  void set_xrange(V min, V max)
265  {
266  _x_min = min;
267  _x_max = max;
268  _x_div = (_x_max - _x_min) / (_cols - 1);
269  }
270 
272  template<class V>
273  void set_yrange(const std::vector<V> & func)
274  {
275  this->compute_yrange(func);
276  }
278  template<class V>
279  void set_yrange(V min, V max)
280  {
281  _y_min = min;
282  _y_max = max;
283  _y_div = (_y_max - _y_min) / (_rows - 1);
284  }
285 };
286 
287 
294 template<class V>
296 {
297  private:
298  asciiPlotter _plotter;
299  std::vector<float> _xval, _yval;
300  size_t _num_int;
301 
302  V _min, _max;
303  double _avrg;
304 
305  void stats(const std::vector<V> & data)
306  {
307  _min = data[0], _max = data[0];
308  _avrg = 0.0;
309 
310  for(size_t i=0; i<data.size(); i++)
311  {
312  V c = data[i];
313  if(_min > c) _min = c;
314  if(_max < c) _max = c;
315  _avrg += c;
316  }
317  _avrg /= double(data.size());
318  }
319 
320  void generate_xy(const std::vector<V> & data)
321  {
322  this->stats(data);
323 
324  float delta = float(_max - _min) / float(_num_int);
325 
326  for(size_t i=0; i<_num_int+1; i++) {
327  _xval[i] = float(_min) + i*delta;
328  _yval[i] = 0.0f;
329  }
330 
331  for(size_t i=0; i < data.size(); i++) {
332  size_t idx = size_t((data[i] - _min) / delta);
333  if(idx < _num_int+1)
334  _yval[idx] += 1.0f;
335  }
336  for(size_t i=0; i<_num_int+1; i++) _yval[i] /= ((float)data.size());
337  }
338 
339  public:
340  histogramm_plotter(size_t num_int, size_t rows, size_t cols) :
341  _plotter(rows, cols), _xval(num_int+1), _yval(num_int+1), _num_int(num_int)
342  {}
343 
344  void plot(const std::vector<V> & data, std::string msg)
345  {
346  this->generate_xy(data);
347 
348  _plotter.set_xrange(_min, _max);
349  _plotter.set_yrange(_yval);
350  _plotter.add_graph(_xval, _yval, '*');
351 
352  std::cout << msg << std::endl << std::endl;
353  std::cout << "Average: " << _avrg << ", (min: " << _min << ", max: " << _max << ")" << std::endl;
354  std::cout << std::endl << " == Histogram == " << std::endl << std::endl;
355  _plotter.print();
356  }
357 };
358 
364 template<class VEC>
366 {
367  private:
368  std::vector< std::vector<char> > _canvas;
369  unsigned int _rows;
370  unsigned int _cols;
371 
372 
380  void draw_matrix(const VEC & cnt,
381  const VEC & col,
382  char s)
383  {
384  long int nrow = cnt.size();
385  long int ncol = *std::max_element(col.begin(), col.end()) + 1;
386  int xdiv = (ncol + _cols - 1) / _cols;
387  int ydiv = (nrow + _rows - 1) / _rows;
388 
389  for(size_t i=0, k=0; i<cnt.size(); i++)
390  for(long int j=0; j < cnt[i]; j++, k++) {
391  int ypos = i / ydiv;
392  int xpos = col[k] / xdiv;
393  _canvas[ypos][xpos] = s;
394  }
395  }
396 
397 
398  public:
400  matrixgraph_plotter() : _rows(0), _cols(0)
401  {}
402 
409  matrixgraph_plotter(const unsigned int rows, const unsigned int cols)
410  {
411  this->setSize(rows, cols);
412  }
413 
417  void reset()
418  {
419  for(unsigned int i=0; i<_rows; i++) {
420  _canvas[i].assign(_cols + 1, ' ');
421  _canvas[i][_cols] = '\0';
422  }
423  }
424 
431  void setSize(const unsigned int rows, const unsigned int cols)
432  {
433  _rows = rows;
434  _cols = cols;
435 
436  _canvas.resize(_rows);
437  this->reset();
438  }
439 
447  void print(const VEC & cnt,
448  const VEC & col,
449  char s)
450  {
451  draw_matrix(cnt, col, s);
452 
453  for(size_t i=0; i<_rows; i++) {
454  printf(" |%s|\n", _canvas[i].data());
455  }
456  }
457 };
458 
459 
460 
461 #endif
462 
void add_graph(const std::vector< V > &func, char c)
asciiPlotter(const unsigned int rows, const unsigned int cols)
void set_xrange(V min, V max)
set x range
void set_yrange(const std::vector< V > &func)
set y range according to min/max of the given function
void set_yrange(V min, V max)
set y range
void setSize(const unsigned int rows, const unsigned int cols)
set canvas size
void set_xrange(const std::vector< V > &x)
set x range according to min/max of the given vector
void add_graph(const std::vector< V > &x, const std::vector< V > &y, char c)
void print()
print the plot on stdout
asciiPlotter()
empty constructor
Class that generates a histogram for a data vector and prints it using asciiPlotter.
void plot(const std::vector< V > &data, std::string msg)
histogramm_plotter(size_t num_int, size_t rows, size_t cols)
Ascii matrix graph plotter.
void reset()
Clear the canvas.
matrixgraph_plotter()
empty constructor
void setSize(const unsigned int rows, const unsigned int cols)
Set new size and clear the canvas.
matrixgraph_plotter(const unsigned int rows, const unsigned int cols)
Constructor specifying the canvas size.
void print(const VEC &cnt, const VEC &col, char s)
Print a matrix graph to stdout.
piecewiseLinear_function(const std::vector< V > &xval, const std::vector< V > &yval)
bool operator()(const V x, V &y)
constexpr T min(T a, T b)
Definition: ion_type.h:33
constexpr T max(T a, T b)
Definition: ion_type.h:31