问题
I would like to use CERN ROOT to draw a 2d graph of pairs of x-y datapoints possibly also with y-errorbars. However I only know how to draw histograms.
Is this possible with CERN ROOT? If so how?
Also I realize that there may be better libraries for doing this. I have been using GNUPlot, but unfortunately I can't seem to integrate it well with my C++ code, since I can't find a C/C++ GNUPlot interface which covers all the features and allows me to send data in a bidirectional manner - ie: both to and from GNUPlot.
If you have a better alternative suggestion then that would be most welcome.
回答1:
There is gnuplot iostream to send data from c++ to gnuplot. Within root, you can use (as suggested by the others) TGraph
, TGraphErrors
, TGraphAsymErrors
.
EDIT:
the gnuplot iostream example from its homepage looks like this. Means once you have your data points either as one vector of tuples or as several vectors of floats, you can send them to gnuplot.
#include <vector>
#include <cmath>
#include <boost/tuple/tuple.hpp>
#include "gnuplot-iostream.h"
int main() {
Gnuplot gp;
// Create a script which can be manually fed into gnuplot later:
// Gnuplot gp(">script.gp");
// Create script and also feed to gnuplot:
// Gnuplot gp("tee plot.gp | gnuplot -persist");
// Or choose any of those options at runtime by setting the GNUPLOT_IOSTREAM_CMD
// environment variable.
// Gnuplot vectors (i.e. arrows) require four columns: (x,y,dx,dy)
std::vector<boost::tuple<double, double, double, double> > pts_A;
// You can also use a separate container for each column, like so:
std::vector<double> pts_B_x;
std::vector<double> pts_B_y;
std::vector<double> pts_B_dx;
std::vector<double> pts_B_dy;
// You could also use:
// std::vector<std::vector<double> >
// boost::tuple of four std::vector's
// std::vector of std::tuple (if you have C++11)
// arma::mat (with the Armadillo library)
// blitz::Array<blitz::TinyVector<double, 4>, 1> (with the Blitz++ library)
// ... or anything of that sort
for(double alpha=0; alpha<1; alpha+=1.0/24.0) {
double theta = alpha*2.0*3.14159;
pts_A.push_back(boost::make_tuple(
cos(theta),
sin(theta),
-cos(theta)*0.1,
-sin(theta)*0.1
));
pts_B_x .push_back( cos(theta)*0.8);
pts_B_y .push_back( sin(theta)*0.8);
pts_B_dx.push_back( sin(theta)*0.1);
pts_B_dy.push_back(-cos(theta)*0.1);
}
// Don't forget to put "\n" at the end of each line!
gp << "set xrange [-2:2]\nset yrange [-2:2]\n";
// '-' means read from stdin. The send1d() function sends data to gnuplot's stdin.
gp << "plot '-' with vectors title 'pts_A', '-' with vectors title 'pts_B'\n";
gp.send1d(pts_A);
gp.send1d(boost::make_tuple(pts_B_x, pts_B_y, pts_B_dx, pts_B_dy));
return 0;
}
回答2:
Yes it is possible, you can do it like this:
// At program start
TApplication tapp("app", 0, 0); // this is needed for some reason - not ideal
// Later in program
TGraph *tgraph = new TGraph(N, x, y); // data: x,y N points
TCanvas *tcanvas = new TCanvas("tcanvas","canvas title", 200, 10, 800, 600);
tgraph->SetMarkerColor(kBlue);
tgraph->SetMarkerStyle(21);
tgraph->Draw();
tcanvas->Update();
// Wait for user to check if graph is "okay"
std::cin.get();
delete tcanvas;
delete tgraph;
**BUT** This code will NOT work in a loop. The subsequent graphs will be blank. I do not know why.
来源:https://stackoverflow.com/questions/31654406/cern-root-is-is-possible-to-plot-pairs-of-x-y-data-points