ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/FGolf/Tools/browseStacks.C
Revision: 1.5
Committed: Tue Mar 20 19:04:39 2012 UTC (13 years, 1 month ago) by fgolf
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +0 -0 lines
State: FILE REMOVED
Error occurred while calculating annotation data.
Log Message:
replace .C file with .cc

File Contents

# Content
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 TString outfile, vector<TString> v_legEntries, bool drawLogY = false,
36 vector<Style_t> v_style = vector<Style_t>()) {
37
38
39 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
44 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
49 gStyle->SetOptTitle(0);
50
51
52 // 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
91 for(unsigned int i_prefix = 0; i_prefix < v_samples.size(); i_prefix++) {
92
93 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
103 TH1F *htemp = dynamic_cast<TH1F*>(obj);
104
105 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
114
115 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
145 }
146
147
148 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
167 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
180
181 //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
185
186 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
197
198
199 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
207
208
209 //now we gotta draw, in reverse order
210 for(vector<TH1F*>::reverse_iterator it = v_hists.rbegin(); it != v_hists.rend(); it++) {
211
212 //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
238 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
252
253
254 TPaveText *pt = getPaveText(v_hists, i_channel);
255 pt->Draw();
256
257
258
259
260 }//channel loop
261 c->Modified();
262 c->Update();
263
264 //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
271
272
273
274 }//histos loop
275
276
277
278 }
279
280
281
282
283 double GetMinimum(const vector<TH1F*> &v_hists) {
284
285 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
297 }
298
299
300
301 TLegend* makeLegend(const vector<TH1F*> &v_hists, vector<TString> v_legEntries, bool drawLogY, TString histName) {
302
303 //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
323
324
325 //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
334
335
336 //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
351 //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
366 //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
376 }
377
378 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
396
397
398
399 return leg;
400 }
401
402
403
404
405
406 TPaveText *getPaveText(const vector<TH1F*> &v_hists, int i_channel) {
407
408 if(v_hists.size() == 0)
409 return NULL;
410
411
412 /*
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
424 cout << "lowX, highX: "<< lowX << "," << highX << endl;
425 cout << "lowY, highY: "<< lowY << "," << highY << endl;
426
427 TPaveText *pt1 = new TPaveText(lowX, lowY, highX, highY, "br");
428 */
429
430
431 /*
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
456
457 //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
462
463 pt1->SetName("pt1name");
464 pt1->SetBorderSize(0);
465 pt1->SetFillStyle(0);
466
467
468 TText *blah = pt1->AddText("CMS Preliminary");
469 blah->SetTextSize(0.032);
470 blah->SetTextAlign(11);
471 blah = pt1->AddText("34.85 pb^{-1} at #sqrt{s}=7 TeV");
472 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
486
487 return pt1;
488 }