I am having an issue with creating a TGraph. What I have is a vector (not a TVector) of doubles and a vector of strings. I would like to fill a TGraph and have the y-axis values be the values from the vector of doubles and have the x-axis values be the values from the vector of strings. Is there a way to do this? Thanks in advance.
Although as couet said this is not intended by root it is still possible because the TGraph class uses an internal TH1 for drawing so all possibilities of a TH1 are more or less available for TGraphs. Assuming your vecors are of the std::vector type I’ve written you a short macro that does what you want. I names the vecors simply y_vals and x_labels. The problem is that you still have to set a numeric x-value, because otherwise root does not know where on the x-axis a specific string has to be drawn. In my example I just enumerate the points from 1 to Number of Points, which I assume is what you intended:
std::vector<Double_t> y_vals;
std::vector<std::string> x_labels;
// Fill the vectors here
TGraph* tg = new TGraph(TMath::Min(y_vals.size(), x_labels.size())); // Create the TGraph object
for (Int_t i = 0; i < TMath::Min(y_vals.size(), x_labels.size()); i++) { // Loop over all entries
tg->SetPoint(i, i + 1., y_vals[i]); // Set The point itself
tg->GetXaxis()->SetBinLabel(tg->GetXaxis()->FindBin(i + 1.), x_labels[i].c_str()); // Find out which bin on the x-axis the point corresponds to and set the bin label
}
tg->Draw("AP"); // Draw the TGraph
Hope this helps you. I tested it and it worked like I expected it to.
data40Ktest.dat.txt (701 Bytes)
Hi, thank you for this solution, it works for me- but along the x axis, all values aren’t displayed. It just shows one of them at the end. Any idea how to solve this?
void plot(){
std::vector<Double_t> y_vals;
std::vector<std::string> x_labels;
// Fill the vectors here
std::ifstream file ("data40Ktest.dat");
if(!file){
cout << "File doesn't exist" << endl;
}
std::string x;
double y;
int i = 0;
while(!file.eof()){
file >> x >> y;
x_labels.push_back(x);
y_vals.push_back(y);
}
TGraph* tg = new TGraph(TMath::Min(y_vals.size(), x_labels.size())); // Create the TGraph object
for (Int_t i = 0; i < TMath::Min(y_vals.size(), x_labels.size()); i++) { // Loop over all entries
tg->SetPoint(i, i + 1., y_vals[i]); // Set The point itself
tg->GetXaxis()->SetBinLabel(tg->GetXaxis()->FindBin(i + 1.), x_labels[i].c_str()); // Find out which bin on the x-axis the point corresponds to and set t
}
tg->Draw("ALP"); // Draw the TGraph
}
As @couet already stated alphanumeric labels are not intended on Graphs. You have to see my solution as a dirty hack. I think the most probable reason why it does not work for you is that the bin labels are not transferred when the internal helper histogram is recreated.
One could solve this by creating an explicit helper histogram by hand:
TGraph* tg = new TGraph(TMath::Min(y_vals.size(), x_labels.size()));
for (Int_t i = 0; i < tg->GetN(); i++)
tg->SetPoint(i, i + 1., y_vals[i]);
TH1F* h = (TH1F*) tg->GetHistogram()->Clone();
for (Int_t i = 0; i < tg->GetN(); i++)
h->GetXaxis()->SetBinLabel(i + 1, x_labels[i].c_str());
h->Draw("AXIS");
tg->Draw("LP");
@Triple_S Thanks for the trick, but it doesn’t work for me, when I try to make a graph with double Y axis. It either doesn’t draw it at all, or draws it wrong.
void plot(){
std::vector<Double_t> y_vals;
std::vector<std::string> x_labels;
std::vector<Double_t> y2_vals;
auto c=new TCanvas();
c->SetGrid();
// Fill the vectors here
std::ifstream file ("data40Ktest.dat.txt");
if(!file){
cout << "File doesn't exist" << endl;
}
std::string x;
double x2, y, y2;
while(!file.eof()){
file >> x >> y >> x2 >> y2;
x_labels.push_back(x);
y_vals.push_back(y);
y2_vals.push_back(y2);
}
//fill the Graphs
c->cd();
/*TGraph* tg = new TGraph(TMath::Min(y_vals.size(), x_labels.size())); // Create the TGraph object
for (Int_t i = 0; i < TMath::Min(y_vals.size(), x_labels.size()); i++) { // Loop over all entries
tg->SetPoint(i, i + 1., y_vals[i]); // Set The point itself
tg->GetXaxis()->SetBinLabel(tg->GetXaxis()->FindBin(i + 1.), x_labels[i].c_str()); // Find out which bin on the x-axis the point corresponds to and set t
}*/
TGraph* tg2 = new TGraph(TMath::Min(y2_vals.size(), x_labels.size())); // Create the TGraph object
for (Int_t i = 0; i < TMath::Min(y2_vals.size(), x_labels.size()); i++) { // Loop over all entries
tg2->SetPoint(i, i + 1., y2_vals[i]); // Set The point itself
tg2->GetXaxis()->SetBinLabel(tg2->GetXaxis()->FindBin(i + 1.), x_labels[i].c_str()); // Find out which bin on the x-axis the point corresponds to and set
}
TGraph* tg = new TGraph(TMath::Min(y_vals.size(), x_labels.size()));
for (Int_t i = 0; i < tg->GetN(); i++)
tg->SetPoint(i, i + 1., y_vals[i]);
TH1F* h = (TH1F*) tg->GetHistogram()->Clone();
for (Int_t i = 0; i < tg->GetN(); i++)
h->GetXaxis()->SetBinLabel(i + 1, x_labels[i].c_str());
// Draw the plots
tg->SetMarkerStyle(7);
tg2->SetMarkerStyle(8);
tg2->SetMarkerColor(kBlue);
tg2->SetLineColor(kBlue);
tg2->GetYaxis()->SetLabelColor(kBlue);
tg2->GetYaxis()->SetTitleOffset(1.4);
tg2->GetYaxis()->SetTitle("y2-title");
tg->GetYaxis()->SetTitle("y1-title");
tg->GetXaxis()->SetTitle("x1-title");
TPad *pad1 = new TPad("pad1","",0,0,1,1);
TPad *pad2 = new TPad("pad2","",0,0,1,1);
TPad *pad3 = new TPad("pad3","",0,0,1,1);
pad2->SetFillStyle(4000); //will be transparent
pad2->SetFrameFillStyle(0);
pad1->Draw();
pad1->cd();
h->Draw("AXIS");
tg->Draw("ALP");
pad2->Draw();
pad2->cd();
tg2->Draw("ALPY+"); //sets the axis/labels on the opposite side
c->Update();
}
That’s weird. It runs for me… Could you please try it now? newfile.txt (1.0 KB)
void plot(){
std::vector<Double_t> y_vals;
std::vector<std::string> x_labels;
std::vector<Double_t> y2_vals;
auto c=new TCanvas();
c->SetGrid();
// Fill the vectors here
std::ifstream file ("newfile.txt");
if(!file){
cout << "File doesn't exist" << endl;
}
std::string x;
double x2, y, y2;
while(!file.eof()){
file >> x >> y >> x2 >> y2;
x_labels.push_back(x);
y_vals.push_back(y);
y2_vals.push_back(y2);
}
//fill the Graphs
c->cd();
TGraph* tg = new TGraph(TMath::Min(y_vals.size(), x_labels.size())); // Create the TGraph object
for (Int_t i = 0; i < TMath::Min(y_vals.size(), x_labels.size()); i++) { // Loop over all entries
tg->SetPoint(i, i + 1., y_vals[i]); // Set The point itself
tg->GetXaxis()->SetBinLabel(tg->GetXaxis()->FindBin(i + 1.), x_labels[i].c_str()); // Find out which bin on the x-axis the point corresponds to and set t
}
TGraph* tg2 = new TGraph(TMath::Min(y2_vals.size(), x_labels.size())); // Create the TGraph object
for (Int_t i = 0; i < TMath::Min(y2_vals.size(), x_labels.size()); i++) { // Loop over all entries
tg2->SetPoint(i, i + 1., y2_vals[i]); // Set The point itself
tg2->GetXaxis()->SetBinLabel(tg2->GetXaxis()->FindBin(i + 1.), x_labels[i].c_str()); // Find out which bin on the x-axis the point corresponds to and set
}
TH1F* h = (TH1F*) tg->GetHistogram()->Clone();
for (Int_t i = 0; i < tg->GetN(); i++)
h->GetXaxis()->SetBinLabel(i + 1, x_labels[i].c_str());
// Draw the plots
tg->SetMarkerStyle(7);
tg2->SetMarkerStyle(8);
tg2->SetMarkerColor(kBlue);
tg2->SetLineColor(kBlue);
tg2->GetYaxis()->SetLabelColor(kBlue);
tg2->GetYaxis()->SetTitleOffset(1.4);
tg2->GetYaxis()->SetTitle("y2-title");
tg->GetYaxis()->SetTitle("y1-title");
tg->GetXaxis()->SetTitle("x1-title");
TPad *pad1 = new TPad("pad1","",0,0,1,1);
TPad *pad2 = new TPad("pad2","",0,0,1,1);
TPad *pad3 = new TPad("pad3","",0,0,1,1);
pad2->SetFillStyle(4000); //will be transparent
pad2->SetFrameFillStyle(0);
pad1->Draw();
pad1->cd();
tg->Draw("ALP");
h->Draw("AXIS");
pad2->Draw();
pad2->cd();
tg2->Draw("ALPY+"); //sets the axis/labels on the opposite side
c->Update();
}
We already discussed it in previous topic, but I just find it strange, that the helping histogram isn’t drawn properly.
void plot(){
std::vector<Double_t> y_vals;
std::vector<std::string> x_labels;
std::vector<Double_t> y2_vals;
auto c=new TCanvas();
c->SetGrid();
// Fill the vectors here
std::ifstream file ("newfile.txt");
if(!file) cout << "File doesn't exist" << endl;
std::string x;
double x2, y, y2;
while(!file.eof()){
file >> x >> y >> x2 >> y2;
x_labels.push_back(x);
y_vals.push_back(y);
y2_vals.push_back(y2);
}
//fill the Graphs
c->cd();
int n = TMath::Min(y_vals.size(), x_labels.size());
TGraph* tg = new TGraph(n);
for (Int_t i = 0; i <n; i++) tg->SetPoint(i, i + 1., y_vals[i]);
auto h = new TH1F("h","h",n,0,n);
tg->SetHistogram(h);
for (Int_t i = 0; i < n; i++) {
h->GetXaxis()->SetBinLabel(i + 1, x_labels[i].c_str());
}
// Draw the plots
tg->SetMarkerStyle(20);
tg->Draw("ALP");
}