Commit cf974ef2 authored by Pietro Incardona's avatar Pietro Incardona

Adding Google Chart

parent 2c3e2c62
......@@ -11,6 +11,7 @@
#include <fstream>
#define GGRAPH_COLUMS 1
#define GGRAPH_POINTS 2
/*! \brief Google chart options
*
......@@ -38,8 +39,34 @@ struct GCoptions
size_t width=900;
size_t heigh=500;
//! Flag that specify if the colums are stacked
//! Check in Google Chart for is stacked option
bool isStacked = false;
//! Width of the line
size_t lineWidth = 4;
//! Style for all the intervals
//! Check Google Chart API intervals option
std::string intervalsext;
//! Style for each interval
//! Check Google Chart API interval option
std::string intervalext;
GCoptions & operator=(const GCoptions & opt)
{
title = opt.title;
yAxis = opt.yAxis;
xAxis = opt.xAxis;
stype = opt.stype;
stypeext = opt.stypeext;
width=opt.width;
heigh=opt.heigh;
lineWidth = opt.lineWidth;
intervalsext = opt.intervalsext;
return *this;
}
};
......@@ -93,14 +120,83 @@ class GoogleChart
// set inject HTML;
openfpm::vector<std::string> injectHTML;
/*! \brief Given X and Y vector
/*! \brief Given X and Y vector return the string representing the data section of the Google Chart
*
* \param X vector
* \param Y vector
* \param i counter
*
* \return string with the data section
*
*/
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)
{
std::stringstream data;
size_t interval = 0;
// 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";
// Google chart visualization
data << "var data" << i << " = new google.visualization.DataTable();\n";
if (std::is_same<X,typename std::string>::value == true)
data << "data" << i << ".addColumn(" << "'string'" << "," << "'" << opt.xAxis <<"');\n";
else
data << "data" << i << ".addColumn(" << "'number'" << "," << "'" << opt.xAxis <<"');\n";
for (size_t j = 0 ; j < y.last().size() ; j++)
{
if (yn.get(j) == std::string("interval"))
{
data << "data" << i << ".addColumn({id:'i" << interval/2 << "', type:'number', role:'interval'});\n";
interval++;
}
else
data << "data" << i << ".addColumn(" << "'number'" << "," << "'" << yn.get(j) <<"');\n";
}
data << "data" << i << ".addRows([\n";
for (size_t i = 0 ; i < y.size() ; i++)
{
for (size_t j = 0 ; j < y.get(i).size()+1 ; j++)
{
// the first is x
if (j == 0)
{
if (std::is_same<X,typename std::string>::value == true)
data << "['" << x.get(i) << "'";
else
data << "[" << x.get(i);
}
else
data << "," << y.get(i).get(j-1);
}
data << "],\n";
}
return data.str();
}
/*! \brief Given X and Y vector return the string representing the data section of the Google Chart
*
* \param X vector
* \param Y vector
*
* \return string with the data section
*
*/
template<typename X, typename Y, typename Yn> std::string get_data(const openfpm::vector<X> & x, const openfpm::vector<Y> & y, const openfpm::vector<Yn> & yn, const GCoptions & opt)
template<typename X, typename Y, typename Yn> std::string get_colums_bar_data(const openfpm::vector<X> & x, const openfpm::vector<Y> & y, const openfpm::vector<Yn> & yn, const GCoptions & opt, size_t i)
{
std::stringstream data;
data << "var data";
data << i;
data << " = google.visualization.arrayToDataTable([\n";
// we require that the number of x elements are the same as y elements
if (x.size() != y.size())
......@@ -127,7 +223,7 @@ class GoogleChart
return data.str();
}
std::string get_option(const GCoptions & opt)
std::string get_colums_bar_option(const GCoptions & opt)
{
std::stringstream str;
str << "title : '" << opt.title << "',\n";
......@@ -140,6 +236,26 @@ class GoogleChart
return str.str();
}
std::string get_points_plot_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 << "curveType: 'function',\n";
str << "lineWidth: " << opt.lineWidth << ",\n";
if (opt.intervalsext.size() != 0)
str << "intervals: " << opt.intervalsext << ",\n";
else
str << "intervals: " << "{ 'style':'area' }" << ",\n";
if (opt.intervalext.size() != 0)
str << "interval: " << opt.intervalext << "\n";
return str.str();
}
/*! \brief Add a graph data variable
*
* \param of file out
......@@ -149,9 +265,7 @@ class GoogleChart
*/
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";
}
......@@ -294,8 +408,77 @@ public:
}
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().data = get_colums_bar_data(x,y,yn,opt,set_of_graphs.size()-1);
set_of_graphs.last().option = get_colums_bar_option(opt);
set_of_graphs.last().opt = opt;
}
/*! \brief Add a simple plot graph
*
* \param y A vector of vector of values (numbers) the size of y indicate how many x values
* or colums do we have, while the internal vector can store multiple realizations,
* or min and max, for error bar
*
* \param x Give a name or number to each colums, so can be a string or a number
*
* \param opt Graph options
*
*/
template<typename X, typename Y> void AddPointsGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y , const GCoptions & opt)
{
openfpm::vector<std::string> yn;
if (y.size() == 0)
{
std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled";
return;
}
for (size_t i = 0 ; i < y.last().size() ; i++)
yn.add(std::string("line") + std::to_string(i));
AddPointsGraph(x,y,yn,opt);
}
/*! \brief Add a simple plot graph
*
* \param y A vector of vector of values (numbers) the size of y indicate how many x values
* or colums we have, while the internal vector store multiple lines,
* or error bars
*
* \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 line, or specify an error bar
*
* \param opt Graph options
*
*/
template<typename X, typename Y> void AddPointsGraph(openfpm::vector<X> & x, openfpm::vector<Y> & y , const openfpm::vector<std::string> & yn, const GCoptions & opt)
{
if (y.size() == 0)
{
std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " vector y must be filled";
return;
}
set_of_graphs.add();
injectHTML.add();
// Check that all the internal vectors 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_POINTS;
set_of_graphs.last().data = get_points_plot_data(x,y,yn,opt,set_of_graphs.size()-1);
set_of_graphs.last().option = get_points_plot_option(opt);
set_of_graphs.last().opt = opt;
}
......
......@@ -284,6 +284,104 @@ BOOST_AUTO_TEST_CASE( google_chart_with_inject_HTML )
BOOST_REQUIRE_EQUAL(true,test);
}
BOOST_AUTO_TEST_CASE( google_chart_linear_plot )
{
openfpm::vector<std::string> x;
openfpm::vector<openfpm::vector<double>> y;
openfpm::vector<std::string> yn;
x.add("colum1");
x.add("colum2");
x.add("colum3");
x.add("colum4");
x.add("colum5");
x.add("colum6");
// Here we specify how many lines we have
// first Line
yn.add("line1");
// second line + 2 intervals (Error bands)
yn.add("line2");
yn.add("interval");
yn.add("interval");
yn.add("interval");
yn.add("interval");
// third line + 1 interval (Error bands)
yn.add("line3");
yn.add("interval");
yn.add("interval");
// Each line can have multiple intervals or error bars
// The first number specify the bottom line
// The last three numbers specify the top line + error band (min, max)
// The middle 5 line specify the middle lines + one external error band + one internal error band
y.add({0.10,0.20,0.19,0.22,0.195,0.215,0.35,0.34,0.36});
y.add({0.11,0.21,0.18,0.22,0.19,0.215,0.36,0.35,0.37});
y.add({0.12,0.22,0.21,0.23,0.215,0.225,0.35,0.34,0.36});
y.add({0.15,0.25,0.20,0.26,0.22,0.255,0.36,0.35,0.37});
y.add({0.09,0.29,0.25,0.30,0.26,0.295,0.35,0.34,0.36});
y.add({0.08,0.28,0.27,0.29,0.275,0.285,0.36,0.35,0.37});
// Google charts options
GCoptions options;
options.title = std::string("Example");
options.yAxis = std::string("Y Axis");
options.xAxis = std::string("X Axis");
options.lineWidth = 1.0;
options.intervalext = std::string("{'i2': { 'color': '#4374E0', 'style':'bars', 'lineWidth':4, 'fillOpacity':1 } }");
GoogleChart cg;
cg.AddPointsGraph(x,y,yn,options);
cg.write("gc_plot_out.html");
bool test = compare("gc_plot_out.html","gc_plot_out_test.html");
BOOST_REQUIRE_EQUAL(true,test);
}
BOOST_AUTO_TEST_CASE( google_chart_linear_plot2 )
{
openfpm::vector<std::string> x;
openfpm::vector<openfpm::vector<double>> y;
x.add("colum1");
x.add("colum2");
x.add("colum3");
x.add("colum4");
x.add("colum5");
x.add("colum6");
// Each line can have multiple intervals or error bars
// The first number specify the bottom line
// The last three numbers specify the top line + error band (min, max)
// The middle 5 line specify the middle lines + one external error band + one internal error band
y.add({0.10,0.20,0.19,0.22,0.195,0.215,0.35,0.34,0.36});
y.add({0.11,0.21,0.18,0.22,0.19,0.215,0.36,0.35,0.37});
y.add({0.12,0.22,0.21,0.23,0.215,0.225,0.35,0.34,0.36});
y.add({0.15,0.25,0.20,0.26,0.22,0.255,0.36,0.35,0.37});
y.add({0.09,0.29,0.25,0.30,0.26,0.295,0.35,0.34,0.36});
y.add({0.08,0.28,0.27,0.29,0.275,0.285,0.36,0.35,0.37});
// Google charts options
GCoptions options;
options.title = std::string("Example");
options.yAxis = std::string("Y Axis");
options.xAxis = std::string("X Axis");
options.lineWidth = 1.0;
GoogleChart cg;
cg.AddPointsGraph(x,y,options);
cg.write("gc_plot2_out.html");
bool test = compare("gc_plot2_out.html","gc_plot2_out_test.html");
BOOST_REQUIRE_EQUAL(true,test);
}
BOOST_AUTO_TEST_SUITE_END()
#endif /* OPENFPM_DATA_SRC_PLOT_PLOT_UNIT_TESTS_HPP_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment