OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
GoogleChart.hpp
1 /*
2  * GoogleChart.hpp
3  *
4  * Created on: Jan 9, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_
9 #define OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_
10 
11 #include <fstream>
12 #include "Vector/map_vector.hpp"
13 #include <cmath>
14 
15 #define GGRAPH_COLUMS 1
16 #define GGRAPH_POINTS 2
17 
18 #define GC_ZOOM std::string("explorer: {actions: ['dragToZoom', 'rightClickToReset'],axis: 'horizontal,vertical',keepInBounds: true, maxZoomIn: 128.0}")
19 #define GC_X_LOG std::string("hAxis: { logScale: true }")
20 #define GC_Y_LOG std::string("vAxis: { logScale: true }")
21 
25 struct GCoptions
26 {
28  std::string title;
30  std::string yAxis;
32  std::string xAxis;
33 
38  std::string stype;
39 
43  std::string stypeext;
44 
46  size_t width=900;
47 
49  size_t heigh=500;
50 
53  bool isStacked = false;
54 
56  size_t lineWidth = 4;
57 
60  std::string intervalsext;
61 
64  std::string intervalext;
65 
67  std::string more;
68 
70  std::string curveType = "function";
71 
73  bool barWD = false;
74 
82  GCoptions & operator=(const GCoptions & opt)
83  {
84  title = opt.title;
85  yAxis = opt.yAxis;
86  xAxis = opt.xAxis;
87  stype = opt.stype;
88  stypeext = opt.stypeext;
89  width=opt.width;
90  heigh=opt.heigh;
91 
92  lineWidth = opt.lineWidth;
94  more = opt.more;
95 
96  return *this;
97  }
98 };
99 
103 struct GGraph
104 {
106  size_t type;
107 
109  std::string data;
110 
112  std::string option;
113 
115  std::string view;
116 
119 };
120 
122 
123 const std::string begin_data ="<html>\n\
124  <head>\n\
125  <script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>\n\
126  <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\"></script>\n\
127  <script type=\"text/javascript\">\n\
128  google.charts.load('current', {'packages':['corechart']});\n\
129  google.charts.setOnLoadCallback(drawVisualization);\n\
130 \n\
131 function exportToSVG(i)\n\
132 {\n\
133 var e = document.getElementById('chart_div'+i);\n\
134 var svg = e.getElementsByTagName('svg')[0].parentNode.innerHTML;\n\
135 var pos = svg.lastIndexOf(\"</svg>\");\n\
136 pos += 6;\n\
137 svg = svg.substring(0,4) + \" xmlns='http://www.w3.org/2000/svg' xmlns:xlink= 'http://www.w3.org/1999/xlink' \" + svg.substring(4,pos);\n\
138 svgData = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);\n\
139 $(this).attr({'href': svgData,'target': '_blank'});\n\
140 }\n\
141 \n\
142  function drawVisualization() {\n";
143 
144 const std::string end_data="]);\n\n";
145 
146 const std::string begin_div = "}</script>\n\
147 </head>\n\
148 <body>\n";
149 
150 const std::string div_end = "</body>\n\
151 </html>\n";
152 
153 const std::string saving_javascript = "function save(i)\n\
154  var e = document.getElementById('chart_')\n\
155  e.getElementsByTagName('svg')[0].parentNode.innerHTML";
156 
157 template<typename T>
158 struct check_nan
159 {
160  static bool check(const T & n)
161  {
162  return false;
163  }
164 };
165 
166 template<>
167 struct check_nan<float>
168 {
169  static bool check(const float & n)
170  {
171  return std::isnan(n);
172  }
173 };
174 
175 template<>
176 struct check_nan<double>
177 {
178  static bool check(const double & n)
179  {
180  return std::isnan(n);
181  }
182 };
183 
185 
216 {
217  template<typename arg_0, typename ... args>
219  {
220  typedef typename arg_0::value_type type;
221  };
222 
225 
228 
230  bool holes = false;
231 
239  template<typename X, typename ... Xs>
240  void recursive_sort(X & x,X & y,Xs& ... xy)
241  {
242  struct srt_xy
243  {
244  typename X::value_type x;
245  unsigned int id;
246 
247  bool operator<(const srt_xy & tmp) const
248  {
249  return x < tmp.x;
250  }
251  };
252 
254  X y_tmp;
255 
256  reord.resize(x.size());
257  y_tmp.resize(x.size());
258 
259  for (size_t i = 0 ; i < x.size() ; i++)
260  {
261  reord.get(i).x = x.get(i);
262  reord.get(i).id = i;
263  }
264 
265  reord.sort();
266 
267  // reorder x and y
268 
269  for (size_t i = 0 ; i < x.size() ; i++)
270  {
271  x.get(i) = reord.get(i).x;
272  y_tmp.get(i) = y.get(reord.get(i).id);
273  }
274 
275  y_tmp.swap(y);
276 
277  // sort x
278 
279  recursive_sort(xy ...);
280  }
281 
284  {}
285 
294  template<typename X, typename ... Xs>
295  bool isNext(size_t * counters,X & x,X & y,Xs& ... xy)
296  {
297  if (counters[0] < x.size())
298  {
299  return true;
300  }
301  return isNext(&counters[1],xy ...);
302  }
303 
309  bool isNext(size_t * counters)
310  {
311  return false;
312  }
313 
314 
323  template<typename T, typename X, typename ... Xs>
324  T get_low(size_t * counters,X & x,X & y,Xs& ... xy)
325  {
326  if (sizeof...(Xs) != 0)
327  {
328  T low1;
329  if (counters[0] >= x.size())
330  {low1 = std::numeric_limits<typename X::value_type>::infinity();}
331  else
332  {low1 = x.get(counters[0]);}
333 
334  T low2 = get_low<T>(&counters[1],xy ...);
335  return (low1 < low2)?low1:low2;
336  }
337 
338  if (counters[0] >= x.size())
339  {return std::numeric_limits<typename X::value_type>::infinity();}
340  return x.get(counters[0]);
341  }
342 
348  template<typename T>
349  T get_low(size_t * counters)
350  {
351  return 0.0;
352  }
353 
361  template<typename X, typename ... Xs>
362  void get_point(typename X::value_type low,
363  typename X::value_type * point,
364  size_t * counters,
365  X & x,
366  X & y,
367  Xs& ... xy)
368  {
369  if (counters[0] < x.size() && low == x.get(counters[0]))
370  {
371  point[0] = y.get(counters[0]);
372  counters[0]++;
373  }
374  else
375  {
376  point[0] = std::numeric_limits<typename X::value_type>::quiet_NaN();
377  }
378 
379  get_point(low,&point[1],&counters[1],xy...);
380  }
381 
389  template<typename T>
390  void get_point(T low,
391  T * point,
392  size_t * counters)
393  {
394  return;
395  }
396 
404  template<typename ... Xs>
405  bool get_v(typename get_value_type<Xs...>::type & x,
406  typename get_value_type<Xs...>::type * point,
407  size_t * counters,
408  Xs& ... xy)
409  {
410  // if exist the next element
411  if (isNext(counters,xy...) == false)
412  {return false;}
413 
414  // get lowest x
415  typename get_value_type<Xs...>::type low = get_low<typename get_value_type<Xs...>::type>(counters,xy...);
416 
417  x = low;
418 
419  get_point(low,point,counters,xy...);
420 
421  return true;
422  }
423 
438  template<typename X, typename Y> std::string get_points_plot_data(const openfpm::vector<X> & x, const openfpm::vector<Y> & y, const openfpm::vector<std::string> & yn, const GCoptions & opt, size_t i)
439  {
440  std::stringstream data;
441 
442  size_t interval = 0;
443 
444  // we require that the number of x elements are the same as y elements
445 
446  if (x.size() != y.size())
447  {std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector x and the vector y must have the same number of elements " << x.size() << "!=" << y.size() << "\n";}
448 
449  // Google chart visualization
450  data << "var data" << i << " = new google.visualization.DataTable();\n";
451  if (std::is_same<X,typename std::string>::value == true)
452  data << "data" << i << ".addColumn(" << "'string'" << "," << "'" << opt.xAxis <<"');\n";
453  else
454  data << "data" << i << ".addColumn(" << "'number'" << "," << "'" << opt.xAxis <<"');\n";
455 
456  for (size_t j = 0 ; j < y.last().size() ; j++)
457  {
458  if (yn.get(j) == std::string("interval"))
459  {
460  data << "data" << i << ".addColumn({id:'i" << interval/2 << "', type:'number', role:'interval'});\n";
461  interval++;
462  }
463  else
464  data << "data" << i << ".addColumn(" << "'number'" << "," << "'" << yn.get(j) <<"');\n";
465  }
466 
467  data << "data" << i << ".addRows([\n";
468  for (size_t i = 0 ; i < y.size() && x.size() ; i++)
469  {
470 
471  for (size_t j = 0 ; j < y.get(i).size()+1 ; j++)
472  {
473  // the first is x
474  if (j == 0)
475  {
476  if (std::is_same<X,typename std::string>::value == true)
477  data << "['" << x.get(i) << "'";
478  else
479  data << "[" << x.get(i);
480  }
481  else
482  {
483  if (check_nan<typename Y::value_type>::check(y.get(i).get(j-1)) == false)
484  {
485  data << "," << y.get(i).get(j-1);
486  }
487  else
488  {
489  holes = true;
490  data << "," << "null";
491  }
492  }
493  }
494  data << "],\n";
495  }
496 
497  return data.str();
498  }
499 
507  std::string get_view_bar_option(const GCoptions & opt, size_t n_col)
508  {
509  if (opt.barWD == false)
510  return std::string();
511 
512  std::stringstream str;
513 
514  str << "[0" << std::endl;
515 
516  for (size_t i = 1 ; i < n_col ; i++)
517  {
518  str << "," << i << ",{ calc: \"stringify\"," << std::endl;
519  str << "sourceColumn: " << i << "," << std::endl;
520  str << "type: \"string\"," << std::endl;
521  str << "role: \"annotation\" }"<< std::endl;
522  }
523 
524  str << "]" << std::endl;
525 
526  return str.str();
527  }
528 
529  std::string get_colums_bar_option(const GCoptions & opt)
530  {
531  std::stringstream str;
532  str << "title : '" << opt.title << "'";
533  str << ",\nvAxis: {title: '" << opt.yAxis << "'}";
534  str << ",\nhAxis: {title: '" << opt.xAxis << "'}";
535  str << ",\nseriesType: '" << opt.stype << "'";
536  if (opt.stypeext.size() != 0)
537  str << ",\nseries: " << opt.stypeext;
538  if (opt.more.size() != 0)
539  str << ",\n" <<opt.more;
540 
541  return str.str();
542  }
543 
544  std::string get_points_plot_option(const GCoptions & opt)
545  {
546  std::stringstream str;
547  str << "title : '" << opt.title << "'";
548  str << ",\nvAxis: {title: '" << opt.yAxis << "'}";
549  str << ",\nhAxis: {title: '" << opt.xAxis << "'}";
550  str << ",\ncurveType: '"<< opt.curveType << "'";
551 
552  str << ",\nlineWidth: " << opt.lineWidth;
553  if (opt.intervalsext.size() != 0)
554  str << ",\nintervals: " << opt.intervalsext;
555  else
556  str << ",\nintervals: " << "{ 'style':'area' }";
557 
558  if (opt.intervalext.size() != 0)
559  str << ",\ninterval: " << opt.intervalext << "\n";
560 
561  if (opt.more.size() != 0)
562  str << ",\n" << opt.more;
563 
564  return str.str();
565  }
566 
574  void addData(std::ofstream & of, size_t i, const std::string & data)
575  {
576 
577  of << data;
578  of << "]);\n";
579  }
580 
588  void addOption(std::ofstream & of, size_t i, const std::string & opt)
589  {
590  of << "var options";
591  of << i;
592  of << "= {\n";
593  if (holes == true)
594  {of << "interpolateNulls : true,\n";}
595  of << opt;
596  of << "};\n";
597  }
598 
606  void addView(std::ofstream & of, size_t i, std::string view)
607  {
608  if (view.size() == 0)
609  return;
610 
611  of << "var view" << i << " = new google.visualization.DataView(data" << i << ");" << std::endl;
612  of << "view"<< i << ".setColumns(";
613  of << view << ");" << std::endl;
614  }
615 
623  void addDrawDiv(std::ofstream & of, size_t i, bool draw_view)
624  {
625  of << "$(\"#export_svg" << i << "\").on(\"click\", function (event) {exportToSVG.apply(this,[" << i << "]);});\n";
626  of << "var chart = new google.visualization.ComboChart(document.getElementById('chart_div";
627  of << i;
628  of << "'));" << std::endl;
629  if (draw_view == true)
630  {
631  of << "chart.draw(data";
632  of << i;
633  }
634  else
635  {
636  of << "chart.draw(view";
637  of << i;
638  }
639  of << ", options";
640  of << i;
641  of << ");\n";
642  }
643 
651  void addDiv(std::ofstream & of, size_t i, const GCoptions & gc)
652  {
653  of << "<a href=\"#\" download=\"graph1.svg\" id=\"export_svg" << i << "\"><button>Export data into svg</button></a>";
654  of << "<div id=\"chart_div";
655  of << i;
656  of << "\" style=\"width: ";
657  of << gc.width;
658  of << "px; height: ";
659  of << gc.heigh;
660  of << "px;\"></div>\n";
661  }
662 
663 public:
664 
665  GoogleChart()
666  {
667  injectHTML.add();
668  }
669 
676  template<typename Y> void AddHistGraph(openfpm::vector<Y> & y)
677  {
679  x.resize(y.size());
680 
681  AddHistGraph<std::string,Y>(x,y);
682  }
683 
692  template<typename X, typename Y> void AddHistGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y)
693  {
694  GCoptions opt;
695 
697 
698  if (y.size() != 0)
699  yn.resize(y.get(0).size());
700 
701  AddHistGraph<X,Y,std::string>(x,y,yn,opt);
702  }
703 
714  template<typename X, typename Y, typename Yn> void AddHistGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y, openfpm::vector<Yn> & yn)
715  {
716  GCoptions opt;
717 
718  AddHistGraph(x,y,yn,opt);
719  }
720 
733  template<typename X, typename Y, typename Yn> void AddHistGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y, openfpm::vector<Yn> & yn , const GCoptions & opt)
734  {
735  set_of_graphs.add();
736  injectHTML.add();
737 
738  // Check that all the internal vector has the same number of elements
739 
740  if (y.size() != 0)
741  {
742  size_t sz = y.get(0).size();
743  for (size_t i = 0; i < y.size() ; i++)
744  {
745  if (y.get(i).size() != sz)
746  std::cerr << __FILE__ << ":" << __LINE__ << " error all the elements in the y vector must have the same numbers, element " << i << ": " << y.get(i).size() << " " << " mismatch the numbers of elements at 0: " << sz << "/n";
747  }
748  }
749 
750  set_of_graphs.last().type = GGRAPH_COLUMS;
751  set_of_graphs.last().data = get_points_plot_data(x,y,yn,opt,set_of_graphs.size()-1);
752  set_of_graphs.last().option = get_colums_bar_option(opt);
753  set_of_graphs.last().view = get_view_bar_option(opt,y.get(0).size());
754  set_of_graphs.last().opt = opt;
755  }
756 
757 
767  template<typename ... X> void AddLines(const openfpm::vector<std::string> & yn,
768  const GCoptions & opt,
769  X ... xy)
770  {
771  // first we sort the vectors
772  recursive_sort(xy ... );
773 
774  size_t counters[sizeof...(X)];
775  memset(&counters,0,sizeof(counters));
776 
777  typename get_value_type<X...>::type point[sizeof...(X)];
778  typename get_value_type<X...>::type xe;
779 
780  openfpm::vector<typename get_value_type<X...>::type> x;
781 
782  openfpm::vector<openfpm::vector<typename get_value_type<X...>::type>> y;
783 
784 
785  while (get_v(xe,point,counters,xy...))
786  {
787  y.add();
788  x.add(xe);
789 
790  for (size_t i = 0 ; i < sizeof...(X)/2 ; i++)
791  {
792  y.last().add(point[i]);
793  }
794  }
795 
796  AddLinesGraph(x,y,yn,opt);
797  }
798 
819  template<typename X, typename Y> void AddLinesGraphT(openfpm::vector<X> & x, openfpm::vector<Y> & y , const GCoptions & opt)
820  {
822 
823  if (y.size() == 0)
824  {
825  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled" << std::endl;
826  return;
827  }
828 
829  for (size_t i = 0 ; i < y.last().size() ; i++)
830  yn.add(std::string("line") + std::to_string(i));
831 
832  if (y.size() == 0)
833  return;
834 
835  // number of points
836  size_t np = y.last().size();
837 
838  for (size_t j = 0 ; j < y.size() ; j++)
839  {
840  if (y.get(j).size() != np)
841  std::cerr << __FILE__ << ":" << __LINE__ << " Error all the graph must have the same number of points " << np << "!=" << y.get(j).size() << std::endl;
842  }
843 
845 
846 
847  // swap the vector
848  // Each vector is a graph
849  // It is different from the other call where each vector
850  // has multiple value for the same point
851  for (size_t i = 0 ; i < np ; i++)
852  {
853  swap.add();
854  for (size_t j = 0 ; j < y.size() ; j++)
855  {
856  swap.last().add(y.get(j).get(i));
857  }
858  }
859 
860  AddLinesGraph(x,swap,yn,opt);
861  }
862 
886  template<typename X, typename Y> void AddLinesGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y , const GCoptions & opt)
887  {
889 
890  if (y.size() == 0)
891  {
892  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled";
893  return;
894  }
895 
896  for (size_t i = 0 ; i < y.last().size() ; i++)
897  yn.add(std::string("line") + std::to_string(i));
898 
899  AddLinesGraph(x,y,yn,opt);
900  }
901 
915  template<typename X, typename Y> void AddLinesGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y , const openfpm::vector<std::string> & yn, const GCoptions & opt)
916  {
917  if (y.size() == 0)
918  {
919  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled\n";
920  return;
921  }
922 
923  set_of_graphs.add();
924  injectHTML.add();
925 
926  // Check that all the internal vectors has the same number of elements
927 
928  if (y.size() != 0)
929  {
930  size_t sz = y.get(0).size();
931  for (size_t i = 0; i < y.size() ; i++)
932  {
933  if (y.get(i).size() != sz)
934  std::cerr << __FILE__ << ":" << __LINE__ << " error all the elements in the y vector must have the same numbers of elements " << y.get(i).size() << " != " << sz << "\n";
935  }
936  }
937 
938  set_of_graphs.last().type = GGRAPH_POINTS;
939  set_of_graphs.last().data = get_points_plot_data(x,y,yn,opt,set_of_graphs.size()-1);
940  set_of_graphs.last().option = get_points_plot_option(opt);
941  set_of_graphs.last().opt = opt;
942  }
943 
949  void addHTML(const std::string & html)
950  {
951  injectHTML.last() = html;
952  }
953 
959  void write(std::string file)
960  {
961  // Open a file
962 
963  std::ofstream of(file);
964 
965  // Check if the file is open
966  if (of.is_open() == false)
967  {std::cerr << "Error cannot create the HTML file: " + file + "\n";}
968 
969  // write the file
970 
971  of << begin_data;
972 
973  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
974  addData(of,i,set_of_graphs.get(i).data);
975 
976  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
977  addOption(of,i,set_of_graphs.get(i).option);
978 
979  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
980  addView(of,i,set_of_graphs.get(i).view);
981 
982  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
983  addDrawDiv(of,i,set_of_graphs.get(i).view.size() == 0);
984 
985  of << begin_div;
986 
987  of << injectHTML.get(0);
988 
989  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
990  {
991  addDiv(of,i,set_of_graphs.get(i).opt);
992  of << injectHTML.get(i+1);
993  }
994 
995  of << div_end;
996 
997  of.close();
998  }
999 };
1000 
1001 #endif /* OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_ */
size_t heigh
height of the graph in pixels
Definition: GoogleChart.hpp:49
GCoptions opt
Google chart option.
T get_low(size_t *counters)
Recursively sort variadic template of vectors.
void addDiv(std::ofstream &of, size_t i, const GCoptions &gc)
Add a div section.
std::string curveType
curve type
Definition: GoogleChart.hpp:70
void addHTML(const std::string &html)
Add HTML text.
void addOption(std::ofstream &of, size_t i, const std::string &opt)
Add an option data variable.
void AddLinesGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, const GCoptions &opt)
Add a simple lines graph.
openfpm::vector< std::string > injectHTML
set inject HTML;
bool isStacked
Definition: GoogleChart.hpp:53
void AddHistGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, openfpm::vector< Yn > &yn)
Add an histogram graph.
std::string title
Title of the chart.
Definition: GoogleChart.hpp:28
void AddHistGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, openfpm::vector< Yn > &yn, const GCoptions &opt)
Add an histogram graph.
void AddHistGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y)
Add an histogram graph.
void get_point(typename X::value_type low, typename X::value_type *point, size_t *counters, X &x, X &y, Xs &... xy)
Recursively sort variadic template of vectors.
std::string data
data
bool holes
Data has holes.
std::string more
more
Definition: GoogleChart.hpp:67
std::string view
view in case we need a view
std::string stypeext
Definition: GoogleChart.hpp:43
bool isNext(size_t *counters, X &x, X &y, Xs &... xy)
Recursively sort variadic template of vectors.
size_t size()
Stub size.
Definition: map_vector.hpp:211
void addData(std::ofstream &of, size_t i, const std::string &data)
Add a graph data variable.
void get_point(T low, T *point, size_t *counters)
Recursively sort variadic template of vectors.
void AddLinesGraphT(openfpm::vector< X > &x, openfpm::vector< Y > &y, const GCoptions &opt)
Add lines graph.
std::string yAxis
Y axis name.
Definition: GoogleChart.hpp:30
void AddLines(const openfpm::vector< std::string > &yn, const GCoptions &opt, X ... xy)
Add lines graph.
openfpm::vector< GGraph > set_of_graphs
set of graphs
Small class to produce graph with Google chart in HTML.
std::string intervalext
Definition: GoogleChart.hpp:64
Google Graph.
GCoptions & operator=(const GCoptions &opt)
copy operator
Definition: GoogleChart.hpp:82
void recursive_sort(X &x, X &y, Xs &... xy)
Recursively sort variadic template of vectors.
bool get_v(typename get_value_type< Xs... >::type &x, typename get_value_type< Xs... >::type *point, size_t *counters, Xs &... xy)
Recursively sort variadic template of vectors.
size_t lineWidth
Width of the line.
Definition: GoogleChart.hpp:56
bool isNext(size_t *counters)
Recursively sort variadic template of vectors.
std::string get_view_bar_option(const GCoptions &opt, size_t n_col)
Construct a view option.
size_t type
TypeOfGraph.
std::string option
option
bool barWD
barWD
Definition: GoogleChart.hpp:73
void write(std::string file)
It write the graphs on file in html format using Google charts.
T get_low(size_t *counters, X &x, X &y, Xs &... xy)
Recursively sort variadic template of vectors.
void addDrawDiv(std::ofstream &of, size_t i, bool draw_view)
Add a draw div section.
size_t width
width of the graph in pixels
Definition: GoogleChart.hpp:46
std::string get_points_plot_data(const openfpm::vector< X > &x, const openfpm::vector< Y > &y, const openfpm::vector< std::string > &yn, const GCoptions &opt, size_t i)
Given X and Y vector return the string representing the data section of the Google Chart.
std::string stype
Definition: GoogleChart.hpp:38
std::string intervalsext
Definition: GoogleChart.hpp:60
void AddHistGraph(openfpm::vector< Y > &y)
Add an histogram graph.
void AddLinesGraph(openfpm::vector< X > &x, openfpm::vector< Y > &y, const openfpm::vector< std::string > &yn, const GCoptions &opt)
Add a simple plot graph.
void recursive_sort()
terminator for recursive sort
std::string xAxis
X axis name.
Definition: GoogleChart.hpp:32
Google chart options.
Definition: GoogleChart.hpp:25
void addView(std::ofstream &of, size_t i, std::string view)
Add a view data variable.