ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/UHHAnalysis/SFramePlotter/SPlotter.cxx
Revision: 1.2
Committed: Mon Nov 12 13:26:25 2012 UTC (12 years, 5 months ago) by peiffer
Content type: text/plain
Branch: MAIN
Changes since 1.1: +8 -0 lines
Log Message:
lumibin plots

File Contents

# User Rev Content
1 rkogler 1.1 #include <iostream>
2     #include <iomanip>
3    
4     #include <TObjArray.h>
5     #include <TObjString.h>
6     #include <TStyle.h>
7     #include <TROOT.h>
8     #include <TPaveText.h>
9     #include <TLegend.h>
10     #include <TLegendEntry.h>
11     #include <TLatex.h>
12     #include "SPlotter.h"
13    
14     using namespace std;
15    
16     SPlotter::SPlotter()
17     {
18     m_can = NULL;
19     m_ps = NULL;
20     m_ps_name = "default.ps";
21    
22     m_pad1 = NULL;
23     m_rp1 = NULL;
24     m_pad2 = NULL;
25     m_rp2 = NULL;
26    
27     m_page = 0;
28     debug = false;
29     bShapeNorm = false;
30     bPortrait = true;
31     bDrawEntries = false;
32     bDrawLumi = true;
33     bDrawLegend = true;
34     bPlotRatio = false;
35     need_update = true;
36    
37     }
38    
39     SPlotter::~SPlotter()
40     {
41     Cleanup();
42     }
43    
44     void SPlotter::SetPsFilename(TString name)
45     {
46     if (!name.EndsWith(".ps")){
47     cerr << "SPlotter::SetPsFilename, given filename: " << name
48     << " does not end with .ps, intention? Please correct steering." << endl;
49     exit(EXIT_FAILURE);
50     }
51     m_ps_name = name;
52    
53     }
54    
55     void SPlotter::DoStacking(vector<TObjArray*>& hists, TObjArray* StackNames)
56     {
57     if (hists.size()==0){
58     cerr << "SPlotter::DoStacking: Empty array of histograms. Aborting." << endl;
59     exit(EXIT_FAILURE);
60     }
61    
62     if (!StackNames){ // trivial case: do nothing
63     return;
64     }
65    
66     // loop over all histogram arrays
67     int narr = hists.size();
68     for (int i=narr-1; i>=0; --i){
69     TObjArray* ha = hists[i];
70     if (ha->GetEntries()<1) continue;
71     TString proc = ((SHist*)ha->At(0))->GetProcessName();
72     if (debug) cout << "SPlotter::DoStacking, hist array = " << i
73     << " process name = " << proc << endl;
74    
75     // loop over all stack-names
76     for (int j=0; j<StackNames->GetEntries(); ++j){
77     TString sname = ((TObjString*)StackNames->At(j))->GetString();
78     if (debug) cout << " stack name = " << sname << endl;
79     if (proc.Contains(sname)){
80     if (debug) cout << " -> found match, stacking this array." << endl;
81     StackHists(hists, i);
82     break;
83     }
84     }
85     }
86    
87     if (debug) cout << "SPlotter::DoStacking: Done." << endl;
88    
89     return;
90    
91     }
92    
93     void SPlotter::StackHists(std::vector<TObjArray*>& hists, int index)
94     {
95     // stack histograms at position 'index' with an existing array of stacks
96     // in hists
97     // if the stacks don't exist, they are created and added to the array
98    
99     // get the stack (create a new one if it doesn't exist yet)
100     TObjArray* stacks = GetStacks(hists, index);
101    
102     // add the histograms at 'index' to the stack
103     for (int i=0; i<stacks->GetEntries(); ++i){
104     SHist* stack = (SHist*)stacks->At(i);
105     SHist* hist = (SHist*)hists[index]->At(i);
106     if (!stack || !hist){
107     cerr << "SPlotter::StackHists: stack or hist at position " << i
108     << " does not exist! Abort." << endl;
109     exit(EXIT_FAILURE);
110     }
111     // sanity check: compare names
112     TString stackname = stack->GetStack()->GetName();
113     TString histname = hist->GetHist()->GetName();
114     if (!stackname.Contains(histname)){
115     cerr << "SPlotter::StackHists: incompatible histograms at position " << i
116     << ", stackname = " << stackname << " histname = " << histname
117     << ". Prefer to exit because of consistency." << endl;
118     exit(EXIT_FAILURE);
119     }
120     // still here? do the stackin'!
121     hist->GetHist()->SetFillColor(hist->GetHist()->GetLineColor());
122     hist->GetHist()->SetFillStyle(1001);
123     stack->GetStack()->Add(hist->GetHist());
124     hist->SetIsUsedInStack(true);
125     hist->SetDoDraw(false);
126     if (debug) cout << "stacking hist " << histname << " on " << stackname
127     << " (dir = " << stack->GetDir() << ")" << endl;
128     }
129    
130     return;
131    
132     }
133    
134     TObjArray* SPlotter::GetStacks(std::vector<TObjArray*>& hists, int index)
135     {
136     // get the array of stacks from the input hists
137     // if it doesn't exist, a new array will be created if index>0
138     // and the hists at position 'index' will be used as blue-print
139    
140     // try to find a stack in the array
141     TObjArray* arr = NULL;
142     int narr = hists.size();
143     for (int i=0; i<narr; ++i){
144     if (hists[i]->GetEntries()==0){
145     cerr << "SPlotter::GetStacks: Got no histograms in array " << i
146     << " unexpected behaviour - abort." << endl;
147     exit(EXIT_FAILURE);
148     }
149    
150     arr = hists[i];
151     SHist* sh = (SHist*) arr->At(i);
152     if (sh->IsStack()){
153     if (debug) cout << "SPlotter::GetStacks: Found stack at position " << i << endl;
154     return arr;
155     }
156     }
157    
158     // no stack found, create a new array with THStacks -> use position 'index'
159     // in the array as a blue-print
160     if (index>-1){
161     if (debug) cout << "SPlotter::GetStacks: Creating new array of THStacks "
162     << "using position " << index << " as blueprint." << endl;
163     if (index>narr){
164     cerr << "SPlotter::GetStacks: Can not create an array of stacks from array"
165     << " index " << index << ", since size is only " << hists.size()
166     << ". Unexpected behaviour - abort." << endl;
167     exit(EXIT_FAILURE);
168     }
169    
170     arr = new TObjArray();
171     for (int i=0; i<hists[index]->GetEntries();++i){
172     TString hname = ((SHist*)hists[index]->At(i))->GetHist()->GetName();
173     TString name = hname + "_stack";
174     THStack* st = new THStack(name, "");
175     SHist* sh = new SHist(st);
176     sh->SetDir(((SHist*)hists[index]->At(i))->GetDir());
177     sh->SetProcessName("SM");
178     sh->SetDoDraw(true);
179     arr->Add(sh);
180     if (debug) cout << "SPlotter::GetStacks: Adding stack with name " << name
181     << " in directory " << sh->GetDir() << " at position " << i << endl;
182     }
183    
184     hists.push_back(arr);
185     if (debug) cout << "SPlotter::GetStacks: Added stack array to collection. "
186     << "New size = " << hists.size() << ", old = " << narr << endl;
187     }
188    
189     return arr;
190    
191     }
192    
193     void SPlotter::CopyStyle(TH1& h1, TH1* h2)
194     {
195     // copy the style from hist2 to hist1
196     h1.SetMarkerStyle(h2->GetMarkerStyle());
197     h1.SetMarkerSize(h2->GetMarkerSize());
198     h1.SetMarkerColor(h2->GetMarkerColor());
199     h1.SetLineWidth(h2->GetLineWidth());
200     h1.SetLineStyle(h2->GetLineStyle());
201     h1.SetLineColor(h2->GetLineColor());
202     h1.SetFillColor(h2->GetFillColor());
203     return;
204     }
205    
206     void SPlotter::SetupGlobalStyle()
207     {
208     // general appearance and style
209    
210     gROOT->SetStyle("Plain");
211     gStyle->SetOptStat(0);
212     gStyle -> SetPadTickX(1);
213     gStyle -> SetPadTickY(1);
214    
215     gStyle->SetPadBorderMode(0);
216     gStyle->SetPadColor(kWhite);
217     gStyle->SetPadGridX(false);
218     gStyle->SetPadGridY(false);
219     gStyle->SetGridColor(0);
220     gStyle->SetGridStyle(3);
221     gStyle->SetGridWidth(1);
222    
223     gStyle->SetFrameBorderMode(0);
224     gStyle->SetFrameBorderSize(1);
225     gStyle->SetFrameFillColor(0);
226     gStyle->SetFrameFillStyle(0);
227     gStyle->SetFrameLineColor(1);
228     gStyle->SetFrameLineStyle(1);
229     gStyle->SetFrameLineWidth(1);
230    
231     gStyle->SetTitleFont(42, "XYZ");
232     gStyle->SetLabelFont(42, "XYZ");
233    
234     gStyle->SetAxisColor(1, "XYZ");
235     gStyle->SetStripDecimals(kTRUE);
236     gStyle->SetTickLength(0.03, "XYZ");
237     gStyle->SetNdivisions(510, "XYZ");
238    
239     gStyle->UseCurrentStyle();
240    
241     }
242    
243     void SPlotter::Cleanup()
244     {
245     // do what the name suggests
246    
247     ClosePostscript();
248     if (m_can){
249     delete m_can;
250     m_can = NULL;
251     }
252     }
253    
254     void SPlotter::SetupCanvas()
255     {
256     // set up a canvas, different possibilities
257     // to take into account portrait/landscape
258     // and ratio/no ratio plots
259    
260     Int_t CanWidth;
261     Int_t CanHeight;
262     if (bPortrait){
263     CanWidth = 600;
264     CanHeight = 830;
265     } else {
266     CanWidth = 800;
267     CanHeight = 600;
268     }
269    
270     // set up the canvas
271     m_can = new TCanvas("canvas","Control Plots", CanWidth, CanHeight);
272    
273     Float_t yplot = 0.3;
274     Float_t yratio = 0.17;
275    
276     // coordinates:
277     //
278     // set up the coordinates of the two pads: // y6 +-------------+
279     Float_t y1, y2, y3, y4, y5, y6; // | |
280     y6 = 0.97; // | pad1 |
281     y5 = y6-yplot; // y5 |-------------|
282     y4 = y5-yratio; // | rp1 |
283     y3 = 0.49; // y4 +-------------+
284     y2 = y3-yplot; //
285     y1 = y2-yratio; // y3 +-------------+
286     Float_t x1, x2; // | |
287     x1 = 0.01; // | pad2 |
288     x2 = 0.99; // y2 |-------------|
289     // | rp2 |
290     // y1 +-------------+
291     // x1 x2
292    
293    
294     if (bPlotRatio){
295    
296     m_pad1 = new TPad("pad1", "Control Plots 1", x1, y5, x2, y6);
297     m_rp1 = new TPad("rp1", "Ratio1", x1, y4, x2, y5);
298    
299     m_pad2 = new TPad("pad2", "Control Plots 2", x1, y2, x2, y3);
300     m_rp2 = new TPad("rp2", "Ratio2", x1, y1, x2, y2);
301    
302     } else {
303    
304     m_pad1 = new TPad("pad1", "Control Plots 1", x1, y4, x2, y6);
305     m_pad2 = new TPad("pad2", "Control Plots 2", x1, y1, x2, y3);
306    
307     }
308    
309     // set margins for portrait mode
310     if (bPortrait){
311    
312     m_pad1->SetTopMargin(0.05); m_pad1->SetBottomMargin(0.13); m_pad1->SetLeftMargin(0.19); m_pad1->SetRightMargin(0.05);
313     m_pad2->SetTopMargin(0.05); m_pad2->SetBottomMargin(0.13); m_pad2->SetLeftMargin(0.19); m_pad2->SetRightMargin(0.05);
314     if (bPlotRatio){
315     m_pad1->SetTopMargin(0.02); m_pad1->SetBottomMargin(0.0); m_pad1->SetLeftMargin(0.19); m_pad1->SetRightMargin(0.05);
316     m_pad2->SetTopMargin(0.02); m_pad2->SetBottomMargin(0.0); m_pad2->SetLeftMargin(0.19); m_pad2->SetRightMargin(0.05);
317     m_rp1->SetTopMargin(0.0); m_rp1->SetBottomMargin(0.35); m_rp1->SetLeftMargin(0.19); m_rp1->SetRightMargin(0.05);
318     m_rp2->SetTopMargin(0.0); m_rp2->SetBottomMargin(0.35); m_rp2->SetLeftMargin(0.19); m_rp2->SetRightMargin(0.05);
319     }
320    
321     // margins for landscape
322     } else {
323    
324     m_pad1->SetTopMargin(0.02); m_pad1->SetBottomMargin(0.0); m_pad1->SetLeftMargin(0.13); m_pad1->SetRightMargin(0.05);
325     m_pad2->SetTopMargin(0.02); m_pad2->SetBottomMargin(0.0); m_pad2->SetLeftMargin(0.13); m_pad2->SetRightMargin(0.05);
326    
327     if (bPlotRatio){
328     m_rp1->SetTopMargin(0.0); m_rp1->SetBottomMargin(0.35); m_rp1->SetLeftMargin(0.13); m_rp1->SetRightMargin(0.05);
329     m_rp2->SetTopMargin(0.0); m_rp2->SetBottomMargin(0.35); m_rp2->SetLeftMargin(0.13); m_rp2->SetRightMargin(0.05);
330     }
331     }
332    
333    
334    
335     if (debug){
336     m_pad1->SetFillColor(kYellow);
337     m_pad2->SetFillColor(kOrange);
338     if (bPlotRatio){
339     m_rp1->SetFillColor(kGray);
340     m_rp2->SetFillColor(kGray);
341     }
342     }
343    
344     m_pad1->Draw();
345     m_pad2->Draw();
346    
347     if (bPlotRatio){
348     m_rp1->Draw();
349     m_rp2->Draw();
350     }
351    
352     return;
353    
354     }
355    
356     void SPlotter::OpenPostscript(TString dir)
357     {
358     // create a new ps file with the directory in the name
359    
360     TString filename(m_ps_name);
361     filename.ReplaceAll(".ps","");
362     filename.Append("_");
363     filename.Append(dir);
364     filename.Append(".ps");
365    
366     TString text(dir);
367     text.Prepend("Plotting all histograms in directory ");
368    
369     cout << "\n+-------------------------- SFrame Plotter ---------------------------+" << endl;
370     cout << "| " << setw(60)<< text << " |" << endl;
371     cout << "+---------------------------------------------------------------------+" << endl;
372     m_page = 0;
373    
374     m_ps = NULL;
375     if (bPortrait){
376     m_ps = new TPostScript(filename, 111); // ps output
377     m_ps->Range(20.0, 30.0);
378     } else {
379     m_ps = new TPostScript(filename, 112); // ps output
380     m_ps->Range(27.0, 18.0);
381     }
382    
383     }
384    
385     void SPlotter::ClosePostscript()
386     {
387     // close the ps file and set page number to 0
388     if (m_ps){
389     m_ps->Close();
390     delete m_ps;
391     m_ps = NULL;
392     }
393     m_page = 0;
394     }
395    
396     void SPlotter::ProcessAndPlot(std::vector<TObjArray*> histarr)
397     {
398     // loop over all arrays in the input array and plot them
399    
400     if (histarr.size()<1){
401     cerr << "SPlotter::ProcessAndPlot: No arrays of histograms given. Abort." << endl;
402     exit(EXIT_FAILURE);
403     }
404    
405     if (histarr[0]->GetEntries()<1){
406     cerr << "SPlotter::ProcessAndPlot: No histograms given. Abort." << endl;
407     exit(EXIT_FAILURE);
408     }
409    
410     if (bPlotRatio && histarr.size()==1){
411     cerr << "SPlotter::ProcessAndPlot: Only one process given, can not plot "
412     << " ratio. Steering correct?" << endl;
413     exit(EXIT_FAILURE);
414     }
415    
416     SetupGlobalStyle();
417    
418     TString psname = m_ps_name;
419     TString current_dir = "";
420    
421     // loop over all histograms and plot them!
422     int iplot = 1;
423     bool bleg = true;
424     for (int i=0; i<histarr[0]->GetEntries(); ++i){
425    
426     // get the histograms for the different processes
427     vector<SHist*> hists = GetPlottableHists(histarr, i);
428    
429     // no plottable hists found at position i
430     if (debug) cout << "Number of plottable hists at index " << i << " = " << hists.size() << endl;
431     if (hists.size()==0) continue;
432    
433     // new directory? create new ps file!
434     TString dir = hists[0]->GetDir();
435     if (dir.CompareTo(current_dir)!=0){
436     if (iplot!=1) DrawPageNum();
437     Cleanup();
438     SetupCanvas();
439     OpenPostscript(dir);
440     current_dir = dir;
441     iplot = 1;
442     bleg = true;
443     }
444    
445     int ipad = GetCurrentPad(iplot);
446     if (debug) cout << "Plotting histograms " << hists[0]->GetName()
447     << " iplot = " << iplot << " ipad = " << ipad << endl;
448    
449     // new page every second plot
450     if (iplot%2==1){
451     if (debug) cout << "Creating new page with number " << m_page << endl;
452     DrawPageNum();
453     if (need_update) m_can->Update();
454     m_ps->NewPage();
455     ++m_page;
456     }
457    
458     // cosmetics
459     DoCosmetics(hists);
460    
461     // do what we set out to do: plot!
462     PlotHists(hists, ipad);
463     // draw a legend
464     if (bleg){
465     DrawLegend(GetHistsAtIndex(histarr, i));
466     if (!bDrawLegend) bleg = false;
467     }
468     // draw lumi information
469     if (bDrawLumi) DrawLumi();
470     // draw the ratio
471     if (bPlotRatio) PlotRatios(hists, ipad);
472    
473    
474     ++iplot;
475     }
476    
477     // done!
478     DrawPageNum();
479     if (need_update) m_can->Update();
480     Cleanup();
481    
482     }
483    
484     void SPlotter::PlotHists(vector<SHist*> hists, int ipad)
485     {
486     // plot all histograms in the array
487    
488     if (ipad==1) m_pad1->cd();
489     if (ipad==2) m_pad2->cd();
490    
491     bool isok = SetMinMax(hists);
492     if (isok) SetLogAxes(hists);
493    
494     // first get some basic histograms
495     SHist* sstack = SelStack(hists);
496     SHist* sdata = SelData(hists);
497    
498     // first, draw data if it exists
499     int ndrawn = 0;
500     if (sdata){
501     sdata->Draw();
502     ++ndrawn;
503     }
504    
505     // first round
506     int nh = hists.size();
507    
508     for (int i=0; i<nh; ++i){
509     SHist* sh = hists[i];
510     if (sh->IsStack()) continue;
511     if (sh==sdata) continue;
512     if (ndrawn==0) sh->Draw();
513     else sh->Draw("same");
514     ++ndrawn;
515     }
516    
517     // now draw the stack
518     if (sstack){
519     if (ndrawn==0){
520     sstack->Draw();
521     need_update = false;
522     } else {
523     sstack->Draw("same");
524     }
525     }
526    
527     // second round
528     for (int i=0; i<nh; ++i){
529     SHist* sh = hists[i];
530     if (sh->IsStack()) continue;
531     if (sh==sdata) continue;
532     sh->Draw("same");
533     }
534    
535     // draw data on top
536     if (sdata) sdata->Draw("same");
537    
538     gPad->RedrawAxis();
539    
540     }
541    
542     void SPlotter::PlotRatios(vector<SHist*> hists, int ipad)
543     {
544     // plot all histograms in the array
545    
546     if (ipad==1) m_rp1->cd();
547     if (ipad==2) m_rp2->cd();
548    
549     // calculate ratios
550     vector<SHist*> ratios = CalcRatios(hists);
551    
552     gPad->SetLogx(0);
553     gPad->SetLogy(0);
554    
555     int ndrawn = 0;
556     int nh = ratios.size();
557     for (int i=0; i<nh; ++i){
558     SHist* rh = ratios[i];
559     TString name = rh->GetName();
560     if (name.Contains("_lx")) gPad->SetLogx(1);
561     if (ndrawn==0) rh->Draw();
562     else rh->Draw("same");
563     ++ndrawn;
564     }
565    
566     gPad->RedrawAxis();
567    
568     }
569    
570     vector<SHist*> SPlotter::CalcRatios(vector<SHist*> hists)
571     {
572     // build ratios from the array 'hists'
573     // by default it is checked if a data histogram exists,
574     // which is then divided by the stack
575     // steerable: which histograms should be calculated for the ratio
576    
577     // first get the basic histograms
578     SHist* sstack = SelStack(hists);
579     SHist* sdata = SelData(hists);
580    
581     vector<SHist*> ratios;
582    
583     // TODO: ratio if neither stack nor data exist
584     if (!sstack || !sdata){
585     return ratios;
586     }
587    
588     SHist* rd = (SHist*) sdata->Duplicate();
589     TH1D* rdhist = (TH1D*) rd->GetHist();
590    
591     // get the denominator: the last element in the stack is the sum of all
592     TObjArray* arr = sstack->GetStack()->GetStack();
593     TH1D* denom = (TH1D*) arr->At(arr->GetEntries()-1);
594    
595     rdhist->Divide(denom);
596     rdhist->GetYaxis()->SetTitle(rd->GetProcessName() + " / MC");
597     RatioCosmetics(rdhist);
598    
599     // one histogram for the MC statistical error
600     SHist* mcerr = new SHist(rdhist);
601     mcerr->GetHist()->SetName("MCstat");
602     mcerr->SetProcessName("MCstat");
603     TH1D* MCstat = (TH1D*)mcerr->GetHist();
604    
605     for (Int_t ibin=1;ibin<denom->GetNbinsX()+1; ++ibin){
606     Double_t val = denom->GetBinContent(ibin);
607     Double_t err = denom->GetBinError(ibin);
608     MCstat->SetBinContent(ibin, 1.0);
609     MCstat->SetBinError(ibin, err/val);
610     }
611     MCstat->SetMarkerStyle(0);
612     MCstat->SetMarkerSize(0);
613     MCstat->SetLineColor(kGray);
614     MCstat->SetFillColor(kGray);
615    
616     ratios.push_back(mcerr);
617     ratios.push_back(rd);
618    
619     return ratios;
620    
621     }
622    
623     void SPlotter::DrawLegend(vector<SHist*> hists)
624     {
625     // draw a legend
626    
627     int narr = hists.size();
628     float yfrac = 0.06;
629     if (!bPlotRatio) yfrac = 0.05;
630     float top = 0.92;
631     float ysize = yfrac*narr;
632     float xleft = 0.65;
633     float xright = 0.92;
634     if (!bPortrait){
635     top = 0.99;
636     ysize = 0.07*narr;
637     xleft = 0.72;
638     xright = 0.96;
639     }
640    
641     TLegend *leg = new TLegend(xleft,top-ysize,xright,top, NULL,"brNDC");
642     leg->SetFillColor(0);
643     leg->SetLineColor(1);
644     leg->SetBorderSize(0);
645     leg->SetTextFont(42);
646     leg->SetFillStyle(0);
647    
648     for (Int_t i=0; i<narr; ++i){
649     SHist* sh = hists[i];
650     if (sh->IsStack()) continue;
651    
652     TString legname = TString::Format("leg_entry_%i",i);
653     TString legtitle = sh->GetLegName();
654     TLegendEntry* entry = NULL;
655     int marker = sh->GetHist()->GetMarkerStyle();
656     int lstyle = sh->GetHist()->GetLineStyle();
657    
658     if (marker>0){
659     entry = leg->AddEntry(legname, legtitle, "lp");
660     entry->SetLineWidth(1);
661     entry->SetLineColor(sh->GetHist()->GetLineColor());
662     entry->SetMarkerColor(sh->GetHist()->GetLineColor());
663     entry->SetMarkerStyle(marker);
664     entry->SetMarkerSize(1.0);
665     } else {
666    
667     if (sh->IsUsedInStack()){
668     entry = leg->AddEntry(legname, legtitle, "f");
669     entry->SetLineWidth(1);
670     entry->SetLineColor(sh->GetHist()->GetLineColor());
671     entry->SetFillColor(sh->GetHist()->GetLineColor());
672     entry->SetFillStyle(1001);
673    
674     } else {
675     entry = leg->AddEntry(legname, legtitle, "l");
676     entry->SetLineColor(sh->GetHist()->GetLineColor());
677     entry->SetMarkerStyle(0);
678     entry->SetMarkerSize(0);
679     entry->SetMarkerColor(sh->GetHist()->GetLineColor());
680     entry->SetLineWidth(2);
681     entry->SetLineStyle(lstyle);
682    
683     }
684     entry->SetTextAlign(12);
685     //entry->SetTextColor(fSampleColors.At(i));
686     }
687     }
688     leg->Draw();
689    
690     }
691    
692    
693     void SPlotter::DrawLumi()
694     {
695     float lumi = 5.2;
696     TString infotext = TString::Format("CMS Preliminary, %3.1f fb^{-1} at #sqrt{s} = 8 TeV", lumi);
697     TLatex *text1 = new TLatex(3.5, 24, infotext);
698     text1->SetNDC();
699     text1->SetTextAlign(13);
700     text1->SetX(0.22);
701     text1->SetY(0.94);
702     text1->SetTextFont(42);
703     text1->SetTextSize(0.06);
704     text1->Draw();
705    
706     // TLatex *text2 = new TLatex(3.5,23,"5.2 fb^{-1} at #sqrt{s} = 8 TeV");
707     //text2->SetNDC();
708     //text2->SetTextAlign(13);
709     //text2->SetX(0.22);
710     //text2->SetY(0.89);
711     //text2->SetTextFont(42);
712     //text2->SetTextSizePixels(40);
713     //text2->Draw();
714     }
715    
716     void SPlotter::DoCosmetics(vector<SHist*> hists)
717     {
718    
719     // loop over all histograms and make them pretty
720     int nh = hists.size();
721     for (int i=0; i<nh; ++i){
722     SHist* sh = hists[i];
723     if (sh->IsStack()) continue;
724     GeneralCosmetics(sh->GetHist());
725     if (bPortrait) PortraitCosmetics(sh->GetHist());
726     if (!bPortrait) LandscapeCosmetics(sh->GetHist());
727     }
728    
729     }
730    
731     SHist* SPlotter::SelStack(vector<SHist*> hists)
732     {
733     // select the stack histogram from the array
734     int narr = hists.size();
735     SHist* h = NULL;
736     for (int i=0; i<narr; ++i){
737     if (hists[i]->IsStack()){
738     h=hists[i];
739     break;
740     }
741     }
742     return h;
743     }
744    
745     SHist* SPlotter::SelData(vector<SHist*> hists)
746     {
747     // select the data histogram from the array
748     int narr = hists.size();
749     SHist* h = NULL;
750     TString process;
751     for (int i=0; i<narr; ++i){
752     process = hists[i]->GetProcessName();
753     if (process.Contains("data", TString::kIgnoreCase)){
754     h = hists[i];
755     break;
756     }
757     }
758     return h;
759     }
760    
761     bool SPlotter::SetMinMax(vector<SHist*> hists)
762     {
763     // set minimum and maximum of all histograms
764     int narr = hists.size();
765     TString name = hists[0]->GetName();
766     double max = 0;
767     double min = FLT_MAX;
768     for (int i=0; i<narr; ++i){
769     if (max<hists[i]->GetMaximum()) max = hists[i]->GetMaximum();
770     if (min>hists[i]->GetMinimum()) min = hists[i]->GetMinimum();
771     }
772    
773     bool isok = true;
774     if (max<1e-6){
775     isok = false;
776     return isok;
777     }
778    
779     bool islog = false;
780     double uscale = 1.2;
781     if (name.Contains("_lxy") || name.Contains("_ly")){
782     islog = true;
783     uscale = 12.;
784     }
785    
786     for (int i=0; i<narr; ++i){
787     SHist* h = hists[i];
788     if (h->IsStack()){
789     if (!islog) h->GetStack()->SetMinimum(0.001);
790     h->GetStack()->SetMaximum(uscale*max);
791     } else {
792     if (!islog) h->GetHist()->SetMinimum(0.001);
793     h->GetHist()->SetMaximum(uscale*max);
794     }
795     }
796    
797     return isok;
798     }
799    
800     void SPlotter::SetLogAxes(vector<SHist*> hists)
801     {
802     // set log axes
803     TString name = hists[0]->GetName();
804     gPad->SetLogx(0);
805     gPad->SetLogy(0);
806     if (name.Contains("_lxy")){
807     gPad->SetLogx(1);
808     gPad->SetLogy(1);
809     } else if (name.Contains("_lx")){
810     gPad->SetLogx(1);
811     } else if (name.Contains("_ly")){
812     gPad->SetLogy(1);
813     } else {
814     // do nothing, all fine
815     }
816     return;
817     }
818    
819     int SPlotter::GetCurrentPad(int np)
820     {
821     // get the current pad, depending on the number of
822     // already processed plots
823     int ipad = 1;
824     int rest = np%2;
825     if (rest==0) ipad=2;
826     return ipad;
827     }
828    
829     vector<SHist*> SPlotter::GetHistsAtIndex(std::vector<TObjArray*> histarr, int index)
830     {
831     // fill an array with histograms at position index.
832    
833     vector<SHist*> hists;
834     int narr = histarr.size();
835     for (int i=0; i<narr; ++i){
836     SHist* hist = (SHist*)histarr[i]->At(index);
837     hists.push_back(hist);
838     }
839    
840     return hists;
841    
842     }
843    
844     vector<SHist*> SPlotter::GetPlottableHists(std::vector<TObjArray*> histarr, int index)
845     {
846     // fill an array with plottable histograms at position index.
847     // if the first histogram in the array should be plotted (DoPlot flag),
848     // then take at first position in the array
849     // otherwise look for the stack and plot it first
850     // only then all other histograms are added
851    
852     if (debug) cout << "\nSPlotter: Collecting plottable hists for index " << index << endl;
853     vector<SHist*> hists;
854     bool gotstack = false;
855     SHist* hist = (SHist*)histarr[0]->At(index);
856    
857     // check if the histogram is a 2D or 3D histogram,
858     // plotting not supported yet, to come
859     if (hist->GetHist()->InheritsFrom(TH2::Class())){
860     if (debug) cout << "Hist inherits from TH2, return without adding any to the array " << endl;
861     return hists;
862     }
863    
864 peiffer 1.2 TString name = hist->GetName();
865     TString process = hist->GetProcessName();
866     if (process.Contains("data",TString::kIgnoreCase)
867     && name.Contains("_perlumibin", TString::kIgnoreCase)){
868     hists.push_back(hist);
869     return hists;
870     }
871    
872 rkogler 1.1 if (hist->DoDraw()){ // take first hist
873     hists.push_back(hist);
874     gotstack = false;
875     if (debug) cout << "Adding hist " << hist->GetHist()->GetName()
876     << " from process " << hist->GetProcessName()
877     << " and directory " << hist->GetDir() << " to array." << endl;
878     } else { // try if stack exists
879     TObjArray* stacks = GetStacks(histarr);
880     if (stacks){
881     hist = (SHist*)stacks->At(index);
882     hists.push_back(hist);
883     gotstack = true;
884     if (debug) cout << "Adding stack " << hist->GetStack()->GetName()
885     << " from process " << hist->GetProcessName()
886     << " and directory " << hist->GetDir() << " to array." << endl;
887     }
888     }
889    
890     // loop over the rest and add them to the array
891     int narr = histarr.size();
892     for (int i=1; i<narr; ++i){
893    
894     SHist* hist = (SHist*)histarr[i]->At(index);
895    
896     if (hist->DoDraw()){ // take it if it should be drawn
897    
898     if (hist->IsStack()){
899     if (!gotstack){ // take the stack only if not already added
900     hists.push_back(hist);
901     if (debug) cout << "Adding stack " << hist->GetStack()->GetName()
902     << " from process " << hist->GetProcessName()
903     << " and directory " << hist->GetDir() << " to array." << endl;
904     }
905     } else { // take the histogram if it's not the stack hist
906     hists.push_back(hist);
907     if (debug) cout << "Adding hist " << hist->GetHist()->GetName()
908     << " from process " << hist->GetProcessName()
909     << " and directory " << hist->GetDir() << " to array." << endl;
910     }
911     }
912     }
913    
914     if (debug) cout << "SPlotter: Done with collecting plottable hists for index "
915     << index << ", got " << hists.size() << " histograms" << endl;
916    
917     return hists;
918    
919     }
920    
921     void SPlotter::DrawPageNum()
922     {
923    
924     m_can->cd();
925     TPaveText* text;
926     TString s;
927     s.Form("%i",m_page);
928     if (bPortrait){
929     text = new TPaveText(0.93, 0.00, 0.97, 0.03, "NDC");
930     } else {
931     text = new TPaveText(0.03,0.00, 0.06, 0.03, "NDC");
932     }
933     text->SetBorderSize(0);
934     text->SetFillColor(0);
935     text->AddText(s.Data());
936     text->Draw("same");
937    
938     }
939    
940     void SPlotter::GeneralCosmetics(TH1* hist)
941     {
942     // set Y-axis title
943     hist->GetYaxis()->SetTitle("Entries");
944    
945     // set X-axis title
946     hist->GetXaxis()->SetTitle(hist->GetTitle());
947    
948     hist->SetTitle("");
949    
950     if (bShapeNorm) {
951     hist->GetYaxis()->SetTitle("#DeltaN/N");
952     }
953    
954     hist->GetXaxis()->SetTitleFont(42);
955     hist->GetXaxis()->SetLabelFont(42);
956     hist->GetYaxis()->SetTitleFont(42);
957     hist->GetYaxis()->SetLabelFont(42);
958    
959     }
960    
961     void SPlotter::PortraitCosmetics(TH1* hist)
962     {
963    
964     // top histogram of the ratio plot
965     if (bPlotRatio){
966    
967     // x-axis
968     hist->GetXaxis()->SetTickLength(0.05);
969    
970     // y-axis
971     hist->GetYaxis()->SetTitleSize(0.07);
972     hist->GetYaxis()->SetLabelSize(0.062);
973     hist->GetYaxis()->SetLabelOffset(0.01);
974     hist->GetYaxis()->SetTitleOffset(0.8);
975     hist->GetYaxis()->SetTickLength(0.02);
976    
977     // only this histogram
978     } else {
979    
980     hist->GetXaxis()->SetLabelSize(0.05);
981     hist->GetXaxis()->SetLabelOffset(0.008);
982     hist->GetXaxis()->SetTickLength(0.03);
983     hist->GetXaxis()->SetTitleSize(0.05);
984     hist->GetXaxis()->SetTitleOffset(1.2);
985    
986     hist->GetYaxis()->SetTitleOffset(1.2);
987     hist->GetYaxis()->SetTitleSize(0.06);
988     hist->GetYaxis()->SetLabelSize(0.045);
989     hist->GetYaxis()->SetTickLength(0.02);
990     hist->GetYaxis()->SetLabelOffset(0.011);
991    
992     }
993    
994     }
995    
996     void SPlotter::LandscapeCosmetics(TH1* hist)
997     {
998    
999    
1000    
1001     }
1002    
1003     void SPlotter::RatioCosmetics(TH1* hist)
1004     {
1005    
1006     hist->GetYaxis()->SetRangeUser(0.3, 1.7);
1007     hist->SetMarkerSize(0.7);
1008    
1009     // cosmetics for portrait mode
1010     if (bPortrait){
1011     hist->SetTitle("");
1012    
1013     // x-axis
1014     hist->GetXaxis()->SetLabelSize(0.12);
1015     hist->GetXaxis()->SetTickLength(0.08);
1016     hist->GetXaxis()->SetTitleSize(0.12);
1017     hist->GetXaxis()->SetTitleOffset(1.25);
1018    
1019     // y-axis
1020     hist->GetYaxis()->CenterTitle();
1021     hist->GetYaxis()->SetTitleSize(0.12);
1022     hist->GetYaxis()->SetTitleOffset(0.46);
1023     hist->GetYaxis()->SetLabelSize(0.11);
1024     hist->GetYaxis()->SetNdivisions(210);
1025     hist->GetYaxis()->SetTickLength(0.02);
1026     hist->GetYaxis()->SetLabelOffset(0.011);
1027    
1028     // cosmetics for landscape mode
1029     } else {
1030    
1031     hist->SetTitle("");
1032     hist->SetTitleOffset(1.1, "X");
1033     hist->SetTitleOffset(0.5, "Y");
1034     hist->SetLabelOffset(0.02, "X");
1035     hist->SetLabelOffset(0.01, "Y");
1036    
1037     hist->GetXaxis()->SetLabelSize(0.14);
1038     hist->GetXaxis()->SetTickLength(0.07);
1039     hist->GetXaxis()->SetTitleSize(0.15);
1040    
1041     hist->GetYaxis()->CenterTitle();
1042     hist->GetYaxis()->SetTitleSize(0.11);
1043     hist->GetYaxis()->SetLabelSize(0.12);
1044     hist->GetYaxis()->SetNdivisions(505);
1045     hist->GetYaxis()->SetTickLength(0.03);
1046    
1047     }
1048    
1049    
1050    
1051     }