OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
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 
14 #define GGRAPH_COLUMS 1
15 #define GGRAPH_POINTS 2
16 
17 #define GC_ZOOM std::string("explorer: {actions: ['dragToZoom', 'rightClickToReset'],axis: 'horizontal,vertical',keepInBounds: true, maxZoomIn: 128.0}")
18 #define GC_X_LOG std::string("hAxis: { logScale: true }")
19 #define GC_Y_LOG std::string("vAxis: { logScale: true }")
20 
24 struct GCoptions
25 {
27  std::string title;
29  std::string yAxis;
31  std::string xAxis;
32 
37  std::string stype;
38 
42  std::string stypeext;
43 
45  size_t width=900;
46 
48  size_t heigh=500;
49 
52  bool isStacked = false;
53 
55  size_t lineWidth = 4;
56 
59  std::string intervalsext;
60 
63  std::string intervalext;
64 
66  std::string more;
67 
69  std::string curveType = "function";
70 
72  bool barWD = false;
73 
81  GCoptions & operator=(const GCoptions & opt)
82  {
83  title = opt.title;
84  yAxis = opt.yAxis;
85  xAxis = opt.xAxis;
86  stype = opt.stype;
87  stypeext = opt.stypeext;
88  width=opt.width;
89  heigh=opt.heigh;
90 
91  lineWidth = opt.lineWidth;
93  more = opt.more;
94 
95  return *this;
96  }
97 };
98 
102 struct GGraph
103 {
105  size_t type;
106 
108  std::string data;
109 
111  std::string option;
112 
114  std::string view;
115 
118 };
119 
121 
122 const std::string begin_data ="<html>\n\
123  <head>\n\
124  <script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>\n\
125  <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\"></script>\n\
126  <script type=\"text/javascript\">\n\
127  google.charts.load('current', {'packages':['corechart']});\n\
128  google.charts.setOnLoadCallback(drawVisualization);\n\
129 \n\
130 function exportToSVG(i)\n\
131 {\n\
132 var e = document.getElementById('chart_div'+i);\n\
133 var svg = e.getElementsByTagName('svg')[0].parentNode.innerHTML;\n\
134 var pos = svg.lastIndexOf(\"</svg>\");\n\
135 pos += 6;\n\
136 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\
137 svgData = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg);\n\
138 $(this).attr({'href': svgData,'target': '_blank'});\n\
139 }\n\
140 \n\
141  function drawVisualization() {\n";
142 
143 const std::string end_data="]);\n\n";
144 
145 const std::string begin_div = "}</script>\n\
146 </head>\n\
147 <body>\n";
148 
149 const std::string div_end = "</body>\n\
150 </html>\n";
151 
152 const std::string saving_javascript = "function save(i)\n\
153  var e = document.getElementById('chart_')\n\
154  e.getElementsByTagName('svg')[0].parentNode.innerHTML";
155 
157 
188 {
191 
194 
209  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)
210  {
211  std::stringstream data;
212 
213  size_t interval = 0;
214 
215  // we require that the number of x elements are the same as y elements
216 
217  if (x.size() != y.size())
218  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector x and the vector y must have the same number of elements " << x.size() << "!=" << y.size() << "\n";
219 
220  // Google chart visualization
221  data << "var data" << i << " = new google.visualization.DataTable();\n";
222  if (std::is_same<X,typename std::string>::value == true)
223  data << "data" << i << ".addColumn(" << "'string'" << "," << "'" << opt.xAxis <<"');\n";
224  else
225  data << "data" << i << ".addColumn(" << "'number'" << "," << "'" << opt.xAxis <<"');\n";
226 
227  for (size_t j = 0 ; j < y.last().size() ; j++)
228  {
229  if (yn.get(j) == std::string("interval"))
230  {
231  data << "data" << i << ".addColumn({id:'i" << interval/2 << "', type:'number', role:'interval'});\n";
232  interval++;
233  }
234  else
235  data << "data" << i << ".addColumn(" << "'number'" << "," << "'" << yn.get(j) <<"');\n";
236  }
237 
238  data << "data" << i << ".addRows([\n";
239  for (size_t i = 0 ; i < y.size() && x.size() ; i++)
240  {
241 
242  for (size_t j = 0 ; j < y.get(i).size()+1 ; j++)
243  {
244  // the first is x
245  if (j == 0)
246  {
247  if (std::is_same<X,typename std::string>::value == true)
248  data << "['" << x.get(i) << "'";
249  else
250  data << "[" << x.get(i);
251  }
252  else
253  data << "," << y.get(i).get(j-1);
254  }
255  data << "],\n";
256  }
257 
258  return data.str();
259  }
260 
268  std::string get_view_bar_option(const GCoptions & opt, size_t n_col)
269  {
270  if (opt.barWD == false)
271  return std::string();
272 
273  std::stringstream str;
274 
275  str << "[0" << std::endl;
276 
277  for (size_t i = 1 ; i < n_col ; i++)
278  {
279  str << "," << i << ",{ calc: \"stringify\"," << std::endl;
280  str << "sourceColumn: " << i << "," << std::endl;
281  str << "type: \"string\"," << std::endl;
282  str << "role: \"annotation\" }"<< std::endl;
283  }
284 
285  str << "]" << std::endl;
286 
287  return str.str();
288  }
289 
290  std::string get_colums_bar_option(const GCoptions & opt)
291  {
292  std::stringstream str;
293  str << "title : '" << opt.title << "'";
294  str << ",\nvAxis: {title: '" << opt.yAxis << "'}";
295  str << ",\nhAxis: {title: '" << opt.xAxis << "'}";
296  str << ",\nseriesType: '" << opt.stype << "'";
297  if (opt.stypeext.size() != 0)
298  str << ",\nseries: " << opt.stypeext;
299  if (opt.more.size() != 0)
300  str << ",\n" <<opt.more;
301 
302  return str.str();
303  }
304 
305  std::string get_points_plot_option(const GCoptions & opt)
306  {
307  std::stringstream str;
308  str << "title : '" << opt.title << "'";
309  str << ",\nvAxis: {title: '" << opt.yAxis << "'}";
310  str << ",\nhAxis: {title: '" << opt.xAxis << "'}";
311  str << ",\ncurveType: '"<< opt.curveType << "'";
312 
313  str << ",\nlineWidth: " << opt.lineWidth;
314  if (opt.intervalsext.size() != 0)
315  str << ",\nintervals: " << opt.intervalsext;
316  else
317  str << ",\nintervals: " << "{ 'style':'area' }";
318 
319  if (opt.intervalext.size() != 0)
320  str << ",\ninterval: " << opt.intervalext << "\n";
321 
322  if (opt.more.size() != 0)
323  str << ",\n" << opt.more;
324 
325  return str.str();
326  }
327 
335  void addData(std::ofstream & of, size_t i, const std::string & data)
336  {
337 
338  of << data;
339  of << "]);\n";
340  }
341 
349  void addOption(std::ofstream & of, size_t i, const std::string & opt)
350  {
351  of << "var options";
352  of << i;
353  of << "= {\n";
354  of << opt;
355  of << "};\n";
356  }
357 
365  void addView(std::ofstream & of, size_t i, std::string view)
366  {
367  if (view.size() == 0)
368  return;
369 
370  of << "var view" << i << " = new google.visualization.DataView(data" << i << ");" << std::endl;
371  of << "view"<< i << ".setColumns(";
372  of << view << ");" << std::endl;
373  }
374 
382  void addDrawDiv(std::ofstream & of, size_t i, bool draw_view)
383  {
384  of << "$(\"#export_svg" << i << "\").on(\"click\", function (event) {exportToSVG.apply(this,[" << i << "]);});\n";
385  of << "var chart = new google.visualization.ComboChart(document.getElementById('chart_div";
386  of << i;
387  of << "'));" << std::endl;
388  if (draw_view == true)
389  {
390  of << "chart.draw(data";
391  of << i;
392  }
393  else
394  {
395  of << "chart.draw(view";
396  of << i;
397  }
398  of << ", options";
399  of << i;
400  of << ");\n";
401  }
402 
410  void addDiv(std::ofstream & of, size_t i, const GCoptions & gc)
411  {
412  of << "<a href=\"#\" download=\"graph1.svg\" id=\"export_svg" << i << "\"><button>Export data into svg</button></a>";
413  of << "<div id=\"chart_div";
414  of << i;
415  of << "\" style=\"width: ";
416  of << gc.width;
417  of << "px; height: ";
418  of << gc.heigh;
419  of << "px;\"></div>\n";
420  }
421 
422 public:
423 
424  GoogleChart()
425  {
426  injectHTML.add();
427  }
428 
435  template<typename Y> void AddHistGraph(openfpm::vector<Y> & y)
436  {
438  x.resize(y.size());
439 
440  AddHistGraph<std::string,Y>(x,y);
441  }
442 
451  template<typename X, typename Y> void AddHistGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y)
452  {
453  GCoptions opt;
454 
456 
457  if (y.size() != 0)
458  yn.resize(y.get(0).size());
459 
460  AddHistGraph<X,Y,std::string>(x,y,yn,opt);
461  }
462 
473  template<typename X, typename Y, typename Yn> void AddHistGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y, openfpm::vector<Yn> & yn)
474  {
475  GCoptions opt;
476 
477  AddHistGraph(x,y,yn,opt);
478  }
479 
492  template<typename X, typename Y, typename Yn> void AddHistGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y, openfpm::vector<Yn> & yn , const GCoptions & opt)
493  {
494  set_of_graphs.add();
495  injectHTML.add();
496 
497  // Check that all the internal vector has the same number of elements
498 
499  if (y.size() != 0)
500  {
501  size_t sz = y.get(0).size();
502  for (size_t i = 0; i < y.size() ; i++)
503  {
504  if (y.get(i).size() != sz)
505  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";
506  }
507  }
508 
509  set_of_graphs.last().type = GGRAPH_COLUMS;
510  set_of_graphs.last().data = get_points_plot_data(x,y,yn,opt,set_of_graphs.size()-1);
511  set_of_graphs.last().option = get_colums_bar_option(opt);
512  set_of_graphs.last().view = get_view_bar_option(opt,y.get(0).size());
513  set_of_graphs.last().opt = opt;
514  }
515 
525  template<typename X, typename Y> void AddLines(openfpm::vector<X> & x, openfpm::vector<Y> & y , const GCoptions & opt)
526  {
528 
529  if (y.size() == 0)
530  {
531  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled" << std::endl;
532  return;
533  }
534 
535  for (size_t i = 0 ; i < y.last().size() ; i++)
536  yn.add(std::string("line") + std::to_string(i));
537 
538  if (y.size() == 0)
539  return;
540 
541  // number of points
542  size_t np = y.last().size();
543 
544  for (size_t j = 0 ; j < y.size() ; j++)
545  {
546  if (y.get(j).size() != np)
547  std::cerr << __FILE__ << ":" << __LINE__ << " Error all the graph must have the same number of points " << np << "!=" << y.get(j).size() << std::endl;
548  }
549 
551 
552 
553  // swap the vector
554  // Each vector is a graph
555  // It is different from the other call where each vector
556  // has multiple value for the same point
557  for (size_t i = 0 ; i < np ; i++)
558  {
559  swap.add();
560  for (size_t j = 0 ; j < y.size() ; j++)
561  {
562  swap.last().add(y.get(j).get(i));
563  }
564  }
565 
566  AddLinesGraph(x,swap,yn,opt);
567  }
568 
580  template<typename X, typename Y> void AddLinesGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y , const GCoptions & opt)
581  {
583 
584  if (y.size() == 0)
585  {
586  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled";
587  return;
588  }
589 
590  for (size_t i = 0 ; i < y.last().size() ; i++)
591  yn.add(std::string("line") + std::to_string(i));
592 
593  AddLinesGraph(x,y,yn,opt);
594  }
595 
609  template<typename X, typename Y> void AddLinesGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y , const openfpm::vector<std::string> & yn, const GCoptions & opt)
610  {
611  if (y.size() == 0)
612  {
613  std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled\n";
614  return;
615  }
616 
617  set_of_graphs.add();
618  injectHTML.add();
619 
620  // Check that all the internal vectors has the same number of elements
621 
622  if (y.size() != 0)
623  {
624  size_t sz = y.get(0).size();
625  for (size_t i = 0; i < y.size() ; i++)
626  {
627  if (y.get(i).size() != sz)
628  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";
629  }
630  }
631 
632  set_of_graphs.last().type = GGRAPH_POINTS;
633  set_of_graphs.last().data = get_points_plot_data(x,y,yn,opt,set_of_graphs.size()-1);
634  set_of_graphs.last().option = get_points_plot_option(opt);
635  set_of_graphs.last().opt = opt;
636  }
637 
643  void addHTML(const std::string & html)
644  {
645  injectHTML.last() = html;
646  }
647 
653  void write(std::string file)
654  {
655  // Open a file
656 
657  std::ofstream of(file);
658 
659  // Check if the file is open
660  if (of.is_open() == false)
661  {std::cerr << "Error cannot create the HTML file: " + file + "\n";}
662 
663  // write the file
664 
665  of << begin_data;
666 
667  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
668  addData(of,i,set_of_graphs.get(i).data);
669 
670  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
671  addOption(of,i,set_of_graphs.get(i).option);
672 
673  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
674  addView(of,i,set_of_graphs.get(i).view);
675 
676  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
677  addDrawDiv(of,i,set_of_graphs.get(i).view.size() == 0);
678 
679  of << begin_div;
680 
681  of << injectHTML.get(0);
682 
683  for (size_t i = 0 ; i < set_of_graphs.size() ; i++)
684  {
685  addDiv(of,i,set_of_graphs.get(i).opt);
686  of << injectHTML.get(i+1);
687  }
688 
689  of << div_end;
690 
691  of.close();
692  }
693 };
694 
695 #endif /* OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_ */
size_t heigh
height of the graph in pixels
Definition: GoogleChart.hpp:48
GCoptions opt
Google chart option.
void addDiv(std::ofstream &of, size_t i, const GCoptions &gc)
Add a div section.
std::string curveType
curve type
Definition: GoogleChart.hpp:69
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 AddLines(openfpm::vector< X > &x, openfpm::vector< Y > &y, const GCoptions &opt)
Add lines graph.
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:52
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:27
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.
std::string data
data
std::string more
more
Definition: GoogleChart.hpp:66
std::string view
view in case we need a view
std::string stypeext
Definition: GoogleChart.hpp:42
size_t size()
Stub size.
Definition: map_vector.hpp:70
void addData(std::ofstream &of, size_t i, const std::string &data)
Add a graph data variable.
std::string yAxis
Y axis name.
Definition: GoogleChart.hpp:29
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:63
Google Graph.
GCoptions & operator=(const GCoptions &opt)
copy operator
Definition: GoogleChart.hpp:81
size_t lineWidth
Width of the line.
Definition: GoogleChart.hpp:55
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:72
void write(std::string file)
It write the graphs on file in html format using Google charts.
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:45
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:37
std::string intervalsext
Definition: GoogleChart.hpp:59
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.
std::string xAxis
X axis name.
Definition: GoogleChart.hpp:31
Google chart options.
Definition: GoogleChart.hpp:24
void addView(std::ofstream &of, size_t i, std::string view)
Add a view data variable.