ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/FGolf/Tools/browseStacks.C
Revision: 1.4
Committed: Fri Mar 18 20:51:50 2011 UTC (14 years, 1 month ago) by fgolf
Content type: text/plain
Branch: MAIN
CVS Tags: ss_summer2011approvalV2, ss_summer2011approval, synchMay2011v1, ss20May2011
Changes since 1.3: +1 -1 lines
Log Message:
update for 35/pb

File Contents

# User Rev Content
1 fgolf 1.1 #include "TH1.h"
2     #include "TH2.h"
3     #include "THStack.h"
4     #include "TRegexp.h"
5     #include "TROOT.h"
6     #include "TCanvas.h"
7     #include "TObjArray.h"
8     #include "TLegend.h"
9     #include "TPaveText.h"
10     #include "TText.h"
11     #include "TString.h"
12     #include "TStyle.h"
13     #include <iostream>
14     #include <algorithm>
15     #include <set>
16    
17     #include "getMyHistosNames.C"
18     #include "histtools.C"
19    
20     using namespace std;
21    
22     // Make the stacks and then browse them interactive
23     // if (makePictures==true), saves all plots to out/stacks.ps
24     // Also: make out_stacks_xx.png where xx is the page number
25     // on the stack.ps file
26     //
27     // keep2D=false to skip the annoying 2D histograms
28     //
29    
30    
31     double GetMinimum(const vector<TH1F*> &v_hists);
32     TLegend* makeLegend(const vector<TH1F*> &v_hists, vector<TString> v_legEntries, bool drawLogY, TString histName);
33     TPaveText *getPaveText(const vector<TH1F*> &v_hists, int i_channel); //call this after makeLegend please
34     void browseStacks(vector<TString> v_samples, vector<Color_t> v_colors,
35 fgolf 1.3 TString outfile, vector<TString> v_legEntries, bool drawLogY = false,
36     vector<Style_t> v_style = vector<Style_t>()) {
37 fgolf 1.1
38    
39 fgolf 1.3 if(v_samples.size() != v_colors.size()) {
40     cout << "Number of entries in the vector of samples is not the same as the number of entries in the vector of Color_t" << endl;
41     return;
42     }
43 fgolf 1.1
44 fgolf 1.3 if(v_style.size()!=0 && v_style.size() != v_colors.size()) {
45     cout << "Number of entries in the vector of styles is not the same as the number of entries in the vector of samples" << endl;
46     return;
47     }
48 fgolf 1.1
49 fgolf 1.3 gStyle->SetOptTitle(0);
50 fgolf 1.1
51    
52 fgolf 1.3 // Find out what the names of the existing histograms are
53     // The histogram names are XX_YY_ZZ, where XX is the sample,
54     // eg, "tt", YY is the actual name, ZZ is the final state, eg, "ee"
55     //exclude data if it is found
56     bool keep2D = false;
57     TObjArray* myNames = getMyHistosNames(v_samples.at(0).Data(),"ee",keep2D);
58     if(myNames->GetSize() == 0) {
59     cout << "could not find the sample at the first point in the vector of samples. Exiting." << endl;
60     return;
61     }
62     /*
63     // debugging code to see what's in myNames
64     std::cout << "Processing the following histograms: ";
65     for (unsigned int i = 0; i < myNames->GetEntries(); i++)
66     {
67     if (i > 0)
68     std::cout << ", ";
69     else
70     std::cout << "";
71    
72     std::cout << myNames->At(i)->GetName();
73     }
74    
75     std::cout << std::endl;
76     std::cout.flush();
77     */
78     // Now loop over histograms, and make stacks
79     TCanvas *c = new TCanvas();
80     c->Divide(2,2);
81     vector<string> v_channel;
82     v_channel.push_back("ee");
83     v_channel.push_back("mm");
84     v_channel.push_back("em");
85     v_channel.push_back("all");
86     for (int i=0; i<myNames->GetEntries(); i++) {
87     for (int i_channel=0; i_channel<4; i_channel++) {
88     vector<TH1F*> v_hists;
89     TH1F *hdata = NULL;
90 fgolf 1.2
91 fgolf 1.3 for(unsigned int i_prefix = 0; i_prefix < v_samples.size(); i_prefix++) {
92 fgolf 1.1
93 fgolf 1.3 TString histoName = v_samples.at(i_prefix) + "_" + myNames->At(i)->GetName() + "_" + v_channel.at(i_channel);
94     /*
95     std::cout << "processing histogram " << histoName.Data() << std::endl;
96     if (histoName.Contains("data_hbTagsimpleSecVtxHighEff"))
97     gDirectory->Print("*bTag*");
98     */
99     TObject *obj = gDirectory->Get(histoName.Data());
100     if (!obj->InheritsFrom(TH1::Class()))
101     continue;
102 fgolf 1.1
103 fgolf 1.3 TH1F *htemp = dynamic_cast<TH1F*>(obj);
104 fgolf 1.1
105 fgolf 1.3 htemp->SetFillColor(v_colors.at(i_prefix));
106     htemp->SetLineColor(kBlack);
107     TString plot(myNames->At(i)->GetName());
108     if(plot.Contains("hnJet") ||
109     plot.Contains("htcmet") ||
110     plot.Contains("bTag") ||
111     plot.Contains("dilMass") ||
112     plot.Contains("hpfmet")) {
113 fgolf 1.1
114    
115 fgolf 1.3 string xtitle;
116     string ytitle;
117     if(plot.Contains("hnJet")) {
118     xtitle = "Number of jets";
119     ytitle = "Events";
120     } else if(plot.Contains("htcmet")) {
121     //xtitle = "Missing transverse energy [GeV]";
122     xtitle = "tc Missing transverse energy [GeV]";
123     ytitle = "Events/(10 GeV)";
124     } else if(plot.Contains("hpfmet")) {
125     xtitle = "PF Missing transverse energy [GeV]";
126     ytitle = "Events/(10 GeV)";
127     } else if(plot.Contains("bTag")) {
128     xtitle = "Number of b-tagged jets";
129     ytitle = "Events";
130     const char *jetbins[4] = {"0", "1", "2", "#geq 3"};
131     for(int k = 0; k<4; k++)
132     htemp->GetXaxis()->SetBinLabel(k+1, jetbins[k]);
133     htemp->GetXaxis()->SetLabelSize(0.07);
134    
135     } else if(plot.Contains("dilMass")) {
136     xtitle = "Dilepton mass [GeV/c^{2}]";
137     ytitle = "Events/(5 GeV/c^{2})";
138     }
139     htemp->GetXaxis()->SetTitle(xtitle.c_str());
140     htemp->GetYaxis()->SetTitle(ytitle.c_str());
141     htemp->GetYaxis()->SetTitleOffset(1.5);
142     htemp->GetXaxis()->SetTitleSize(0.045);
143     htemp->GetYaxis()->SetTitleSize(0.045);
144 fgolf 1.1
145 fgolf 1.3 }
146 fgolf 1.1
147    
148 fgolf 1.3 if(v_style.size() > 0) {
149     htemp->SetFillStyle(v_style.at(i_prefix));
150     if(v_samples.at(i_prefix) == "data") {
151     htemp->SetMarkerStyle(v_style.at(i_prefix));
152     htemp->SetMarkerColor(v_colors.at(i_prefix));
153     }
154     }
155    
156     //don't add the data histogram to the stack
157     if(v_samples.at(i_prefix) == "data") {
158     hdata = htemp;
159     continue;
160     }
161    
162     if(i_prefix==0) {
163     v_hists.push_back(htemp);
164     continue;
165     }
166 fgolf 1.1
167 fgolf 1.3 htemp->Add(v_hists.back());
168     v_hists.push_back(htemp);
169     }//prefix loop
170     if(hdata != NULL)
171     v_hists.push_back(hdata);
172    
173     c->cd(i_channel+1);
174    
175     //now set the Minimum if we want Log Scale
176     float min = 0;
177     if(drawLogY && i_channel != 2)
178     min = GetMinimum(v_hists);
179 fgolf 1.1
180    
181 fgolf 1.3 //set the minimum, before we pass the vector of hists to the legend function
182     for(vector<TH1F*>::iterator it = v_hists.begin(); it != v_hists.end(); it++)
183     (*it)->SetMinimum(min);
184 fgolf 1.1
185    
186 fgolf 1.3 TLegend *leg = NULL;
187     if(i_channel == 3) {
188     leg = makeLegend(v_hists, v_legEntries, drawLogY, TString(myNames->At(i)->GetName()));
189    
190     } else {
191     float max = 0;
192     for(vector<TH1F*>::iterator it = v_hists.begin(); it != v_hists.end(); it++) {
193     if((*it)->GetMaximum() > max)
194     max = (*it)->GetMaximum();
195     }
196 fgolf 1.1
197    
198    
199 fgolf 1.3 for(vector<TH1F*>::iterator it = v_hists.begin(); it != v_hists.end(); it++) {
200     if(drawLogY && i_channel != 2 )
201     (*it)->SetMaximum(50*max);
202     else
203     (*it)->SetMaximum(1.5*max);
204     }
205     }
206 fgolf 1.1
207    
208    
209 fgolf 1.3 //now we gotta draw, in reverse order
210     for(vector<TH1F*>::reverse_iterator it = v_hists.rbegin(); it != v_hists.rend(); it++) {
211 fgolf 1.1
212 fgolf 1.3 //do not draw if the histogram is empty...1e-6 should be good enough
213     if(drawLogY && (*it)->GetMaximum() < 1e-6)
214     continue;
215    
216     if(i_channel == 3) {
217     float max = 1.1*leg->GetY2();
218     if(drawLogY)
219     max = 5*leg->GetY2();
220     if(v_hists.back()->GetMaximum() < max)
221     (*it)->SetMaximum(max);
222     }
223    
224     if(TString((*it)->GetName()).Contains("data")) {
225     hdata = (*it);
226     if(it == v_hists.rbegin())
227     (*it)->Draw("Pe");
228     else
229     (*it)->Draw("Pesame");
230     } else {
231     if(it == v_hists.rbegin())
232     (*it)->Draw("hist");
233     else
234     (*it)->Draw("histsame");
235     }
236     }
237 fgolf 1.1
238 fgolf 1.3 if(hdata != NULL) {
239     hdata->Draw("Pesame");
240     }
241    
242     gPad->RedrawAxis();
243     if(i_channel == 3)
244     leg->Draw();
245    
246     //need to draw the first histogram in the stack again, because of the tickmarks
247    
248     //now set the Log scale, if desired
249     if(drawLogY && i_channel!=2)
250     gPad->SetLogy(1);
251 fgolf 1.1
252    
253    
254 fgolf 1.3 TPaveText *pt = getPaveText(v_hists, i_channel);
255     pt->Draw();
256 fgolf 1.1
257    
258    
259    
260 fgolf 1.3 }//channel loop
261     c->Modified();
262     c->Update();
263 fgolf 1.1
264 fgolf 1.3 //cout << myNames->At(i)->GetName() << endl;
265     TString tempstring = outfile.ReplaceAll(".root", "");
266     if(i != myNames->GetEntries() - 1)
267     c->Print((tempstring + ".eps(").Data());
268     else
269     c->Print((tempstring + ".eps)").Data());
270 fgolf 1.1
271    
272    
273    
274 fgolf 1.3 }//histos loop
275 fgolf 1.1
276    
277    
278     }
279    
280    
281    
282    
283     double GetMinimum(const vector<TH1F*> &v_hists) {
284    
285 fgolf 1.3 TH1* h = NULL; //get the first non-empty histogram
286     for(unsigned int i = 0; v_hists.size(); i++) {
287     h = v_hists.at(i);
288     if(h->Integral() > 0)
289     break;
290     }
291     if(h->GetMinimum() < 5e-3)
292     return 5e-3;
293     else
294     return
295     0.5*(h->GetMinimum());
296 fgolf 1.1
297     }
298    
299    
300    
301     TLegend* makeLegend(const vector<TH1F*> &v_hists, vector<TString> v_legEntries, bool drawLogY, TString histName) {
302    
303 fgolf 1.3 //Prefer to draw the Legend on the right half of the
304     //canvas, so only look at the right half
305     int nbins = v_hists.at(0)->GetNbinsX();
306     TH1F *hdata = NULL;
307     TH1F *hmax = NULL;
308    
309     for(vector<TH1F*>::const_reverse_iterator rit = v_hists.rbegin(); rit != v_hists.rend(); rit++) {
310     if(TString((*rit)->GetName()).Contains("data")) {
311     hdata = *rit;
312     break;
313     }
314     }
315    
316     for(vector<TH1F*>::const_reverse_iterator rit = v_hists.rbegin(); rit != v_hists.rend(); rit++) {
317     if(TString((*rit)->GetName()).Contains("data"))
318     continue;
319     hmax = *rit;
320     break;
321     }
322 fgolf 1.1
323    
324    
325 fgolf 1.3 //want the legend to be on the right
326     //start with the last but 1 bin, and let this be the highX bin
327     //skip the last bin 'cause it has the overflow
328     float rangeX = hmax->GetXaxis()->GetXmax() - hmax->GetXaxis()->GetXmin() - hmax->GetBinWidth(nbins);
329     int highBinX = nbins - 1;
330     float highX = hmax->GetBinLowEdge(nbins) - 0.01*rangeX;
331     float lowX = hmax->GetXaxis()->GetXmin() + 0.75*rangeX;
332     int lowBinX = hmax->FindBin(lowX);
333 fgolf 1.1
334    
335    
336 fgolf 1.3 //now we need to figure out what the maxY is in the range
337     //and set the Y's of the legend to accomodate
338     float max = 1e-6;
339     float lowY, highY;
340     float rangeY = hmax->GetYaxis()->GetXmax() - hmax->GetYaxis()->GetXmin();
341     for(int bin = lowBinX; bin < highBinX+1; bin++) {
342     if(hmax->GetBinContent(bin) >= hdata->GetBinContent(bin)) {
343     if(max < hmax->GetBinContent(bin))
344     max = hmax->GetBinContent(bin);
345     } else {
346     if(max < hdata->GetBinContent(bin))
347     max = hdata->GetBinContent(bin);
348     }
349     }
350 fgolf 1.1
351 fgolf 1.3 //cout << "max: " << max << endl;
352     rangeY = hdata->GetMinimum();
353     if(hdata->GetMaximum() > hmax->GetMinimum())
354     rangeY = hdata->GetMaximum() - rangeY;
355     else
356     rangeY = hmax->GetMaximum() - rangeY;
357    
358     if(drawLogY) {
359     lowY = 5*max;
360     highY = lowY + 10*rangeY;
361     } else {
362     lowY = 1.2*max;
363     highY = lowY + 0.3*rangeY;
364     }
365 fgolf 1.1
366 fgolf 1.3 //cout << "lowY, highY: "<< lowY << "," << highY << endl;
367     TLegend *leg;
368     if(drawLogY)
369     leg = new TLegend(lowX,lowY,highX,highY, "", "br");
370     else
371     leg = new TLegend(0.7, 0.58, 0.95, 0.92, "", "brNDC");
372     if((histName.Contains("nJet") || histName.Contains("bTag")) && drawLogY) {
373     int temp = hdata->GetNbinsX();
374     leg = new TLegend(hdata->GetNbinsX()-1.1, lowY, temp - 0.05*hdata->GetBinWidth(temp), highY, "", "br");
375 fgolf 1.1
376 fgolf 1.3 }
377 fgolf 1.1
378 fgolf 1.3 leg->SetFillColor(kWhite);
379     leg->SetBorderSize(0);
380     leg->SetFillStyle(1001);
381    
382     if(v_hists.size() != v_legEntries.size()) {
383     cout << "the number of entries in the legend vector are not the same as the number"
384     << " of entries in the hists vector. Returning a null TLegend. " << endl;
385     return NULL;
386     }
387     vector<TH1F*>::const_reverse_iterator ritH = v_hists.rbegin();
388     vector<TString>::const_reverse_iterator ritE = v_legEntries.rbegin();
389     for(; ritH != v_hists.rend(); ritH++, ritE++) {
390     if(*ritE == "Data")
391     leg->AddEntry(*ritH, *ritE, "P");
392     else
393     leg->AddEntry(*ritH, *ritE, "f");
394     }
395 fgolf 1.1
396    
397    
398    
399 fgolf 1.3 return leg;
400 fgolf 1.1 }
401    
402    
403    
404    
405    
406     TPaveText *getPaveText(const vector<TH1F*> &v_hists, int i_channel) {
407    
408 fgolf 1.3 if(v_hists.size() == 0)
409     return NULL;
410 fgolf 1.1
411    
412 fgolf 1.3 /*
413     //all the histograms should have the same Y range
414     TH1F *temp = dynamic_cast<TH1F*>(v_hists.at(0)->Clone());
415     float lowX, lowY;
416     float highX, highY;
417     float rangeX = temp->GetXaxis()->GetXmax() - temp->GetXaxis()->GetXmin();
418     float rangeY = temp->GetMaximum() - temp->GetMinimum();
419     lowX = temp->GetXaxis()->GetXmin() + 0.05*rangeX;
420     highX = lowX + 0.2*rangeX;
421     lowY = temp->GetMinimum() + 0.85*rangeY;
422     highY = temp->GetMinimum() + 0.98*rangeY;
423 fgolf 1.1
424 fgolf 1.3 cout << "lowX, highX: "<< lowX << "," << highX << endl;
425     cout << "lowY, highY: "<< lowY << "," << highY << endl;
426 fgolf 1.1
427 fgolf 1.3 TPaveText *pt1 = new TPaveText(lowX, lowY, highX, highY, "br");
428     */
429 fgolf 1.1
430    
431 fgolf 1.3 /*
432     //used for iso, id plots
433     TPaveText *pt1 = new TPaveText(0.3, 0.77, 0.5, 0.90, "brNDC");
434     if(i_channel == 2) {
435     pt1 = new TPaveText(0.62, 0.77, 0.82, 0.90, "brNDC");
436     }
437     */
438    
439    
440     /*
441     //for full analysis cut plots
442     TPaveText *pt1 = new TPaveText(0.20, 0.77, 0.40, 0.90, "brNDC");
443     if(i_channel == 2) {
444     pt1 = new TPaveText(0.58, 0.77, 0.78, 0.90, "brNDC"); //used for iso, id plots
445     }
446     */
447    
448    
449     /*
450     //for the NJet plot, after the Z veto and the met cut
451     TPaveText *pt1 = new TPaveText(0.25, 0.77, 0.45, 0.90, "brNDC");
452     if(i_channel != 3)
453     pt1 = new TPaveText(0.62, 0.77, 0.82, 0.90, "brNDC");
454     */
455 fgolf 1.1
456    
457 fgolf 1.3 //for the MET plot, after the Zveto and the 2jet cut
458     TPaveText *pt1 = new TPaveText(0.62, 0.77, 0.82, 0.90, "brNDC");
459     if(i_channel == 3)
460     pt1 = new TPaveText(0.2, 0.77, 0.4, 0.90, "brNDC");
461 fgolf 1.1
462    
463 fgolf 1.3 pt1->SetName("pt1name");
464     pt1->SetBorderSize(0);
465     pt1->SetFillStyle(0);
466 fgolf 1.1
467    
468 fgolf 1.3 TText *blah = pt1->AddText("CMS Preliminary");
469     blah->SetTextSize(0.032);
470     blah->SetTextAlign(11);
471 fgolf 1.4 blah = pt1->AddText("34.85 pb^{-1} at #sqrt{s}=7 TeV");
472 fgolf 1.3 blah->SetTextSize(0.032);
473     blah->SetTextAlign(11);
474    
475     if(i_channel==0)
476     blah = pt1->AddText("Events with ee");
477     if(i_channel == 1)
478     blah = pt1->AddText("Events with #mu#mu");
479     if(i_channel == 2)
480     blah = pt1->AddText("Events with e#mu");
481     if(i_channel == 3)
482     blah = pt1->AddText("Events with ee/#mu#mu/e#mu");
483     blah->SetTextSize(0.032);
484     blah->SetTextAlign(11);
485 fgolf 1.1
486    
487 fgolf 1.3 return pt1;
488 fgolf 1.1 }