diff --git a/gc_out2_test.html b/gc_out2_test.html new file mode 100644 index 0000000000000000000000000000000000000000..771c7bfc6dccce3725accacdcc9d9c2978570703 --- /dev/null +++ b/gc_out2_test.html @@ -0,0 +1,31 @@ + + + + + + +
+ + diff --git a/gc_out3_test.html b/gc_out3_test.html new file mode 100644 index 0000000000000000000000000000000000000000..6ae633a424a988d754fa3e46a6053ebcd43fd33b --- /dev/null +++ b/gc_out3_test.html @@ -0,0 +1,31 @@ + + + + + + +
+ + diff --git a/gc_out4_test.html b/gc_out4_test.html new file mode 100644 index 0000000000000000000000000000000000000000..53d712696c22c2824fcf65eed863f0f473e7cd35 --- /dev/null +++ b/gc_out4_test.html @@ -0,0 +1,31 @@ + + + + + + +
+ + diff --git a/gc_out5_test.html b/gc_out5_test.html new file mode 100644 index 0000000000000000000000000000000000000000..866e4b702683b0103713d1d32f3293745f671542 --- /dev/null +++ b/gc_out5_test.html @@ -0,0 +1,31 @@ + + + + + + +
+ + diff --git a/gc_out6_test.html b/gc_out6_test.html new file mode 100644 index 0000000000000000000000000000000000000000..8787f4649c178c6bd4a910f21b849336ff604ec7 --- /dev/null +++ b/gc_out6_test.html @@ -0,0 +1,31 @@ + + + + + + +
+ + diff --git a/gc_out_test.html b/gc_out_test.html new file mode 100644 index 0000000000000000000000000000000000000000..77b615238355cd3dab9c821dca488a86bb27fd4f --- /dev/null +++ b/gc_out_test.html @@ -0,0 +1,32 @@ + + + + + + +
+ + diff --git a/src/Plot/GoogleChart.hpp b/src/Plot/GoogleChart.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f718a69afd678dd9a1cba26bfce60220fabd5162 --- /dev/null +++ b/src/Plot/GoogleChart.hpp @@ -0,0 +1,356 @@ +/* + * GoogleChart.hpp + * + * Created on: Jan 9, 2016 + * Author: i-bird + */ + +#ifndef OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_ +#define OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_ + +#include + +#define GGRAPH_COLUMS 1 + +/*! \brief Google chart options + * + */ +struct GCoptions +{ + //! Title of the chart + std::string title; + //! Y axis name + std::string yAxis; + //! X axis name + std::string xAxis; + + //! Type of chart (list of the option can be founded in Google Chart API for seriesType) + //! Possible options are: + //! 'line', 'area', 'bars', 'candlesticks', and 'steppedArea' + //! default: line + std::string stype; + + //! Extended series options + //! Example {5: {type: 'line'}} specify that the series number 5 must be represented + //! with a line + std::string stypeext; + + size_t width=900; + size_t heigh=500; + + GCoptions & operator=(const GCoptions & opt) + { + return *this; + } +}; + +struct GGraph +{ + // TypeOfGraph + size_t type; + + // data + std::string data; + + // option + std::string option; + + // Google chart option + GCoptions opt; +}; + +/////////////////// Constants strings usefull to construct the HTML page ////////// + +const std::string begin_data ="\n\ + \n\ + \n\ + \n\ +\n\ +\n"; + +const std::string div_end = "\n\ +\n"; + +///////////////////////////////////////////////////////////////////// + +/*! It convert an array y or a set of two array x,y into a Google chart + * + */ +class GoogleChart +{ + // set of graphs + openfpm::vector set_of_graphs; + + // set inject HTML; + openfpm::vector injectHTML; + + /*! \brief Given X and Y vector + * + * + */ + template std::string get_data(const openfpm::vector & x, const openfpm::vector & y, const openfpm::vector & yn, const GCoptions & opt) + { + std::stringstream data; + + // we require that the number of x elements are the same as y elements + + if (x.size() != y.size()) + std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector x and the vector y must have the same number of elements " << x.size() << "!=" << y.size() << "\n"; + + data << "['"; + data << opt.xAxis << "'"; + for (size_t i = 0 ; i < yn.size() ; i++) + data << ",'" << std::to_string(yn.get(i)) << "'"; + + data << "],\n"; + + // Write the values + for (size_t i = 0 ; i < y.size() ; i++) + { + data << "["; + data << "'" << std::to_string(x.get(i)) << "'"; + for (size_t j = 0 ; j < y.get(i).size() ; j++) + data << "," << std::to_string(y.get(i).get(j)); + + data << "],\n"; + } + + return data.str(); + } + + std::string get_option(const GCoptions & opt) + { + std::stringstream str; + str << "title : '" << opt.title << "',\n"; + str << "vAxis: {title: '" << opt.yAxis << "'},\n"; + str << "hAxis: {title: '" << opt.xAxis << "'},\n"; + str << "seriesType: '" << opt.stype << "',\n"; + if (opt.stypeext.size() != 0) + str << "series: " << opt.stypeext << "\n"; + + return str.str(); + } + + /*! \brief Add a graph data variable + * + * \param of file out + * \param i id + * \param data string + * + */ + void addData(std::ofstream & of, size_t i, const std::string & data) + { + of << "var data"; + of << i; + of << " = google.visualization.arrayToDataTable([\n"; + of << data; + of << "]);\n"; + } + + /*! \brief Add an option data variable + * + * \param of file out + * \param i id + * \param opt string + * + */ + void addOption(std::ofstream & of, size_t i, const std::string & opt) + { + of << "var options"; + of << i; + of << "= {\n"; + of << opt; + of << "};\n"; + } + + /*! \brief Add a draw div section + * + * \param of file out + * \param i id + * + */ + void addDrawDiv(std::ofstream & of, size_t i) + { + of << "var chart = new google.visualization.ComboChart(document.getElementById('chart_div"; + of << i; + of << "'));chart.draw(data"; + of << i; + of << ", options"; + of << i; + of << ");\n"; + } + + /*! \brief Add a div section + * + * \param i id + * \param gc GoogleChart option + * + */ + void addDiv(std::ofstream & of, size_t i, const GCoptions & gc) + { + of << "
\n"; + } + +public: + + GoogleChart() + { + injectHTML.add(); + } + + /*! \brief Add a colums graph + * + * \param y A vector of vector of values (numbers) the size of y indicate how many columns + * has the graph while the internal vector can store multiple datasets + * + */ + template void AddColumsGraph(openfpm::vector & y) + { + openfpm::vector x; + x.resize(y.size()); + + AddColumsGraph(x,y); + } + + /*! \brief Add a colums graph + * + * \param y A vector of vector of values (numbers) the size of y indicate how many columns + * has the graph while the internal vector can store multiple datasets + * + * \param x Give a name or number to each colums, so can be a string or a number + * + */ + template void AddColumsGraph(openfpm::vector & x, openfpm::vector & y) + { + GCoptions opt; + + openfpm::vector yn; + + if (y.size() != 0) + yn.resize(y.get(0).size()); + + AddColumsGraph(x,y,yn,opt); + } + + /*! \brief Add a colums graph + * + * \param y A vector of vector of values (numbers) the size of y indicate how many columns + * has the graph while the internal vector can store multiple datasets + * + * \param x Give a name or number to each colums, so can be a string or a number + * + * \param yn Give a name to each dataset + * + */ + template void AddColumsGraph(openfpm::vector & x, openfpm::vector & y, openfpm::vector & yn) + { + GCoptions opt; + + AddColumsGraph(x,y,yn,opt); + } + + /*! \brief Add a colums graph + * + * \param y A vector of vector of values (numbers) the size of y indicate how many columns + * has the graph while the internal vector can store multiple datasets + * + * \param x Give a name or number to each colums, so can be a string or a number + * + * \param yn Give a name to each dataset + * + * \param opt Graph options + * + */ + template void AddColumsGraph(openfpm::vector & x, openfpm::vector & y, openfpm::vector & yn , const GCoptions & opt) + { + set_of_graphs.add(); + injectHTML.add(); + + // Check that all the internal vector has the same number of elements + + if (y.size() != 0) + { + size_t sz = y.get(0).size(); + for (size_t i = 0; i < y.size() ; i++) + { + if (y.get(i).size() != sz) + 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"; + } + } + + set_of_graphs.last().type = GGRAPH_COLUMS; + set_of_graphs.last().data = get_data(x,y,yn,opt); + set_of_graphs.last().option = get_option(opt); + set_of_graphs.last().opt = opt; + } + + /*! \brief Add HTML text + * + * \param html add html text in the page + * + */ + void addHTML(const std::string & html) + { + injectHTML.last() = html; + } + + /*! \brief It write the html file + * + * \param file output html file + * + */ + void write(std::string file) + { + // Open a file + + std::ofstream of(file); + + // Check if the file is open + if (of.is_open() == false) + {std::cerr << "Error cannot create the HTML file: " + file + "\n";} + + // write the file + + of << begin_data; + + for (size_t i = 0 ; i < set_of_graphs.size() ; i++) + addData(of,i,set_of_graphs.get(i).data); + + for (size_t i = 0 ; i < set_of_graphs.size() ; i++) + addOption(of,i,set_of_graphs.get(i).option); + + for (size_t i = 0 ; i < set_of_graphs.size() ; i++) + addDrawDiv(of,i); + + of << begin_div; + + of << injectHTML.get(0); + + for (size_t i = 0 ; i < set_of_graphs.size() ; i++) + { + addDiv(of,i,set_of_graphs.get(i).opt); + of << injectHTML.get(i+1); + } + + of << div_end; + + of.close(); + } +}; + +#endif /* OPENFPM_DATA_SRC_PLOT_GOOGLECHART_HPP_ */ diff --git a/src/Plot/Plot_unit_tests.hpp b/src/Plot/Plot_unit_tests.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c7591ecfea0e81e84c7dbbcfe8a58f7d09ba21e6 --- /dev/null +++ b/src/Plot/Plot_unit_tests.hpp @@ -0,0 +1,289 @@ +/* + * Plot_unit_tests.hpp + * + * Created on: Jan 9, 2016 + * Author: i-bird + */ + +#ifndef OPENFPM_DATA_SRC_PLOT_PLOT_UNIT_TESTS_HPP_ +#define OPENFPM_DATA_SRC_PLOT_PLOT_UNIT_TESTS_HPP_ + +#include "GoogleChart.hpp" + +BOOST_AUTO_TEST_SUITE( plot_unit_test ) + +BOOST_AUTO_TEST_CASE( google_chart ) +{ + openfpm::vector x; + openfpm::vector> y; + openfpm::vector yn; + + x.add("colum1"); + x.add("colum2"); + x.add("colum3"); + x.add("colum4"); + x.add("colum5"); + x.add("colum6"); + + // Each colum can have multiple data set (in this case 4 dataset) + // Each dataset can have a name + yn.add("dataset1"); + yn.add("dataset2"); + yn.add("dataset3"); + yn.add("dataset4"); + + // Each colums can have multiple data-set + y.add({2,3,5,6}); + y.add({5,6,1,6}); + y.add({2,1,6,9}); + y.add({1,6,3,2}); + y.add({3,3,0,6}); + y.add({2,1,4,6}); + + // Google charts options + GCoptions options; + + options.title = std::string("Example"); + options.yAxis = std::string("Y Axis"); + options.xAxis = std::string("X Axis"); + options.stype = std::string("bars"); + + // it say that the colum4 must me represented with a line + options.stypeext = std::string("{3: {type: 'line'}}"); + + GoogleChart cg; + cg.AddColumsGraph(x,y,yn,options); + cg.write("gc_out.html"); + + bool test = compare("gc_out.html","gc_out_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_CASE( google_chart2 ) +{ + openfpm::vector x; + openfpm::vector> y; + openfpm::vector yn; + + x.add("colum1"); + x.add("colum2"); + x.add("colum3"); + x.add("colum4"); + x.add("colum5"); + x.add("colum6"); + + // Each colum can have multiple data set (in this case 4 dataset) + // Each dataset can have a name + yn.add("dataset1"); + yn.add("dataset2"); + yn.add("dataset3"); + yn.add("dataset4"); + + // Each colums can have multiple data-set + y.add({2.2,1.3,4.5,0.6}); + y.add({5.0,6.1,1.3,2.6}); + y.add({2.1,1.0,6.1,9.3}); + y.add({1.1,6.1,3.0,2.0}); + y.add({3.3,0.3,0.0,6.2}); + y.add({2.0,1.1,4.0,6.1}); + + // Google charts options + GCoptions options; + + options.title = std::string("Example"); + options.yAxis = std::string("Y Axis"); + options.xAxis = std::string("X Axis"); + options.stype = std::string("bars"); + + GoogleChart cg; + cg.AddColumsGraph(x,y,yn,options); + cg.write("gc_out2.html"); + + bool test = compare("gc_out2.html","gc_out2_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_CASE( google_chart3 ) +{ + openfpm::vector x; + openfpm::vector> y; + openfpm::vector yn; + + x.add("colum1"); + x.add("colum2"); + x.add("colum3"); + x.add("colum4"); + x.add("colum5"); + x.add("colum6"); + + // Each colum can have multiple data set (in this case 4 dataset) + // Each dataset can have a name + yn.add("dataset1"); + yn.add("dataset2"); + yn.add("dataset3"); + yn.add("dataset4"); + + // Each colums can have multiple data-set + y.add({2.2,1.3,4.5,0.6}); + y.add({5.0,6.1,1.3,2.6}); + y.add({2.1,1.0,6.1,9.3}); + y.add({1.1,6.1,3.0,2.0}); + y.add({3.3,0.3,0.0,6.2}); + y.add({2.0,1.1,4.0,6.1}); + + // Google charts options + GCoptions options; + + options.title = std::string("Example"); + options.yAxis = std::string("Y Axis"); + options.xAxis = std::string("X Axis"); + + GoogleChart cg; + cg.AddColumsGraph(x,y,yn,options); + cg.write("gc_out3.html"); + + bool test = compare("gc_out3.html","gc_out3_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_CASE( google_chart4 ) +{ + openfpm::vector x; + openfpm::vector> y; + openfpm::vector yn; + + x.add("colum1"); + x.add("colum2"); + x.add("colum3"); + x.add("colum4"); + x.add("colum5"); + x.add("colum6"); + + // Each colum can have multiple data set (in this case 4 dataset) + // Each dataset can have a name + yn.add("dataset1"); + yn.add("dataset2"); + yn.add("dataset3"); + yn.add("dataset4"); + + // Each colums can have multiple data-set + y.add({2.2,1.3,4.5,0.6}); + y.add({5.0,6.1,1.3,2.6}); + y.add({2.1,1.0,6.1,9.3}); + y.add({1.1,6.1,3.0,2.0}); + y.add({3.3,0.3,0.0,6.2}); + y.add({2.0,1.1,4.0,6.1}); + + GoogleChart cg; + cg.AddColumsGraph(x,y,yn); + cg.write("gc_out4.html"); + + bool test = compare("gc_out4.html","gc_out4_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_CASE( google_chart5 ) +{ + openfpm::vector x; + openfpm::vector> y; + + x.add("colum1"); + x.add("colum2"); + x.add("colum3"); + x.add("colum4"); + x.add("colum5"); + x.add("colum6"); + + // Each colums can have multiple data-set + y.add({2.2,1.3,4.5,0.6}); + y.add({5.0,6.1,1.3,2.6}); + y.add({2.1,1.0,6.1,9.3}); + y.add({1.1,6.1,3.0,2.0}); + y.add({3.3,0.3,0.0,6.2}); + y.add({2.0,1.1,4.0,6.1}); + + GoogleChart cg; + cg.AddColumsGraph(x,y); + cg.write("gc_out5.html"); + + bool test = compare("gc_out5.html","gc_out5_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_CASE( google_chart6 ) +{ + openfpm::vector> y; + + // Each colums can have multiple data-set + y.add({2.2,1.3,4.5,0.6}); + y.add({5.0,6.1,1.3,2.6}); + y.add({2.1,1.0,6.1,9.3}); + y.add({1.1,6.1,3.0,2.0}); + y.add({3.3,0.3,0.0,6.2}); + y.add({2.0,1.1,4.0,6.1}); + + GoogleChart cg; + cg.AddColumsGraph(y); + cg.write("gc_out6.html"); + + bool test = compare("gc_out6.html","gc_out6_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_CASE( google_chart_with_inject_HTML ) +{ + openfpm::vector x; + openfpm::vector> y; + openfpm::vector yn; + + x.add("colum1"); + x.add("colum2"); + x.add("colum3"); + x.add("colum4"); + x.add("colum5"); + x.add("colum6"); + + // Each colum can have multiple data set (in this case 4 dataset) + // Each dataset can have a name + yn.add("dataset1"); + yn.add("dataset2"); + yn.add("dataset3"); + yn.add("dataset4"); + + // Each colums can have multiple data-set + y.add({2,3,5,6}); + y.add({5,6,1,6}); + y.add({2,1,6,9}); + y.add({1,6,3,2}); + y.add({3,3,0,6}); + y.add({2,1,4,6}); + + // Google charts options + GCoptions options; + + options.title = std::string("Example"); + options.yAxis = std::string("Y Axis"); + options.xAxis = std::string("X Axis"); + options.stype = std::string("bars"); + + // it say that the colum4 must me represented with a line + options.stypeext = std::string("{3: {type: 'line'}}"); + + GoogleChart cg; + // + cg.addHTML("

Before first graph

"); + cg.AddColumsGraph(x,y,yn,options); + cg.addHTML("

Before second graph

"); + cg.AddColumsGraph(x,y,yn,options); + cg.addHTML("

Before third graph

"); + cg.AddColumsGraph(x,y,yn,options); + cg.addHTML("

At the end

"); + cg.write("gc_out7.html"); + + bool test = compare("gc_out7.html","gc_out7_test.html"); + BOOST_REQUIRE_EQUAL(true,test); +} + +BOOST_AUTO_TEST_SUITE_END() + +#endif /* OPENFPM_DATA_SRC_PLOT_PLOT_UNIT_TESTS_HPP_ */ diff --git a/src/main.cpp b/src/main.cpp index b36f2912e5cca499f1cd4100011aaf9fd39cdee0..24e7fd15d6ebbe64074f8986e8b789a7fd08adda 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,3 +9,4 @@ #include "CSVWriter_unit_tests.hpp" #include "GraphMLWriter_unit_tests.hpp" #include "VTKWriter_unit_tests.hpp" +#include "Plot/Plot_unit_tests.hpp"