Overlaying histograms from different macros?

Hi

I know we can overlay many histograms in a single pad/canvas by using ‘Draw(“SAME”)’ option, provided i call all the histograms in the same macro. But say, if i want to overlay two histograms which are initialized and plotted by two different macros, will it be possible I can still overlay them?

Say for example i have a pT distribution of X which is plotted by X.C macro and I have the pT distribution of Y, which is plotted by Y.C macro. If i want to overlay them, can i do something like saving the canvas from macro X.C in some format(say, canvasX.C or canvasX.root or…) and in the Y.C macro is it possible i can call this canvas file and update it with the pT distribution of Y so that i endup overlaying two histograms in a single plot?

Note:
This may sound stupid, but it will be handy for me, because i am plotting 9 efficiency plots(which means i have to call 9 numerator and 9 denominator histograms) in a single canvas and there are 5 different mass points. And i dont want to call all these in a single macro!

[code]{
gStyle->SetOptStat(0);

gSystem->Unlink(“MultiKulti.root”); // make sure the ROOT file is absent

for (Int_t i = 0; i < 9; i++) {
TFile *f = TFile::Open(“MultiKulti.root”, “UPDATE”); // open the ROOT file
TCanvas *c; f->GetObject(“MultiKulti”, c); // get the “old” canvas
if (!c) c = new TCanvas(“MultiKulti”, “MultiKulti”); // no “old” canvas
// c->Draw(); // this line is (sometimes) mandatory (in case of problems :wink:

TH1F *h = new TH1F(TString::Format("h_%d", i),
                   "MultiKulti",
                   300, -3, 3);
h->SetDirectory(gROOT); // don't save it in the ROOT file
h->SetLineColor(i+1);
h->FillRandom("gaus", 20000 * (10 - i));
h->Draw( (i ? "SAME" : "") );

TLegend *l = new TLegend(0.84, 0.8 - 0.0666 * (i + 1),
                         0.99, 0.8 - 0.0666 * i);
l->SetFillColor(c->GetFillColor());
// l->SetBorderSize(1);
l->SetName(TString::Format("%s_legend", h->GetName()));

#if 1 /* 0 or 1 /
l->AddEntry(h, TString::Format(" %s", h->GetName()), “L”);
#else /
0 or 1 /
l->AddEntry(h, TString::Format(" id = %d", i), “L”);
#endif /
0 or 1 */
l->Draw(); // Note: TLegend does NOT have/use/need the “SAME” drawing option

c->Write(); // save the "current" canvas
delete f; // close the ROOT file

}

TFile *f = TFile::Open(“MultiKulti.root”, “READ”);
f->ls();
TCanvas *c; f->GetObject(“MultiKulti”, c);
if © c->Draw();
}[/code]
However, I believe you should consider using the THStack class and its “NOSTACK” drawing option.

Hi Wile,

Thanks, it helped. But i wonder how to draw the legends for the corresponding histograms? I actually tried the same way as the histograms were drawn

but only the last legend of the loop was drawn.
Can you help me on how to handle the legends for this type of plotting? Thanks again.

  • Hari

I modified my example source code so that all legends are also drawn.
I’ve also added now a small trick which ensures that all legends have distinct names (so that afterwards one can “retrieve” all histograms and legends from the canvas, if it’s needed).

ahh!! intersting, I tried exactly the same way previously, except that i used division, i think that was the problem…

Thanks Wile.

root [0] Int_t i = 5
root [1] (i/10)
(Int_t)0
root [2] (i/10.)
(double)5.00000000000000000e-01

Hi Wile,

Pardon me if I am again making some silly mistake somewhere. This time i tried to divide the canvas using Divide funciton, i encountered error

[code]TCanvas *c1; outroot->GetObject(“ptelec”, c1);
if (!c1) c1 = new TCanvas(“ptelec”, “ptelec”);
if(i ==0 ) c1->Divide(2,1);

c1_1->cd();
hnew1->Draw( (i ? “SAME” : “” ) );
l->Draw((i ? “SAME” : “” ));

c1_2->cd();
hnew2->Draw( (i ? “SAME” : “” ) );
l->Draw((i ? “SAME” : “” ));[/code]
i got this error

Error: Symbol c1_1 is not defined in current scope plotter_pt_elec.C:91: Error: Failed to evaluate c1_1->cd() *** Interpreter error recovered ***

I also checked it without that if(i==0) condition. Still getting the same error.

Instead of “c1_1->cd();” and “c1_2->cd();” use “c1->cd(1);” and “c1->cd(2);”.

BTW. I hope you understand now why your “(i/10)” failed.

ya, i think i do. It because if there is no ‘dot’ at the end of a number ROOT will round it to an integer. I can tell ROOT that i am doing floating point arithmetic by using ‘dot’ at the end.

I tried c1->cd(1), now i have the canvas divided, but, it does not plot all the histograms. It is plotting only the first histogram in the loop. It is as if, the loop is run only for it first entry!

How about: if (!c1) { c1 = new TCanvas("ptelec", "ptelec"); c1->Divide(2,1); }

Hi Wile,

Still the same! :frowning:

Hi Wile,

Any other suggestions??

well if You change using cd(2) for iterator bigger than 0 and then You are trying with Draw( (i ? “SAME” : “” ) ); then You are drawing using SAME option even for the first histogram at that canvas part… that has a tendency not to work You know…

Hi Standa,

I am not sure i am getting this.

[code]if (!c1) { c1 = new TCanvas(“ptelec”, “ptelec”);
c1->Divide(2,1); }

if(i == 0) {
c1->cd(1);
hnew1->Draw( );
l->Draw();

c1->cd(2);
hnew2->Draw( );
l->Draw();
}

else{

c1->cd(1);
hnew1->Draw( “SAME” );
l->Draw(“SAME” );

c1->cd(2);
hnew2->Draw( “SAME” );
l->Draw(“SAME”);
}[/code]
I tried this way. I am just getting the first histogram in the loop on the corresponding pads.

Hi Wile and Standa,

I declared the TCanvas outside the for loop and invoked no .root files. This time i directly draw the histograms and not storing them in a root file. This works!

Thanks

[code]{
gStyle->SetOptStat(0);

gSystem->Unlink(“MultiKulti.root”); // make sure the ROOT file is absent

for (Int_t i = 0; i < 9; i++) {
TFile *f = TFile::Open(“MultiKulti.root”, “UPDATE”); // open the ROOT file
TCanvas *c; f->GetObject(“MultiKulti”, c); // get the “old” canvas
if (!c) {
c = new TCanvas(“MultiKulti”, “MultiKulti”); // no “old” canvas
c->Divide(2, 1);
} else c->Draw(); // THIS LINE IS MANDATORY HERE!

TH1F *h = new TH1F(TString::Format("h_%d", i),
                   "MultiKulti",
                   300, -3, 3);
h->SetDirectory(gROOT); // don't save it in the ROOT file
h->SetLineColor(i+1);
h->FillRandom("gaus", 20000 * (10 - i));
c->cd( ((i % 2) ? 2 : 1) ); // 2 = ODD numbers, 1 = EVEN numbers
h->Draw( ((i > 1) ? "SAME" : "") );

TLegend *l = new TLegend(0.84, 0.8 - 0.0666 * (i + 1),
                         0.99, 0.8 - 0.0666 * i);
l->SetFillColor(c->GetFillColor());
// l->SetBorderSize(1);
l->SetName(TString::Format("%s_legend", h->GetName()));

#if 0 /* 0 or 1 /
l->AddEntry(h, TString::Format(" %s", h->GetName()), “L”);
#else /
0 or 1 /
l->AddEntry(h, TString::Format(" id = %d", i), “L”);
#endif /
0 or 1 */
c->cd( ((i % 2) ? 2 : 1) ); // 2 = ODD numbers, 1 = EVEN numbers
l->Draw(); // Note: TLegend does NOT have/use/need the “SAME” drawing option

c->cd(0);
c->Write(); // save the "current" canvas
delete f; // close the ROOT file

}

TFile *f = TFile::Open(“MultiKulti.root”, “READ”);
f->ls();
TCanvas *c; f->GetObject(“MultiKulti”, c);
if © c->Draw();
}[/code]

Hi Wile,

Thanks, it did work! :slight_smile:

Just to make sure I understood this. Previously without the

line, when the loop runs for its non-first elements, it does not call c1 in order to draw the subsequent histograms! That is the reason I got only the first histogram plotter. Is that right?

  • Hari

To me this seems to be a “bug” in ROOT, but I’m sure other people will prefer to call it a “feature”. :wink:
Anyhow, the “brutal fix” is to make sure that the canvas is drawn in each iteration (for the first time when it gets created with a “new”, it will be drawn automatically, but later we need to draw it “manually”).
Note also that many ROOT objects, including the TLegend, do not have/use/need the “SAME” drawing option. If you try to draw such an object with “SAME”, you may get “unexpected” results -> for example such an object may have separate “S”, “A”, “M”, “E” drawing flags … and you will get it drawn with all of them “switched on”. :mrgreen: