3 #include <TGraphErrors.h>
4 #include <TGraphAsymmErrors.h>
5 #include <TMultiGraph.h>
17 #include <TLegendEntry.h>
25 TAxis* fMasterAxis; // Master axis
26 TAxis* fSlave1Axis; // First slave axis
27 TVirtualPad* fSlave1Pad; // First slave pad
28 TAxis* fSlave2Axis; // Second slave axis
29 TVirtualPad* fSlave2Pad; // Second slave pad
31 //__________________________________________________________________
33 : fShowOthers(false), // Bool_t
34 fShowAlice(false), // Bool_t
35 fShowRatios(false), // Bool_t
36 fShowLeftRight(false), // Bool_t
37 fRebin(5), // UShort_t
38 fCutEdges(false), // Bool_t
39 fTitle(""), // TString
40 fHHDFile(""), // TString
41 fTrigString(0), // TNamed*
42 fSNNString(0), // TNamed*
43 fSysString(0), // TNamed*
44 fVtxAxis(0), // TAxis*
46 fForwardMC(0), // TH1*
47 fForwardHHD(0), // TH1*
50 fForwardSym(0), // TH1*
51 fForwardMCSym(0), // TH1*
52 fForwardHHDSym(0), // TH1*
57 fRangeParam = new RangeParam;
58 fRangeParam->fMasterAxis = 0;
59 fRangeParam->fSlave1Axis = 0;
60 fRangeParam->fSlave1Pad = 0;
61 fRangeParam->fSlave2Axis = 0;
62 fRangeParam->fSlave2Pad = 0;
64 void SetShowOthers(Bool_t x) { fShowOthers = x; }
65 void SetShowAlice(Bool_t x) { fShowAlice = x; }
66 void SetShowRatios(Bool_t x) { fShowRatios = x; }
67 void SetShowLeftRight(Bool_t x) { fShowLeftRight = x; }
68 void SetRebin(UShort_t x) { fRebin = x; }
69 void SetCutEdges(Bool_t x) { fCutEdges = x; }
70 void SetTitle(TString x) { fTitle = x; }
71 void SetHHDFile(const char* fn) { fHHDFile = fn; }
73 //__________________________________________________________________
74 void Run(const char* filename)
76 if (!Open(filename)) return;
80 // Create our stack of results
81 THStack* results = StackResults(max);
83 // Create our stack of other results
84 TMultiGraph* other = 0;
85 if (fShowOthers || fShowAlice) other = StackOther(max);
89 if (fShowRatios) ratios = StackRatios(other, smax);
92 THStack* leftright = 0;
93 if (fShowLeftRight) leftright = StackLeftRight(amax);
95 Plot(results, other, max, ratios, smax, leftright, amax);
98 //__________________________________________________________________
99 Bool_t Open(const char* filename)
101 TFile* file = TFile::Open(filename, "READ");
103 Error("Open", "Cannot open %s", filename);
107 TList* results = static_cast<TList*>(file->Get("ForwardResults"));
109 Error("Open", "Couldn't find list ForwardResults");
113 fForward = GetResult(results, "dndetaForward");
114 fForwardMC = GetResult(results, "dndetaForwardMC");
115 fTruth = GetResult(results, "dndetaTruth");
116 fCentral = GetResult(results, "dndetaCentral");
118 fTrigString = static_cast<TNamed*>(results->FindObject("trigString"));
119 fSNNString = static_cast<TNamed*>(results->FindObject("sNN"));
120 fSysString = static_cast<TNamed*>(results->FindObject("sys"));
121 fVtxAxis = static_cast<TAxis*>(results->FindObject("vtxAxis"));
123 TList* sums = static_cast<TList*>(file->Get("ForwardSums"));
125 fTriggers = GetResult(sums, "triggers");
128 Error("Open", "Couldn't find the result of the forward analysis");
134 fForwardHHD = GetHHD();
138 //__________________________________________________________________
139 TH1* GetResult(TList* list, const char* name) const
143 TH1* ret = static_cast<TH1*>(list->FindObject(name));
145 Warning("GetResult", "Histogram %s not found", name);
149 //__________________________________________________________________
151 * Get the result from previous analysis code
153 * @param fn File to open
154 * @param nsd Whether this is NSD
156 * @return null or result of previous analysis code
160 if (fHHDFile.IsNull()) return 0;
161 const char* fn = fHHDFile.Data();
162 Bool_t nsd = (fTrigString ? fTrigString->GetUniqueID() & 0x4 : false);
163 TDirectory* savdir = gDirectory;
164 if (gSystem->AccessPathName(fn)) {
165 Warning("GetHHD", "Output of HHD analysis (%s) not available", fn);
168 TFile* file = TFile::Open(fn, "READ");
170 Warning("GetHHD", "couldn't open HHD file %s", fn);
173 TString hist(Form("dNdeta_dNdeta%s", (nsd ? "NSD" : "")));
174 TH1* h = static_cast<TH1*>(file->Get(hist.Data()));
176 Warning("GetHHD", "Couldn't find HHD histogram %s in %s",
182 TH1* r = static_cast<TH1*>(h->Clone("dndeta_hhd"));
183 r->SetTitle("ALICE Forward (HHD)");
186 r->SetMarkerStyle(21);
187 r->SetMarkerColor(kPink+1);
194 //__________________________________________________________________
195 THStack* StackResults(Double_t& max)
197 THStack* stack = new THStack("results", "Stack of Results");
198 max = TMath::Max(max, AddHistogram(stack, fTruth, "e5 p"));
199 max = TMath::Max(max, AddHistogram(stack, fForwardHHD, "", fForwardHHDSym));
200 max = TMath::Max(max, AddHistogram(stack, fForwardMC, "", fForwardMCSym));
201 max = TMath::Max(max, AddHistogram(stack, fCentral, ""));
202 max = TMath::Max(max, AddHistogram(stack, fForward, "", fForwardSym));
205 //__________________________________________________________________
206 TMultiGraph* StackOther(Double_t& max) const
208 gROOT->LoadMacro("$ALICE_ROOT/PWG2/FORWARD/analysis2/OtherData.C");
210 Bool_t onlya = (fShowOthers ? false : true);
211 Int_t trg = (fTrigString ? fTrigString->GetUniqueID() : 0);
212 UShort_t snn = (fSNNString ? fSNNString->GetUniqueID() : 0);
213 Long_t ret = gROOT->ProcessLine(Form("GetData(%d,%d,%d);",
216 Error("StackOther", "Failed to execute GetData(%d,%d,%d)",
221 Warning("StackOther", "No other data found for sNN=%d, trigger=%d",
225 TMultiGraph* other = reinterpret_cast<TMultiGraph*>(ret);
227 TGraphAsymmErrors* o = 0;
228 TIter next(other->GetListOfGraphs());
229 while ((o = static_cast<TGraphAsymmErrors*>(next())))
230 max = TMath::Max(max, TMath::MaxElement(o->GetN(), o->GetY()));
234 //__________________________________________________________________
235 THStack* StackRatios(TMultiGraph* others, Double_t& max)
237 THStack* ratios = new THStack("ratios", "Ratios");
240 TGraphAsymmErrors* ua5_1 = 0;
241 TGraphAsymmErrors* ua5_2 = 0;
242 TGraphAsymmErrors* alice = 0;
243 TGraphAsymmErrors* cms = 0;
244 TGraphAsymmErrors* o = 0;
245 TIter nextG(others->GetListOfGraphs());
246 while ((o = static_cast<TGraphAsymmErrors*>(nextG()))) {
247 ratios->Add(Ratio(fForward, o, max));
248 ratios->Add(Ratio(fForwardSym, o, max));
249 ratios->Add(Ratio(fForwardHHD, o, max));
250 ratios->Add(Ratio(fForwardHHDSym, o, max));
251 ratios->Add(Ratio(fCentral, o, max));
252 TString oName(o->GetName());
254 if (oName.Contains("ua5")) { if (ua5_1) ua5_2 = o; else ua5_1 = o; }
255 if (oName.Contains("alice")) alice = o;
256 if (oName.Contains("cms")) cms = o;
258 if (ua5_1 && alice) ratios->Add(Ratio(alice, ua5_1, max));
259 if (ua5_2 && alice) ratios->Add(Ratio(alice, ua5_2, max));
260 if (cms && alice) ratios->Add(Ratio(alice, cms, max));
263 // If we have data from HHD's analysis, then do the ratio of
264 // our result to that data.
266 ratios->Add(Ratio(fForward, fForwardHHD, max));
267 ratios->Add(Ratio(fForwardSym, fForwardHHDSym, max));
270 // Do comparison to MC
272 ratios->Add(Ratio(fForward, fForwardMC, max));
273 ratios->Add(Ratio(fForwardSym, fForwardMCSym, max));
276 // Check if we have ratios
277 if (!ratios->GetHists() ||
278 (ratios->GetHists()->GetEntries() <= 0)) {
284 //__________________________________________________________________
285 THStack* StackLeftRight(Double_t& max)
287 THStack* ret = new THStack("leftright", "Left-right asymmetry");
288 ret->Add(Asymmetry(fForward, max));
289 ret->Add(Asymmetry(fForwardHHD, max));
290 ret->Add(Asymmetry(fForwardMC, max));
292 if (!ret->GetHists() ||
293 (ret->GetHists()->GetEntries() <= 0)) {
299 //__________________________________________________________________
300 TAxis* FindXAxis(TVirtualPad* p, const char* name)
302 TObject* o = p->GetListOfPrimitives()->FindObject(name);
304 Warning("FindXAxis", "%s not found in pad", name);
307 THStack* stack = dynamic_cast<THStack*>(o);
309 Warning("FindXAxis", "%s is not a THStack", name);
312 if (!stack->GetHistogram()) {
313 Warning("FindXAxis", "%s has no histogram", name);
316 TAxis* ret = stack->GetHistogram()->GetXaxis();
319 //__________________________________________________________________
320 void Plot(THStack* results,
328 gStyle->SetOptTitle(0);
329 gStyle->SetTitleFont(132, "xyz");
330 gStyle->SetLabelFont(132, "xyz");
333 Int_t w = 800; // h / TMath::Sqrt(2);
334 if (!ratios) w *= 1.4;
335 if (!leftright) w *= 1.4;
336 TCanvas* c = new TCanvas("Results", "Results", w, h);
344 if (ratios) y1 = 0.3;
355 PlotResults(results, others, max, y1);
358 PlotRatios(ratios, rmax, y2, y1);
361 PlotLeftRight(leftright, amax, y3, y2);
364 //__________________________________________________________________
365 void PlotResults(THStack* results, TMultiGraph* others,
366 Double_t max, Double_t yd)
368 // Make a sub-pad for the result itself
369 TPad* p1 = new TPad("p1", "p1", 0, yd, 1.0, 1.0, 0, 0, 0);
370 p1->SetTopMargin(0.05);
371 p1->SetBorderSize(0);
372 p1->SetBorderMode(0);
373 p1->SetBottomMargin(yd > 0.001 ? 0.001 : 0.1);
374 p1->SetRightMargin(0.05);
381 results->SetMaximum(1.15*max);
382 results->SetMinimum(yd > 0.00001 ? -0.1 : 0);
384 FixAxis(results, 1/(1-yd)/1.7, "#frac{1}{N} #frac{dN_{ch}}{d#eta}");
387 results->DrawClone("nostack e1");
389 fRangeParam->fSlave1Axis = results->GetXaxis();
390 fRangeParam->fSlave1Pad = p1;
394 TGraphAsymmErrors* o = 0;
395 TIter nextG(others->GetListOfGraphs());
396 while ((o = static_cast<TGraphAsymmErrors*>(nextG())))
397 o->DrawClone("same p");
400 // Make a legend in the main result pad
401 TLegend* l = p1->BuildLegend(.15,p1->GetBottomMargin()+.01,.90,.35);
408 // Put a title on top
409 TLatex* tit = new TLatex(0.10, 0.95, fTitle.Data());
411 tit->SetTextFont(132);
412 tit->SetTextSize(0.05);
415 // Put a nice label in the plot
417 UShort_t snn = (fSNNString ? fSNNString->GetUniqueID() : 0);
418 const char* sys = (fSysString ? fSysString->GetTitle() : "?");
419 if (snn > 1000) eS = Form("%4.2fTeV", float(snn)/1000);
420 else eS = Form("%3dGeV", snn);
421 TLatex* tt = new TLatex(.93, .93, Form("%s #sqrt{s}=%s, %s",
425 fTrigString->GetTitle() : "?"));
427 tt->SetTextFont(132);
428 tt->SetTextAlign(33);
431 // Put number of accepted events on the plot
432 Int_t nev = fTriggers->GetBinContent(fTriggers->GetNbinsX());
433 TLatex* et = new TLatex(.93, .83, Form("%d events", nev));
435 et->SetTextFont(132);
436 et->SetTextAlign(33);
439 // Put number of accepted events on the plot
441 TLatex* vt = new TLatex(.93, .88, fVtxAxis->GetTitle());
443 vt->SetTextFont(132);
444 vt->SetTextAlign(33);
447 // results->Draw("nostack e1 same");
449 fRangeParam->fSlave1Axis = FindXAxis(p1, results->GetName());
450 fRangeParam->fSlave1Pad = p1;
453 // Mark the plot as preliminary
454 TLatex* pt = new TLatex(.12, .93, "Preliminary");
457 pt->SetTextSize(0.07);
458 pt->SetTextColor(kRed+1);
459 pt->SetTextAlign(13);
462 if (!gSystem->AccessPathName("ALICE.png")) {
463 TPad* logo = new TPad("logo", "logo", .12, .7, .32, .90, 0, 0, 0);
464 logo->SetFillStyle(0);
467 TImage* i = TImage::Create();
468 i->ReadImage("ALICE.png");
473 //__________________________________________________________________
474 void PlotRatios(THStack* ratios, Double_t max, Double_t y1, Double_t y2)
477 bool isBottom = (y1 < 0.0001);
478 Double_t yd = y2 - y1;
479 // Make a sub-pad for the result itself
480 TPad* p2 = new TPad("p2", "p2", 0, y1, 1.0, y2, 0, 0, 0);
481 p2->SetTopMargin(0.001);
482 p2->SetRightMargin(0.05);
483 p2->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
491 FixAxis(ratios, 1/yd/1.7, "Ratios", 7);
493 ratios->SetMaximum(1+TMath::Max(.22,1.05*max));
494 ratios->SetMinimum(1-TMath::Max(.32,1.05*max));
496 ratios->DrawClone("nostack e1");
500 TLegend* l2 = p2->BuildLegend(.15,p2->GetBottomMargin()+.01,.9,
505 l2->SetBorderSize(0);
506 l2->SetTextFont(132);
508 // Make a nice band from 0.9 to 1.1
509 TGraphErrors* band = new TGraphErrors(2);
510 band->SetPoint(0, fForwardSym->GetXaxis()->GetXmin(), 1);
511 band->SetPoint(1, fForward->GetXaxis()->GetXmax(), 1);
512 band->SetPointError(0, 0, .1);
513 band->SetPointError(1, 0, .1);
514 band->SetFillColor(kYellow+2);
515 band->SetFillStyle(3002);
516 band->SetLineStyle(2);
517 band->SetLineWidth(1);
518 band->Draw("3 same");
519 band->DrawClone("X L same");
521 // Replot the ratios on top
522 ratios->DrawClone("nostack e1 same");
525 fRangeParam->fMasterAxis = FindXAxis(p2, ratios->GetName());
526 p2->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)",
530 fRangeParam->fSlave2Axis = FindXAxis(p2, ratios->GetName());
531 fRangeParam->fSlave2Pad = p2;
534 //__________________________________________________________________
535 void PlotLeftRight(THStack* leftright, Double_t max,
536 Double_t y1, Double_t y2)
538 if (!leftright) return;
539 bool isBottom = (y1 < 0.0001);
540 Double_t yd = y2 - y1;
541 // Make a sub-pad for the result itself
542 TPad* p3 = new TPad("p3", "p3", 0, y1, 1.0, y2, 0, 0, 0);
543 p3->SetTopMargin(0.001);
544 p3->SetRightMargin(0.05);
545 p3->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
553 if (leftright->GetHists()->GetEntries() == 1) {
554 // Add dummy histogram
555 dummy = new TH1F("dummy","", 10, -6, 6);
556 dummy->SetLineColor(0);
557 dummy->SetFillColor(0);
558 dummy->SetMarkerColor(0);
559 leftright->Add(dummy);
563 FixAxis(leftright, 1/yd/1.7, "Right/Left", 4);
565 leftright->SetMaximum(1+TMath::Max(.12,1.05*max));
566 leftright->SetMinimum(1-TMath::Max(.15,1.05*max));
568 leftright->DrawClone("nostack e1");
572 TLegend* l2 = p3->BuildLegend(.15,p3->GetBottomMargin()+.01,.9,.5);
576 l2->SetBorderSize(0);
577 l2->SetTextFont(132);
580 TList* prims = l2->GetListOfPrimitives();
583 while ((o = static_cast<TLegendEntry*>(next()))) {
584 TString lbl(o->GetLabel());
585 if (lbl != "dummy") continue;
591 // Make a nice band from 0.9 to 1.1
592 TGraphErrors* band = new TGraphErrors(2);
593 band->SetPoint(0, fForwardSym->GetXaxis()->GetXmin(), 1);
594 band->SetPoint(1, fForward->GetXaxis()->GetXmax(), 1);
595 band->SetPointError(0, 0, .05);
596 band->SetPointError(1, 0, .05);
597 band->SetFillColor(kYellow+2);
598 band->SetFillStyle(3002);
599 band->SetLineStyle(2);
600 band->SetLineWidth(1);
601 band->Draw("3 same");
602 band->DrawClone("X L same");
604 leftright->DrawClone("nostack e1 same");
606 fRangeParam->fMasterAxis = FindXAxis(p3, leftright->GetName());
607 p3->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)",
611 fRangeParam->fSlave2Axis = FindXAxis(p3, leftright->GetName());
612 fRangeParam->fSlave2Pad = p3;
616 //__________________________________________________________________
618 * Fix the apperance of the axis in a stack
620 * @param stack stack of histogram
621 * @param s Scaling factor
622 * @param ytitle Y axis title
623 * @param force Whether to draw the stack first or not
624 * @param ynDiv Divisions on Y axis
626 void FixAxis(THStack* stack, Double_t s, const char* ytitle,
627 Int_t ynDiv=210, Bool_t force=true)
629 if (force) stack->Draw("nostack e1");
631 TH1* h = stack->GetHistogram();
634 h->SetXTitle("#eta");
635 h->SetYTitle(ytitle);
636 TAxis* xa = h->GetXaxis();
637 TAxis* ya = h->GetYaxis();
639 xa->SetTitle("#eta");
640 // xa->SetTicks("+-");
641 xa->SetTitleSize(s*xa->GetTitleSize());
642 xa->SetLabelSize(s*xa->GetLabelSize());
643 xa->SetTickLength(s*xa->GetTickLength());
646 ya->SetTitle(ytitle);
648 // ya->SetTicks("+-");
649 ya->SetNdivisions(ynDiv);
650 ya->SetTitleSize(s*ya->GetTitleSize());
651 ya->SetTitleOffset(ya->GetTitleOffset()/s);
652 ya->SetLabelSize(s*ya->GetLabelSize());
656 //__________________________________________________________________
657 Double_t AddHistogram(THStack* stack, TH1* hist, Option_t* option) const
659 // Check if we have input
665 stack->Add(hist, option);
666 return hist->GetMaximum();
668 //__________________________________________________________________
669 Double_t AddHistogram(THStack* stack, TH1* hist, Option_t* option,
672 // Check if we have input
677 stack->Add(hist, option);
679 // Now symmetrice the histogram
680 sym = Symmetrice(hist);
681 stack->Add(sym, option);
683 return hist->GetMaximum();
686 //__________________________________________________________________
690 * @param h Histogram to rebin
691 * @param rebin Rebinning factor
695 virtual void Rebin(TH1* h) const
697 if (fRebin <= 1) return;
699 Int_t nBins = h->GetNbinsX();
700 if(nBins % fRebin != 0) {
701 Warning("Rebin", "Rebin factor %d is not a devisor of current number "
702 "of bins %d in the histogram %s", fRebin, nBins, h->GetName());
707 TH1* tmp = static_cast<TH1*>(h->Clone("tmp"));
709 tmp->SetDirectory(0);
711 // The new number of bins
712 Int_t nBinsNew = nBins / fRebin;
713 for(Int_t i = 1;i<= nBinsNew; i++) {
714 Double_t content = 0;
718 for(Int_t j = 1; j<=fRebin;j++) {
719 Int_t bin = (i-1)*fRebin + j;
720 Double_t c = h->GetBinContent(bin);
722 if (c <= 0) continue;
725 if (h->GetBinContent(bin+1)<=0 ||
726 h->GetBinContent(bin-1)) {
727 Warning("Rebin", "removing bin %d=%f of %s (%d=%f,%d=%f)",
728 bin, c, h->GetName(),
729 bin+1, h->GetBinContent(bin+1),
730 bin-1, h->GetBinContent(bin-1));
734 Double_t e = h->GetBinError(bin);
735 Double_t w = 1 / (e*e); // 1/c/c
742 if(content > 0 && nbins > 0) {
743 tmp->SetBinContent(i, wsum / sumw);
744 tmp->SetBinError(i,1./TMath::Sqrt(sumw));
748 // Finally, rebin the histogram, and set new content
751 for(Int_t i = 1; i<= nBinsNew; i++) {
752 h->SetBinContent(i,tmp->GetBinContent(i));
753 h->SetBinError(i, tmp->GetBinError(i));
758 //__________________________________________________________________
760 * Make an extension of @a h to make it symmetric about 0
762 * @param h Histogram to symmertrice
764 * @return Symmetric extension of @a h
766 TH1* Symmetrice(const TH1* h) const
768 Int_t nBins = h->GetNbinsX();
769 TH1* s = static_cast<TH1*>(h->Clone(Form("%s_mirror", h->GetName())));
770 s->SetTitle(Form("%s (mirrored)", h->GetTitle()));
772 s->SetBins(nBins, -h->GetXaxis()->GetXmax(), -h->GetXaxis()->GetXmin());
773 s->SetMarkerColor(h->GetMarkerColor());
774 s->SetMarkerSize(h->GetMarkerSize());
775 s->SetMarkerStyle(h->GetMarkerStyle()+4);
776 s->SetFillColor(h->GetFillColor());
777 s->SetFillStyle(h->GetFillStyle());
780 // Find the first and last bin with data
781 Int_t first = nBins+1;
783 for (Int_t i = 1; i <= nBins; i++) {
784 if (h->GetBinContent(i) <= 0) continue;
785 first = TMath::Min(first, i);
786 last = TMath::Max(last, i);
789 Double_t xfirst = h->GetBinCenter(first-1);
790 Int_t f1 = h->GetXaxis()->FindBin(-xfirst);
791 Int_t l2 = s->GetXaxis()->FindBin(xfirst);
792 for (Int_t i = f1, j=l2; i <= last; i++,j--) {
793 s->SetBinContent(j, h->GetBinContent(i));
794 s->SetBinError(j, h->GetBinError(i));
796 // Fill in overlap bin
797 s->SetBinContent(l2+1, h->GetBinContent(first));
798 s->SetBinError(l2+1, h->GetBinError(first));
801 //__________________________________________________________________
802 Double_t RatioMax(TH1* h) const
804 Int_t nBins = h->GetNbinsX();
806 for (Int_t i = 1; i <= nBins; i++) {
807 Double_t c = h->GetBinContent(i);
808 if (c == 0) continue;
809 Double_t e = h->GetBinError(i);
810 Double_t d = TMath::Abs(1-c-e);
811 ret = TMath::Max(d, ret);
815 //__________________________________________________________________
817 * Compute the ratio of @a h to @a g. @a g is evaluated at the bin
825 TH1* Ratio(const TH1* h, const TGraph* g, Double_t& max) const
827 if (!h || !g) return 0;
829 TH1* ret = static_cast<TH1*>(h->Clone("tmp"));
830 ret->SetName(Form("%s_over_%s", h->GetName(), g->GetName()));
831 ret->SetTitle(Form("%s / %s", h->GetTitle(), g->GetTitle()));
833 ret->SetMarkerStyle(g->GetMarkerStyle());
834 ret->SetMarkerColor(h->GetMarkerColor());
835 ret->SetMarkerSize(0.9*g->GetMarkerSize());
836 Double_t xlow = g->GetX()[0];
837 Double_t xhigh = g->GetX()[g->GetN()-1];
838 if (xlow > xhigh) { Double_t t = xhigh; xhigh = xlow; xlow = t; }
840 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
841 Double_t c = h->GetBinContent(i);
842 if (c <= 0) continue;
844 Double_t x = h->GetBinCenter(i);
845 if (x < xlow || x > xhigh) continue;
847 Double_t f = g->Eval(x);
848 if (f <= 0) continue;
850 ret->SetBinContent(i, c / f);
851 ret->SetBinError(i, h->GetBinError(i) / f);
853 if (ret->GetEntries() <= 0) {
858 max = TMath::Max(RatioMax(ret), max);
861 //__________________________________________________________________
863 * Make the ratio of h1 to h2
865 * @param h1 First histogram (numerator)
866 * @param h2 Second histogram (denominator)
870 TH1* Ratio(const TH1* h1, const TH1* h2, Double_t& max) const
872 if (!h1 || !h2) return 0;
873 TH1* t1 = static_cast<TH1*>(h1->Clone(Form("%s_%s",
876 t1->SetTitle(Form("%s / %s", h1->GetTitle(), h2->GetTitle()));
878 t1->SetMarkerColor(h1->GetMarkerColor());
879 t1->SetMarkerStyle(h2->GetMarkerStyle());
880 max = TMath::Max(RatioMax(t1), max);
883 //__________________________________________________________________
885 * Calculate the ratio of two graphs - g1 / g2
887 * @param g1 Numerator
888 * @param g2 Denominator
890 * @return g1 / g2 in a histogram
892 TH1* Ratio(const TGraphAsymmErrors* g1,
893 const TGraphAsymmErrors* g2, Double_t& max) const
895 Int_t nBins = g1->GetN();
896 TArrayF bins(nBins+1);
898 for (Int_t i = 0; i < nBins; i++) {
899 Double_t x = g1->GetX()[i];
900 Double_t exl = g1->GetEXlow()[i];
901 Double_t exh = g1->GetEXhigh()[i];
902 bins.fArray[i] = x-exl;
903 bins.fArray[i+1] = x+exh;
904 Double_t dxi = exh+exl;
905 if (i == 0) dx = dxi;
906 else if (dxi != dx) dx = 0;
908 TString name(Form("%s_%s", g1->GetName(), g2->GetName()));
909 TString title(Form("%s / %s", g1->GetTitle(), g2->GetTitle()));
912 h = new TH1F(name.Data(), title.Data(), nBins, bins[0], bins[nBins]);
915 h = new TH1F(name.Data(), title.Data(), nBins, bins.fArray);
917 h->SetMarkerStyle(g2->GetMarkerStyle());
918 h->SetMarkerColor(g1->GetMarkerColor());
919 h->SetMarkerSize(0.9*g2->GetMarkerSize());
921 Double_t low = g2->GetX()[0];
922 Double_t high = g2->GetX()[g2->GetN()-1];
923 if (low > high) { Double_t t = low; low = high; high = t; }
924 for (Int_t i = 0; i < nBins; i++) {
925 Double_t x = g1->GetX()[i];
926 if (x < low-dx || x > high+dx) continue;
927 Double_t c1 = g1->GetY()[i];
928 Double_t e1 = g1->GetErrorY(i);
929 Double_t c2 = g2->Eval(x);
931 h->SetBinContent(i+1, c1 / c2);
932 h->SetBinError(i+1, e1 / c2);
934 max = TMath::Max(RatioMax(h), max);
938 //__________________________________________________________________
939 TH1* Graph2Hist(const TGraphAsymmErrors* g) const
941 Int_t nBins = g->GetN();
942 TArrayF bins(nBins+1);
944 for (Int_t i = 0; i < nBins; i++) {
945 Double_t x = g->GetX()[i];
946 Double_t exl = g->GetEXlow()[i];
947 Double_t exh = g->GetEXhigh()[i];
948 bins.fArray[i] = x-exl;
949 bins.fArray[i+1] = x+exh;
950 Double_t dxi = exh+exl;
951 if (i == 0) dx = dxi;
952 else if (dxi != dx) dx = 0;
954 TString name(g->GetName());
955 TString title(g->GetTitle());
958 h = new TH1D(name.Data(), title.Data(), nBins, bins[0], bins[nBins]);
961 h = new TH1D(name.Data(), title.Data(), nBins, bins.fArray);
963 h->SetMarkerStyle(g->GetMarkerStyle());
964 h->SetMarkerColor(g->GetMarkerColor());
965 h->SetMarkerSize(g->GetMarkerSize());
969 //__________________________________________________________________
970 TH1* Asymmetry(TH1* h, Double_t& max)
974 TH1* ret = static_cast<TH1*>(h->Clone(Form("%s_leftright", h->GetName())));
975 // Int_t oBins = h->GetNbinsX();
976 // Double_t high = h->GetXaxis()->GetXmax();
977 // Double_t low = h->GetXaxis()->GetXmin();
978 // Double_t dBin = (high - low) / oBins;
979 // Int_t tBins = Int_t(2*high/dBin+.5);
980 // ret->SetBins(tBins, -high, high);
982 ret->SetTitle(Form("%s (+/-)", h->GetTitle()));
983 ret->SetYTitle("Right/Left");
984 Int_t nBins = h->GetNbinsX();
985 for (Int_t i = 1; i <= nBins; i++) {
986 Double_t x = h->GetBinCenter(i);
989 Double_t c1 = h->GetBinContent(i);
990 Double_t e1 = h->GetBinError(i);
991 if (c1 <= 0) continue;
993 Int_t j = h->FindBin(-x);
994 if (j <= 0 || j > nBins) continue;
996 Double_t c2 = h->GetBinContent(j);
997 Double_t e2 = h->GetBinError(j);
999 Double_t c12 = c1*c1;
1000 Double_t e = TMath::Sqrt((e2*e2*c1*c1+e1*e1*c2*c2)/(c12*c12));
1002 Int_t k = ret->FindBin(x);
1003 ret->SetBinContent(k, c2/c1);
1004 ret->SetBinError(k, e);
1006 max = TMath::Max(max, RatioMax(ret));
1012 //__________________________________________________________________
1016 Bool_t fShowLeftRight;
1021 TNamed* fTrigString;
1032 TH1* fForwardHHDSym;
1034 RangeParam* fRangeParam;
1038 //=== Stuff for auto zooming =========================================
1039 void UpdateRange(dNdetaDrawer::RangeParam* p)
1042 Warning("UpdateRange", "No parameters %p", p);
1045 if (!p->fMasterAxis) {
1046 Warning("UpdateRange", "No master axis %p", p->fMasterAxis);
1049 Int_t first = p->fMasterAxis->GetFirst();
1050 Int_t last = p->fMasterAxis->GetLast();
1051 Double_t x1 = p->fMasterAxis->GetBinCenter(first);
1052 Double_t x2 = p->fMasterAxis->GetBinCenter(last);
1053 //Info("UpdateRange", "Range set to [%3d,%3d]->[%f,%f]", first, last, x1,x2);
1055 if (p->fSlave1Axis) {
1056 Int_t i1 = p->fSlave1Axis->FindBin(x1);
1057 Int_t i2 = p->fSlave1Axis->FindBin(x2);
1058 p->fSlave1Axis->SetRange(i1, i2);
1059 p->fSlave1Pad->Modified();
1060 p->fSlave1Pad->Update();
1062 if (p->fSlave2Axis) {
1063 Int_t i1 = p->fSlave2Axis->FindBin(x1);
1064 Int_t i2 = p->fSlave2Axis->FindBin(x2);
1065 p->fSlave2Axis->SetRange(i1, i2);
1066 p->fSlave2Pad->Modified();
1067 p->fSlave2Pad->Update();
1069 TCanvas* c = gPad->GetCanvas();
1073 //____________________________________________________________________
1074 void RangeExec(dNdetaDrawer::RangeParam* p)
1081 // 11: Mouse release
1082 // dNdetaDrawer::RangeParam* p =
1083 // reinterpret_cast<dNdetaDrawer::RangeParam*>(addr);
1084 Int_t event = gPad->GetEvent();
1085 TObject *select = gPad->GetSelected();
1090 if (event != 11 || !select || select != p->fMasterAxis) return;
1094 //=== Steering function ==============================================
1096 DrawdNdeta(const char* filename="forward_dndeta.root",
1098 const char* title=""
1100 Bool_t cutEdges=false)
1104 d.SetCutEdges(cutEdges);
1107 d.SetShowOthers(flags & 0x1);
1108 d.SetShowAlice(flags & 0x2);
1109 d.SetShowRatios(flags & 0x4);
1110 d.SetShowLeftRight(flags & 0x8);