Skip to content
Snippets Groups Projects
Commit cf974ef2 authored by Pietro Incardona's avatar Pietro Incardona
Browse files

Adding Google Chart

parent 2c3e2c62
No related branches found
No related tags found
No related merge requests found
......@@ -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_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment