3 * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
4 * @date Wed Mar 23 14:07:10 2011
6 * @brief Script to visualise the dN/deta for pp and PbPb
8 * This script is independent of any AliROOT code - and should stay
11 * The script is <i>very</i> long - sigh - the joy of drawing
12 * things nicely in ROOT
14 * @ingroup pwglf_forward_dndeta
19 #include <TGraphErrors.h>
20 #include <TGraphAsymmErrors.h>
21 #include <TMultiGraph.h>
33 #include <TLegendEntry.h>
39 /** Systematic error color */
40 #define SYSERR_COLOR kBlue-10
41 /** Systematic error style */
42 #define SYSERR_STYLE 1001
44 Double_t myFunc(Double_t* xp, Double_t* pp);
47 * Class to draw dN/deta results
49 * @ingroup pwglf_forward_tasks_dndeta
50 * @ingroup pwglf_forward_dndeta
55 * POD of data for range zooming
59 TAxis* fMasterAxis; // Master axis
60 TAxis* fSlave1Axis; // First slave axis
61 TVirtualPad* fSlave1Pad; // First slave pad
62 TAxis* fSlave2Axis; // Second slave axis
63 TVirtualPad* fSlave2Pad; // Second slave pad
65 //__________________________________________________________________
72 fShowRatios(false), // Show ratios
73 fShowLeftRight(false), // Show asymmetry
74 fShowRings(false), // Show rings too
75 fExport(false), // Export data to script
76 fCutEdges(false), // Whether to cut edges
77 fRemoveOuters(false), // Whether to remove outers
78 fShowOthers(0), // Show other data
82 fRebin(0), // Rebinning factor
83 fFwdSysErr(0.076), // Systematic error in forward range
84 fCenSysErr(0), // Systematic error in central range
85 fTitle(""), // Title on plot
86 fClusterScale(""), // Scaling of clusters to tracklets
87 // Read (or set) information
88 fTrigString(0), // Trigger string (read, or set)
89 fNormString(0), // Normalisation string (read, or set)
90 fSNNString(0), // Energy string (read, or set)
91 fSysString(0), // Collision system string (read or set)
92 fVtxAxis(0), // Vertex cuts (read or set)
93 fCentAxis(0), // Centrality axis
95 fResults(0), // Stack of results
96 fRatios(0), // Stack of ratios
97 fLeftRight(0), // Left-right asymmetry
98 fOthers(0), // Older data
99 fTriggers(0), // Number of triggers
100 fTruth(0), // Pointer to truth
101 fRangeParam(0) // Parameter object for range zoom
103 fRangeParam = new RangeParam;
104 fRangeParam->fMasterAxis = 0;
105 fRangeParam->fSlave1Axis = 0;
106 fRangeParam->fSlave1Pad = 0;
107 fRangeParam->fSlave2Axis = 0;
108 fRangeParam->fSlave2Pad = 0;
113 dNdetaDrawer(const dNdetaDrawer&) {}
115 * Assignment operator
118 * @return Reference to this object
120 dNdetaDrawer& operator=(const dNdetaDrawer&) { return *this; }
122 //__________________________________________________________________
126 virtual ~dNdetaDrawer()
128 if (fRatios && fRatios->GetHists()) fRatios->GetHists()->Delete();
129 if (fResults && fResults->GetHists()) fResults->GetHists()->Delete();
131 if (fTrigString) { delete fTrigString; fTrigString = 0; }
132 if (fSNNString) { delete fSNNString; fSNNString = 0; }
133 if (fSysString) { delete fSysString; fSysString = 0; }
134 if (fVtxAxis) { delete fVtxAxis; fVtxAxis = 0; }
135 if (fCentAxis) { delete fCentAxis; fCentAxis = 0; }
136 if (fResults) { delete fResults; fResults = 0; }
137 if (fRatios) { delete fRatios; fRatios = 0; }
138 if (fOthers) { delete fOthers; fOthers = 0; }
139 if (fTriggers) { delete fTriggers; fTriggers = 0; }
143 //==================================================================
146 * @name Set parameters
149 * Show other (UA5, CMS, ...) data
151 * @param x Whether to show or not
153 void SetShowOthers(UShort_t x) { fShowOthers = x; }
154 //__________________________________________________________________
156 * Whether to show ratios or not. If there's nothing to compare to,
157 * the ratio panel will be implicitly disabled
159 * @param x Whether to show or not
161 void SetShowRatios(Bool_t x) { fShowRatios = x; }
162 //__________________________________________________________________
165 * Whether to show the left/right asymmetry
167 * @param x To show or not
169 void SetShowLeftRight(Bool_t x) { fShowLeftRight = x; }
170 //__________________________________________________________________
172 * Whether to show rings
174 * @param x To show or not
176 void SetShowRings(Bool_t x) { fShowRings = x; }
177 //__________________________________________________________________
179 * Whether to export results to a script
181 * @param x Wheter to export results to a script
183 void SetExport(Bool_t x) { fExport = x; }
184 //__________________________________________________________________
186 * Set the rebinning factor
188 * @param x Rebinning factor (must be a divisor in the number of bins)
190 void SetRebin(UShort_t x) { fRebin = x; }
191 //__________________________________________________________________
193 * Wheter to cut away the edges
195 * @param x Whether or not to cut away edges
197 void SetCutEdges(Bool_t x) { fCutEdges = x; }
198 //__________________________________________________________________
200 * Set the title of the plot
204 void SetTitle(TString x) { fTitle = x; }
205 //__________________________________________________________________
207 * Set the systematic error in the forward region
209 * @param e Systematic error in the forward region
211 void SetForwardSysError(Double_t e=0) { fFwdSysErr = e; }
212 //__________________________________________________________________
214 * Set the systematic error in the forward region
216 * @param e Systematic error in the forward region
218 void SetCentralSysError(Double_t e=0) { fCenSysErr = e; }
219 void SetForceMB(Bool_t force=true) { fForceMB = force; }
220 void SetMirror(Bool_t mirror=true) { fMirror = mirror; }
221 void SetFinalMC(const TString& file) { fFinalMC = file; }
222 void SetEmpirical(const TString& file) { fEmpirical = file; }
224 //==================================================================
227 * @name Override settings from input
230 * Override setting from file
232 * @param sNN Center of mass energy per nucleon pair (GeV)
234 void SetSNN(UShort_t sNN)
236 fSNNString = new TNamed("sNN", Form("%04dGeV", sNN));
237 fSNNString->SetUniqueID(sNN);
239 //__________________________________________________________________
241 * Set the collision system
245 * @param sys collision system
247 void SetSys(UShort_t sys)
249 fSysString = new TNamed("sys", (sys == 1 ? "pp" :
253 fSysString->SetUniqueID(sys);
255 //__________________________________________________________________
257 * Set the vertex range in centimeters
259 * @param vzMin Min @f$ v_z@f$
260 * @param vzMax Max @f$ v_z@f$
262 void SetVertexRange(Double_t vzMin, Double_t vzMax)
264 fVtxAxis = new TAxis(10, vzMin, vzMax);
265 fVtxAxis->SetName("vtxAxis");
266 fVtxAxis->SetTitle(Form("v_{z}#in[%+5.1f,%+5.1f]cm", vzMin, vzMax));
268 //__________________________________________________________________
269 void SetTrigger(UShort_t trig)
271 fTrigString = new TNamed("trigString", (trig & 0x1 ? "INEL" :
272 trig & 0x2 ? "INEL>0" :
275 fTrigString->SetUniqueID(trig);
279 //==================================================================
282 * @name Main steering functions
285 * Run the code to produce the final result.
287 * @param filename File containing the data
289 void Run(const char* filename="forward_dndeta.root")
291 Double_t max = 0, rmax=0, amax=0;
293 gStyle->SetPalette(1);
295 // --- Open input file -------------------------------------------
296 TFile* file = TFile::Open(filename, "READ");
298 Error("Open", "Cannot open %s", filename);
301 // --- Get forward list ------------------------------------------
302 TList* forward = static_cast<TList*>(file->Get("ForwardResults"));
304 Error("Open", "Couldn't find list ForwardResults");
307 // --- Get information on the run --------------------------------
308 FetchInformation(forward);
309 // --- Set the macro pathand load other data script --------------
310 gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWGLF/FORWARD/analysis2",
311 gROOT->GetMacroPath()));
312 gROOT->LoadMacro("OtherData.C");
314 // --- Get the central results -----------------------------------
315 TList* clusters = static_cast<TList*>(file->Get("CentralResults"));
316 if (!clusters) Warning("Open", "Couldn't find list CentralResults");
318 // --- Get the central results -----------------------------------
319 TList* mcTruth = static_cast<TList*>(file->Get("MCTruthResults"));
320 if (!mcTruth) Warning("Open", "Couldn't find list MCTruthResults");
322 // --- Make our containtes ---------------------------------------
323 fResults = new THStack("results", "Results");
324 fRatios = new THStack("ratios", "Ratios");
325 fLeftRight = new THStack("asymmetry", "Left-right asymmetry");
326 fOthers = new TMultiGraph();
328 // --- Try to open the final MC file, and find relevant lists ----
329 TList* forwardMC = 0;
330 TList* centralMC = 0;
331 if (!fFinalMC.IsNull()) {
332 TFile* finalMC = TFile::Open(fFinalMC, "READ");
334 Warning("Run", "Failed to open file %s for final MC corrections",
338 forwardMC = static_cast<TList*>(finalMC->Get("ForwardResults"));
340 Warning("Open", "Couldn't find list ForwardResults for final MC");
341 centralMC = static_cast<TList*>(finalMC->Get("CentralResults"));
343 Warning("Open", "Couldn't find list CentralResults for final MC");
346 if (!forwardMC) fFinalMC = "";
348 // --- Try to get the emperical correction -----------------------
349 TGraphErrors* empCorr = 0;
350 if (!fEmpirical.IsNull()) {
351 TFile* empirical = TFile::Open(fEmpirical, "READ");
353 Warning("Run", "Failed to open file %s for empirical corrections",
357 empCorr = static_cast<TGraphErrors*>(empirical->Get("average"));
359 Warning("Open", "couldn't get the empirical correction");
362 if (!empCorr) fEmpirical = "";
364 // --- Loop over input data --------------------------------------
366 FetchResults(mcTruth, 0, 0, "MCTruth", max, rmax, amax,truths);
367 TObjArray* fwdA = FetchResults(forward, forwardMC, empCorr, "Forward",
368 max, rmax, amax,truths);
369 TObjArray* cenA = FetchResults(clusters, 0, 0, "Central",
370 max, rmax, amax,truths);
372 // --- Get trigger information -----------------------------------
373 TList* sums = static_cast<TList*>(file->Get("ForwardSums"));
375 TList* all = static_cast<TList*>(sums->FindObject("all"));
377 fTriggers = FetchResult(all, "triggers");
378 if (!fTriggers) all->ls();
381 Warning("Run", "List all not found in ForwardSums");
386 Warning("Run", "No ForwardSums directory found in %s", file->GetName());
390 // --- Check our stacks ------------------------------------------
391 if (!fResults->GetHists() ||
392 fResults->GetHists()->GetEntries() <= 0) {
393 Error("Run", "No histograms in result stack!");
396 if (!fOthers->GetListOfGraphs() ||
397 fOthers->GetListOfGraphs()->GetEntries() <= 0) {
398 Warning("Run", "No other data found - disabling that");
401 if (!fRatios->GetHists() ||
402 fRatios->GetHists()->GetEntries() <= 0) {
403 Warning("Run", "No ratio data found - disabling that");
407 if (!fLeftRight->GetHists() ||
408 fLeftRight->GetHists()->GetEntries() <= 0) {
409 Warning("Run", "No left/right data found - disabling that");
411 fShowLeftRight = false;
413 if (fFwdSysErr > 0) {
414 if (fCenSysErr <= 0) fCenSysErr = fFwdSysErr;
415 for (Int_t i = 0; i < fwdA->GetEntriesFast(); i++) {
416 TH1* fwd = static_cast<TH1*>(fwdA->At(i));
417 TH1* cen = static_cast<TH1*>(cenA->At(i));
421 TH1* tmp = Merge(cen, fwd, low, high);
422 TF1* f = FitMerged(tmp, low, high);
423 MakeSysError(tmp, cen, fwd, f);
425 Info("", "Adding systematic error histogram %s",
427 fResults->GetHists()->AddFirst(tmp, "e5");
429 if (!fMirror) continue;
431 TH1* tmp2 = Symmetrice(tmp);
432 tmp2->SetFillColor(tmp->GetFillColor());
433 tmp2->SetFillStyle(tmp->GetFillStyle());
434 tmp2->SetMarkerStyle(tmp->GetMarkerStyle());
435 tmp2->SetLineWidth(tmp->GetLineWidth());
436 fResults->GetHists()->AddFirst(tmp2, "e5");
437 fResults->Modified();
443 // --- Close the input file --------------------------------------
448 // --- Plot results ----------------------------------------------
449 Plot(max, rmax, amax);
452 //__________________________________________________________________
454 * Fetch the information on the run from the results list
456 * @param results Results list
458 void FetchInformation(const TList* results)
461 fTrigString = static_cast<TNamed*>(results->FindObject("trigger"));
463 fNormString = static_cast<TNamed*>(results->FindObject("scheme"));
465 fSNNString = static_cast<TNamed*>(results->FindObject("sNN"));
467 fSysString = static_cast<TNamed*>(results->FindObject("sys"));
469 fVtxAxis = static_cast<TAxis*>(results->FindObject("vtxAxis"));
471 fCentAxis = static_cast<TAxis*>(results->FindObject("centAxis"));
473 TNamed* options = static_cast<TAxis*>(results->FindObject("options"));
474 if (!fTrigString) fTrigString = new TNamed("trigger", "unknown");
475 if (!fNormString) fNormString = new TNamed("scheme", "unknown");
476 if (!fSNNString) fSNNString = new TNamed("sNN", "unknown");
477 if (!fSysString) fSysString = new TNamed("sys", "unknown");
479 fVtxAxis = new TAxis(1,0,0);
480 fVtxAxis->SetName("vtxAxis");
481 fVtxAxis->SetTitle("v_{z} range unspecified");
484 TString centTxt("none");
486 Int_t nCent = fCentAxis->GetNbins();
487 centTxt = Form("%d bins", nCent);
488 for (Int_t i = 0; i <= nCent; i++)
489 centTxt.Append(Form("%c%d", i == 0 ? ' ' : '-',
490 int(fCentAxis->GetXbins()->At(i))));
492 Info("FetchInformation",
494 " Trigger: %-30s (%d)\n"
495 " sqrt(sNN): %-30s (%dGeV)\n"
496 " System: %-30s (%d)\n"
497 " Vz range: %-30s (%f,%f)\n"
498 " Normalization: %-30s (%d)\n"
501 fTrigString->GetTitle(), fTrigString->GetUniqueID(),
502 fSNNString->GetTitle(), fSNNString->GetUniqueID(),
503 fSysString->GetTitle(), fSysString->GetUniqueID(),
504 fVtxAxis->GetTitle(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax(),
505 fNormString->GetTitle(), fNormString->GetUniqueID(),
506 centTxt.Data(), (options ? options->GetTitle() : "none"));
508 //__________________________________________________________________
509 TMultiGraph* FetchOthers(UShort_t centLow, UShort_t centHigh)
511 TMultiGraph* thisOther = 0;
512 if (fShowOthers == 0) return 0;
514 UShort_t sys = (fSysString ? fSysString->GetUniqueID() : 0);
515 UShort_t trg = (fTrigString ? fTrigString->GetUniqueID() : 0);
516 UShort_t snn = (fSNNString ? fSNNString->GetUniqueID() : 0);
517 Long_t ret = gROOT->ProcessLine(Form("GetData(%d,%d,%d,%d,%d,%d);",
523 thisOther = reinterpret_cast<TMultiGraph*>(ret);
526 //__________________________________________________________________
528 * Get the results from the top-level list
532 * @param max On return, maximum of data
533 * @param rmax On return, maximum of ratios
534 * @param amax On return, maximum of left-right comparisons
536 * @return Array of results
539 FetchResults(const TList* list,
541 TGraphErrors* empCorr,
549 UShort_t n = HasCent() ? fCentAxis->GetNbins() : 0;
550 // Info("FetchResults","got %d centrality bins", n);
552 TH1* h = FetchOne(list, mcList, empCorr, name, "all",
553 FetchOthers(0,0), -1000, 0,
554 max, rmax, amax, fTruth);
556 TObjArray* a = new TObjArray;
557 // Info("FetchResults", "Adding %s to result stack", h->GetName());
562 TObjArray* a = new TObjArray;
564 for (UShort_t i = 0; i < n; i++) {
565 UShort_t centLow = fCentAxis->GetBinLowEdge(i+1);
566 UShort_t centHigh = fCentAxis->GetBinUpEdge(i+1);
567 TString lname = Form("cent%03d_%03d", centLow, centHigh);
568 Int_t col = GetCentralityColor(i+1);
569 TString centTxt = Form("%3d%%-%3d%% central", centLow, centHigh);
571 TH1* tt = static_cast<TH1*>(truths.At(i));
573 TH1* h = FetchOne(list, mcList, empCorr, name, lname,
574 FetchOthers(centLow,centHigh), col,
575 centTxt.Data(), max, rmax, amax, fTruth);
578 //Info("FetchResults", "old truth=%p new truth=%p (%s)", ot, tt, name);
581 // Info("FetchResults", "Adding %p to result stack", h);
586 //__________________________________________________________________
588 * Get the color for a centrality bin
590 * @param bin Centrality bin
594 Int_t GetCentralityColor(Int_t bin) const
596 if (fCentAxis->GetNbins() < 6) {
598 case 1: return kRed+2;
599 case 2: return kGreen+2;
600 case 3: return kBlue+1;
601 case 4: return kCyan+1;
602 case 5: return kMagenta+1;
603 case 6: return kYellow+2;
606 UShort_t centLow = fCentAxis->GetBinLowEdge(bin);
607 UShort_t centHigh = fCentAxis->GetBinUpEdge(bin);
608 Float_t fc = (centLow+double(centHigh-centLow)/2) / 100;
609 Int_t nCol = gStyle->GetNumberOfColors();
610 Int_t icol = TMath::Min(nCol-1,int(fc * nCol + .5));
611 Int_t col = gStyle->GetColorPalette(icol);
612 //Info("GetCentralityColor","%3d: %3d-%3d -> %3d",bin,centLow,centHigh,col);
615 //__________________________________________________________________
617 * Set attributed on a histogram
622 void SetAttributes(TH1* h, Int_t color)
625 if (color < 0) return;
626 // h->SetLineColor(color);
627 h->SetMarkerColor(color);
628 // h->SetFillColor(color);
630 //__________________________________________________________________
632 * Set attributed on a graph
637 void SetAttributes(TGraph* g, Int_t color)
640 if (color < 0) return;
641 // g->SetLineColor(color);
642 g->SetMarkerColor(color);
643 // g->SetFillColor(color);
645 //__________________________________________________________________
650 void ModifyTitle(TNamed* h, const char* /*centTxt*/)
654 TString title(h->GetTitle());
655 title.ReplaceAll("ALICE ","");
656 if (title.Contains("Central"))
657 title.ReplaceAll("Central", "SPD clusters");
658 if (title.Contains("Forward"))
659 title.ReplaceAll("Forward", "FMD");
664 // if (!centTxt || !h) return;
665 // h->SetTitle(Form("%s, %s", h->GetTitle(), centTxt));
667 //__________________________________________________________________
668 TH1* FetchOne(const TList* list,
670 TGraphErrors* empCorr,
672 const char* folderName,
681 TList* folder = static_cast<TList*>(list->FindObject(folderName));
683 Error("FetchResults", "Couldn't find list '%s' in %s",
684 folderName, list->GetName());
689 mcFolder = static_cast<TList*>(mcList->FindObject(folderName));
691 Warning("FetchResults",
692 "Didn't find the list '%s' in %s for final MC correction",
693 folderName, mcList->GetName());
695 TH1* h = FetchResults(folder, mcFolder, empCorr, name,
696 others, col, txt, max, rmax, amax, truth);
699 //__________________________________________________________________
701 * Fetch results for a particular centrality bin
705 * @param thisOther Other graphs
707 * @param centTxt Centrality text
708 * @param max On return, data maximum
709 * @param rmax On return, ratio maximum
710 * @param amax On return, left-right maximum
712 * @return Histogram of results
714 TH1* FetchResults(const TList* list,
716 TGraphErrors* empCorr,
718 TMultiGraph* thisOther,
727 TH1* dndeta = FetchResult(list, Form("dndeta%s", name));
728 TH1* dndetaMC = FetchResult(list, Form("dndeta%sMC", name));
729 TH1* dndetaTruth = FetchResult(list, "dndetaTruth");
731 if (mcList && FetchResult(mcList, "finalMCCorr"))
732 Warning("FetchResults", "dNdeta already corrected for final MC");
734 CorrectFinalMC(dndeta, mcList);
736 CorrectEmpirical(dndeta, empCorr);
739 TH1* dndetaMCSym = 0;
740 SetAttributes(dndeta, color);
741 SetAttributes(dndetaMC, HasCent() ? color : color+2);
742 SetAttributes(dndetaTruth,color);
743 SetAttributes(dndetaSym, color);
744 SetAttributes(dndetaMCSym,HasCent() ? color : color+2);
745 if (dndetaMC && HasCent())
746 dndetaMC->SetMarkerStyle(dndetaMC->GetMarkerStyle()+2);
747 if (dndetaMCSym && HasCent())
748 dndetaMCSym->SetMarkerStyle(dndetaMCSym->GetMarkerStyle()+2);
749 if (dndetaTruth && HasCent()) {
750 dndetaTruth->SetMarkerStyle(34);
751 dndetaTruth->SetMarkerColor(kYellow-1);
754 dndetaTruth->SetLineColor(kBlack);
755 dndetaTruth->SetFillColor(kBlack);
756 dndetaTruth->SetFillStyle(3002);
757 // dndetaTruth->SetLineColor(kBlack);
759 ModifyTitle(dndeta, centTxt);
760 ModifyTitle(dndetaMC, centTxt);
761 ModifyTitle(dndetaTruth,centTxt);
762 ModifyTitle(dndetaSym, centTxt);
763 ModifyTitle(dndetaMCSym,centTxt);
766 max = TMath::Max(max, AddHistogram(fResults, dndetaTruth, "e5"));
767 max = TMath::Max(max, AddHistogram(fResults, dndetaMC, dndetaMCSym));
768 max = TMath::Max(max, AddHistogram(fResults, dndeta, dndetaSym));
775 THStack* rings = static_cast<THStack*>(list->FindObject("dndetaRings"));
777 TIter next(rings->GetHists());
779 while ((hist = static_cast<TH1*>(next())))
780 max = TMath::Max(max, AddHistogram(fResults, hist));
783 // Info("FetchResults", "Got %p, %p, %p from %s with name %s, max=%f",
784 // dndeta, dndetaMC, dndetaTruth, list->GetName(), name, max);
786 if (fShowLeftRight) {
787 fLeftRight->Add(Asymmetry(dndeta, amax));
788 fLeftRight->Add(Asymmetry(dndetaMC, amax));
792 TIter next(thisOther->GetListOfGraphs());
794 while ((g = static_cast<TGraph*>(next()))) {
795 fRatios->Add(Ratio(dndeta, g, rmax));
796 fRatios->Add(Ratio(dndetaSym, g, rmax));
797 SetAttributes(g, color);
798 ModifyTitle(g, centTxt);
799 if (!fOthers->GetListOfGraphs() ||
800 !fOthers->GetListOfGraphs()->FindObject(g->GetName())) {
801 max = TMath::Max(max,TMath::MaxElement(g->GetN(), g->GetY()));
805 // fOthers->Add(thisOther);
809 fRatios->Add(Ratio(dndeta, dndetaMC, rmax));
810 fRatios->Add(Ratio(dndetaSym, dndetaMCSym, rmax));
813 fRatios->Add(Ratio(dndeta, truth, rmax));
814 fRatios->Add(Ratio(dndetaSym, truth, rmax));
818 //__________________________________________________________________
819 void CorrectFinalMC(TH1* dndeta, const TList* mcList)
824 TH1* dndetaMC = FetchResult(mcList, dndeta->GetName());
825 TH1* dndetaTruth = FetchResult(mcList, "dndetaTruth");
826 if (!dndetaMC || !dndetaTruth) return;
828 TH1* corr = static_cast<TH1*>(dndetaMC->Clone("finalMCCorr"));
829 corr->Divide(dndetaTruth);
831 Info("CorrectFinalMC", "Correcting dN/deta with final MC correction");
832 dndeta->Divide(corr);
834 //__________________________________________________________________
835 void CorrectEmpirical(TH1* dndeta, const TGraphErrors* empCorr)
838 if (!empCorr) return;
840 Info("CorrectEmpirical", "Doing empirical correction of dN/deta");
841 TAxis* xAxis = dndeta->GetXaxis();
842 for (Int_t i = 1; i <= xAxis->GetNbins(); i++) {
843 Double_t x = xAxis->GetBinCenter(i);
844 Double_t y = dndeta->GetBinContent(i);
845 Double_t c = empCorr->Eval(x);
846 dndeta->SetBinContent(i, y / c);
850 //__________________________________________________________________
853 * @param max Max value
854 * @param rmax Maximum diviation from 1 of ratios
855 * @param amax Maximum diviation from 1 of asymmetries
857 void Plot(Double_t max,
861 gStyle->SetOptTitle(0);
862 gStyle->SetTitleFont(132, "xyz");
863 gStyle->SetLabelFont(132, "xyz");
866 Int_t w = 800; // h / TMath::Sqrt(2);
870 if (!fShowRatios) w *= 1.3;
872 if (!fShowLeftRight) w *= 1.3;
875 y1 = (y11 > 0.0001 ? 0.4 : 0.2);
876 y2 = (y11 > 0.0001 ? 0.2 : 0.3);
878 TCanvas* c = new TCanvas("Results", "Results", w, h);
883 PlotResults(max, y1);
886 PlotRatios(rmax, y2, y1);
889 PlotLeftRight(amax, y3, y2);
893 Int_t vMin = fVtxAxis->GetXmin();
894 Int_t vMax = fVtxAxis->GetXmax();
895 TString trg(fTrigString->GetTitle());
897 if (fTriggers) nev = fTriggers->GetBinContent(1);
898 trg = trg.Strip(TString::kBoth);
899 trg.ReplaceAll(" ", "_");
900 trg.ReplaceAll(">", "Gt");
901 TString base(Form("dndeta_%s_%s_%s_%c%02d%c%02dcm_%09dev",
902 fSysString->GetTitle(),
903 fSNNString->GetTitle(),
905 vMin < 0 ? 'm' : 'p', TMath::Abs(vMin),
906 vMax < 0 ? 'm' : 'p', TMath::Abs(vMax),
908 c->SaveAs(Form("%s.png", base.Data()));
909 c->SaveAs(Form("%s.root", base.Data()));
910 c->SaveAs(Form("%s.C", base.Data()));
911 base.ReplaceAll("dndeta", "export");
914 //__________________________________________________________________
918 * @param stack Stack to include
919 * @param mg (optional) Multi graph to include
920 * @param x1 Lower X coordinate in the range [0,1]
921 * @param y1 Lower Y coordinate in the range [0,1]
922 * @param x2 Upper X coordinate in the range [0,1]
923 * @param y2 Upper Y coordinate in the range [0,1]
925 void BuildLegend(THStack* stack, TMultiGraph* mg,
926 Double_t x1, Double_t y1, Double_t x2, Double_t y2,
929 TLegend* l = new TLegend(x1,y1,x2,y2);
930 Int_t nCol = forceCol;
931 if (nCol <= 0) nCol = HasCent() ? 1 : 2;
932 l->SetNColumns(nCol);
938 // Loop over items in stack and get unique items, while ignoring
939 // mirrored data and systematic error bands
940 TIter next(stack->GetHists());
944 Bool_t sysErrSeen = false;
945 while ((hist = static_cast<TH1*>(next()))) {
946 TString t(hist->GetTitle());
947 TString n(hist->GetName());
949 if (t.Contains("mirrored")) continue;
950 if (n.Contains("syserror")) { sysErrSeen = true; continue; }
951 if (unique.FindObject(t.Data())) continue;
952 TObjString* s1 = new TObjString(hist->GetTitle());
953 s1->SetUniqueID(((hist->GetMarkerStyle() & 0xFFFF) << 16) |
954 ((hist->GetMarkerColor() & 0xFFFF) << 0));
956 // l->AddEntry(hist, hist->GetTitle(), "pl");
959 // If we have other stuff, scan for unique names
960 TIter nexto(mg->GetListOfGraphs());
962 while ((g = static_cast<TGraph*>(nexto()))) {
963 TString n(g->GetTitle());
964 if (n.Contains("mirrored")) continue;
965 if (unique.FindObject(n.Data())) continue;
966 TObjString* s2 = new TObjString(n);
967 s2->SetUniqueID(((g->GetMarkerStyle() & 0xFFFF) << 16) |
968 ((g->GetMarkerColor() & 0xFFFF) << 0));
970 // l->AddEntry(hist, hist->GetTitle(), "pl");
974 // Add legend entries for unique items only
975 TIter nextu(&unique);
978 while ((s = nextu())) {
979 TLegendEntry* dd = l->AddEntry(Form("data%2d", i++),
981 Int_t style = (s->GetUniqueID() >> 16) & 0xFFFF;
982 Int_t color = (s->GetUniqueID() >> 0) & 0xFFFF;
983 dd->SetLineColor(kBlack);
984 if (HasCent()) dd->SetMarkerColor(kBlack);
985 else dd->SetMarkerColor(color);
986 dd->SetMarkerStyle(style);
989 // Add entry for systematic errors
990 TLegendEntry* d0 = l->AddEntry("d0", Form("%4.1f%% Systematic error",
991 100*fFwdSysErr), "f");
992 d0->SetLineColor(SYSERR_COLOR);
993 d0->SetMarkerColor(SYSERR_COLOR);
994 d0->SetFillColor(SYSERR_COLOR);
995 d0->SetFillStyle(SYSERR_STYLE);
996 d0->SetMarkerStyle(0);
1000 if (nCol == 2 && i % 2 == 1) {
1001 // To make sure the 'data' and 'mirrored' entries are on a line
1003 TLegendEntry* dd = l->AddEntry("dd", " ", "");
1005 dd->SetFillStyle(0);
1006 dd->SetFillColor(0);
1007 dd->SetLineWidth(0);
1008 dd->SetLineColor(0);
1009 dd->SetMarkerSize(0);
1012 // Add entry for 'data'
1013 TLegendEntry* d1 = l->AddEntry("d1", "Data", "lp");
1014 d1->SetLineColor(kBlack);
1015 d1->SetMarkerColor(kBlack);
1016 d1->SetMarkerStyle(20);
1018 // Add entry for 'mirrored data'
1019 TLegendEntry* d2 = l->AddEntry("d2", "Mirrored data", "lp");
1020 d2->SetLineColor(kBlack);
1021 d2->SetMarkerColor(kBlack);
1022 d2->SetMarkerStyle(24);
1027 //__________________________________________________________________
1029 * Build centrality legend
1031 * @param x1 Lower X coordinate in the range [0,1]
1032 * @param y1 Lower Y coordinate in the range [0,1]
1033 * @param x2 Upper X coordinate in the range [0,1]
1034 * @param y2 Upper Y coordinate in the range [0,1]
1036 void BuildCentLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
1038 if (!HasCent()) return;
1040 TLegend* l = new TLegend(x1,y1,x2,y2);
1044 l->SetBorderSize(0);
1045 l->SetTextFont(132);
1047 Int_t n = fCentAxis->GetNbins();
1048 for (Int_t i = 1; i <= n; i++) {
1049 Double_t low = fCentAxis->GetBinLowEdge(i);
1050 Double_t upp = fCentAxis->GetBinUpEdge(i);
1051 TLegendEntry* e = l->AddEntry(Form("dummy%02d", i),
1052 Form("%3d%% - %3d%%",
1053 int(low), int(upp)), "pl");
1054 e->SetMarkerColor(GetCentralityColor(i));
1058 //__________________________________________________________________
1062 * @param max Maximum
1063 * @param yd Bottom position of pad
1065 void PlotResults(Double_t max, Double_t yd)
1067 // Make a sub-pad for the result itself
1068 TPad* p1 = new TPad("p1", "p1", 0, yd, 1.0, 1.0, 0, 0, 0);
1069 p1->SetTopMargin(0.05);
1070 p1->SetBorderSize(0);
1071 p1->SetBorderMode(0);
1072 p1->SetBottomMargin(yd > 0.001 ? 0.001 : 0.1);
1073 p1->SetRightMargin(0.03);
1074 if (fShowLeftRight || fShowRatios) p1->SetGridx();
1080 // Info("PlotResults", "Plotting results with max=%f", max);
1081 fResults->SetMaximum(1.15*max);
1082 fResults->SetMinimum(yd > 0.00001 ? -0.02*max : 0);
1084 FixAxis(fResults, (1-yd)*(yd > .001 ? 1 : .9 / 1.2),
1085 "#font[12]{#frac{1}{N} "
1086 "#frac{dN_{#font[132]{ch}}}{d#font[152]{#eta}}}");
1089 fResults->DrawClone("nostack e1");
1091 fRangeParam->fSlave1Axis = fResults->GetXaxis();
1092 fRangeParam->fSlave1Pad = p1;
1095 if (fShowOthers != 0) {
1096 TGraphAsymmErrors* o = 0;
1097 TIter nextG(fOthers->GetListOfGraphs());
1098 while ((o = static_cast<TGraphAsymmErrors*>(nextG())))
1099 o->DrawClone("same p");
1102 // Make a legend in the main result pad
1103 BuildCentLegend(.12, 1-p1->GetTopMargin()-.01-.5,
1104 .35, 1-p1->GetTopMargin()-.01-.1);
1105 Double_t x1 = (HasCent() ? .7 : .15);
1106 Double_t x2 = (HasCent() ? 1-p1->GetRightMargin()-.01: .90);
1107 Double_t y1 = (HasCent() ? .5: p1->GetBottomMargin()+.01);
1108 Double_t y2 = (HasCent() ? 1-p1->GetTopMargin()-.01-.15 : .35);
1110 BuildLegend(fResults, fOthers, x1, y1, x2, y2);
1112 // Put a title on top
1113 fTitle.ReplaceAll("@", " ");
1114 TLatex* tit = new TLatex(0.10, 0.95, fTitle.Data());
1116 tit->SetTextFont(132);
1117 tit->SetTextSize(0.05);
1120 Int_t aliceBlue = TColor::GetColor(41,73,156);
1121 // Put a nice label in the plot
1123 UShort_t snn = fSNNString->GetUniqueID();
1124 const char* sys = fSysString->GetTitle();
1125 if (snn == 2750) snn = 2760;
1126 if (snn > 1000) eS = Form("%4.2fTeV", float(snn)/1000);
1127 else eS = Form("%3dGeV", snn);
1128 TLatex* tt = new TLatex(.93, .93, Form("%s #sqrt{s%s}=%s, %s",
1130 (HasCent() ? "_{NN}" : ""),
1132 HasCent() ? "by centrality" :
1133 fTrigString->GetTitle()));
1134 tt->SetTextColor(aliceBlue);
1136 tt->SetTextFont(132);
1137 tt->SetTextAlign(33);
1140 // Put number of accepted events on the plot
1142 if (fTriggers) nev = fTriggers->GetBinContent(1);
1143 TLatex* et = new TLatex(.93, .83, Form("%d events", nev));
1144 et->SetTextColor(aliceBlue);
1146 et->SetTextFont(132);
1147 et->SetTextAlign(33);
1150 // Put number of accepted events on the plot
1152 TLatex* vt = new TLatex(.93, .88, fVtxAxis->GetTitle());
1154 vt->SetTextFont(132);
1155 vt->SetTextAlign(33);
1156 vt->SetTextColor(aliceBlue);
1159 // results->Draw("nostack e1 same");
1162 if (!fEmpirical.IsNull()) corrs.Append("Emperical");
1163 if (!fFinalMC.IsNull()) {
1164 if (!corrs.IsNull()) corrs.Append("+");
1165 corrs.Append("Final MC");
1168 if (!corrs.IsNull()) {
1169 corrs.Append(" correction");
1170 if (corrs.Index("+") != kNPOS) corrs.Append("s");
1171 TLatex* em = new TLatex(.93, .79, corrs);
1173 em->SetTextFont(132);
1174 em->SetTextAlign(33);
1175 em->SetTextColor(aliceBlue);
1179 fRangeParam->fSlave1Axis = FindXAxis(p1, fResults->GetName());
1180 fRangeParam->fSlave1Pad = p1;
1183 // Mark the plot as preliminary
1184 TLatex* pt = new TLatex(.12, .93, "Work in progress");
1186 pt->SetTextFont(22);
1187 // pt->SetTextSize();
1188 pt->SetTextColor(TColor::GetColor(234,26,46));
1189 pt->SetTextAlign(13);
1192 const char* logos[] = { "ALICE.png", "FMD.png", 0 };
1193 const char** logo = logos;
1195 if (gSystem->AccessPathName(*logo)) {
1199 TPad* pad = new TPad("logo", "logo", .12, .7, .25, .9, 0, 0, 0);
1200 pad->SetFillStyle(0);
1203 TImage* i = TImage::Create();
1204 i->ReadImage(*logo);
1210 //__________________________________________________________________
1214 * @param max Maximum diviation from 1
1215 * @param y1 Lower y coordinate of pad
1216 * @param y2 Upper y coordinate of pad
1218 void PlotRatios(Double_t max, Double_t y1, Double_t y2)
1220 if (fShowRatios == 0) return;
1222 bool isBottom = (y1 < 0.0001);
1223 Double_t yd = y2 - y1;
1224 // Make a sub-pad for the result itself
1225 TPad* p2 = new TPad("p2", "p2", 0, y1, 1.0, y2, 0, 0, 0);
1226 p2->SetTopMargin(0.001);
1227 p2->SetRightMargin(0.03);
1228 p2->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
1236 FixAxis(fRatios, yd, "Ratios", 7);
1238 fRatios->SetMaximum(1+TMath::Max(.22,1.05*max));
1239 fRatios->SetMinimum(1-TMath::Max(.32,1.05*max));
1241 fRatios->DrawClone("nostack e1");
1245 BuildLegend(fRatios, 0, .15,p2->GetBottomMargin()+.01,.9,
1246 isBottom ? .6 : .4, 2);
1248 TLegend* l2 = p2->BuildLegend(.15,p2->GetBottomMargin()+.01,.9,
1249 isBottom ? .6 : .4);
1251 l2->SetFillColor(0);
1252 l2->SetFillStyle(0);
1253 l2->SetBorderSize(0);
1254 l2->SetTextFont(132);
1256 // Make a nice band from 0.9 to 1.1
1257 TGraphErrors* band = new TGraphErrors(2);
1258 band->SetPoint(0, fResults->GetXaxis()->GetXmin(), 1);
1259 band->SetPoint(1, fResults->GetXaxis()->GetXmax(), 1);
1260 band->SetPointError(0, 0, .1);
1261 band->SetPointError(1, 0, .1);
1262 band->SetFillColor(kYellow+2);
1263 band->SetFillStyle(3002);
1264 band->SetLineStyle(2);
1265 band->SetLineWidth(1);
1266 band->Draw("3 same");
1267 band->DrawClone("X L same");
1269 // Replot the ratios on top
1270 fRatios->DrawClone("nostack e1 same");
1273 fRangeParam->fMasterAxis = FindXAxis(p2, fRatios->GetName());
1274 p2->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)",
1278 fRangeParam->fSlave2Axis = FindXAxis(p2, fRatios->GetName());
1279 fRangeParam->fSlave2Pad = p2;
1282 //__________________________________________________________________
1284 * Plot the asymmetries
1286 * @param max Maximum diviation from 1
1287 * @param y1 Lower y coordinate of pad
1288 * @param y2 Upper y coordinate of pad
1290 void PlotLeftRight(Double_t max, Double_t y1, Double_t y2)
1292 if (!fShowLeftRight) return;
1294 bool isBottom = (y1 < 0.0001);
1295 Double_t yd = y2 - y1;
1296 // Make a sub-pad for the result itself
1297 TPad* p3 = new TPad("p3", "p3", 0, y1, 1.0, y2, 0, 0, 0);
1298 p3->SetTopMargin(0.001);
1299 p3->SetRightMargin(0.03);
1300 p3->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
1308 FixAxis(fLeftRight, yd, "Right/Left", 4);
1310 fLeftRight->SetMaximum(1+TMath::Max(.12,1.05*max));
1311 fLeftRight->SetMinimum(1-TMath::Max(.15,1.05*max));
1313 fLeftRight->DrawClone("nostack e1");
1317 Double_t xx1 = (HasCent() ? .7 : .15);
1318 Double_t xx2 = (HasCent() ? 1-p3->GetRightMargin()-.01 : .90);
1319 Double_t yy1 = p3->GetBottomMargin()+.01;
1320 Double_t yy2 = (HasCent() ? 1-p3->GetTopMargin()-.01-.15 : .5);
1321 BuildLegend(fLeftRight, 0, xx1, yy1, xx2, yy2);
1322 // TLegend* l2 = p3->BuildLegend(.15,p3->GetBottomMargin()+.01,.9,.5);
1323 // l2->SetNColumns(2);
1324 // l2->SetFillColor(0);
1325 // l2->SetFillStyle(0);
1326 // l2->SetBorderSize(0);
1327 // l2->SetTextFont(132);
1329 // Make a nice band from 0.9 to 1.1
1330 TGraphErrors* band = new TGraphErrors(2);
1331 band->SetPoint(0, fResults->GetXaxis()->GetXmin(), 1);
1332 band->SetPoint(1, fResults->GetXaxis()->GetXmax(), 1);
1333 band->SetPointError(0, 0, .05);
1334 band->SetPointError(1, 0, .05);
1335 band->SetFillColor(kYellow+2);
1336 band->SetFillStyle(3002);
1337 band->SetLineStyle(2);
1338 band->SetLineWidth(1);
1339 band->Draw("3 same");
1340 band->DrawClone("X L same");
1342 fLeftRight->DrawClone("nostack e1 same");
1344 fRangeParam->fMasterAxis = FindXAxis(p3, fLeftRight->GetName());
1345 p3->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)",
1349 fRangeParam->fSlave2Axis = FindXAxis(p3, fLeftRight->GetName());
1350 fRangeParam->fSlave2Pad = p3;
1354 //==================================================================
1357 * @name Data utility functions
1360 * Get a result from the passed list
1362 * @param list List to search
1363 * @param name Object name to search for
1367 TH1* FetchResult(const TList* list, const char* name) const
1369 if (!list) return 0;
1371 TH1* ret = static_cast<TH1*>(list->FindObject(name));
1375 Warning("GetResult", "Histogram %s not found", name);
1381 //__________________________________________________________________
1383 * Add a histogram to the stack after possibly rebinning it
1385 * @param stack Stack to add to
1386 * @param hist histogram
1387 * @param option Draw options
1389 * @return Maximum of histogram
1391 Double_t AddHistogram(THStack* stack, TH1* hist, Option_t* option="") const
1393 // Check if we have input
1394 if (!hist) return 0;
1399 stack->Add(hist, option);
1400 return hist->GetMaximum();
1402 //__________________________________________________________________
1404 * Add a histogram to the stack after possibly rebinning it
1406 * @param stack Stack to add to
1407 * @param hist histogram
1408 * @param option Draw options
1409 * @param sym On return, the data symmetriced (added to stack)
1411 * @return Maximum of histogram
1413 Double_t AddHistogram(THStack* stack, TH1* hist, TH1*& sym,
1414 Option_t* option="") const
1416 // Check if we have input
1417 if (!hist) return 0;
1421 stack->Add(hist, option);
1423 // Now symmetrice the histogram
1425 sym = Symmetrice(hist);
1426 stack->Add(sym, option);
1429 return hist->GetMaximum();
1432 //__________________________________________________________________
1436 * @param h Histogram to rebin
1438 virtual void Rebin(TH1* h) const
1440 if (fRebin <= 1) return;
1442 Int_t nBins = h->GetNbinsX();
1443 if(nBins % fRebin != 0) {
1444 Warning("Rebin", "Rebin factor %d is not a devisor of current number "
1445 "of bins %d in the histogram %s", fRebin, nBins, h->GetName());
1450 TH1* tmp = static_cast<TH1*>(h->Clone("tmp"));
1452 tmp->SetDirectory(0);
1454 // The new number of bins
1455 Int_t nBinsNew = nBins / fRebin;
1456 for(Int_t i = 1;i<= nBinsNew; i++) {
1457 Double_t content = 0;
1461 for(Int_t j = 1; j<=fRebin;j++) {
1462 Int_t bin = (i-1)*fRebin + j;
1463 Double_t c = h->GetBinContent(bin);
1465 if (c <= 0) continue;
1468 if (h->GetBinContent(bin+1)<=0 ||
1469 h->GetBinContent(bin-1)) {
1470 Warning("Rebin", "removing bin %d=%f of %s (%d=%f,%d=%f)",
1471 bin, c, h->GetName(),
1472 bin+1, h->GetBinContent(bin+1),
1473 bin-1, h->GetBinContent(bin-1));
1477 Double_t e = h->GetBinError(bin);
1478 Double_t w = 1 / (e*e); // 1/c/c
1485 if(content > 0 && nbins > 1 ) {
1486 tmp->SetBinContent(i, wsum / sumw);
1487 tmp->SetBinError(i,1./TMath::Sqrt(sumw));
1491 // Finally, rebin the histogram, and set new content
1494 for(Int_t i = 1; i<= nBinsNew; i++) {
1495 h->SetBinContent(i,tmp->GetBinContent(i));
1496 h->SetBinError(i, tmp->GetBinError(i));
1501 //__________________________________________________________________
1503 * Make an extension of @a h to make it symmetric about 0
1505 * @param h Histogram to symmertrice
1507 * @return Symmetric extension of @a h
1509 TH1* Symmetrice(const TH1* h) const
1511 Int_t nBins = h->GetNbinsX();
1512 TH1* s = static_cast<TH1*>(h->Clone(Form("%s_mirror", h->GetName())));
1513 s->SetTitle(Form("%s (mirrored)", h->GetTitle()));
1515 s->SetBins(nBins, -h->GetXaxis()->GetXmax(), -h->GetXaxis()->GetXmin());
1516 s->SetMarkerColor(h->GetMarkerColor());
1517 s->SetMarkerSize(h->GetMarkerSize());
1518 s->SetMarkerStyle(h->GetMarkerStyle()+4);
1519 s->SetFillColor(h->GetFillColor());
1520 s->SetFillStyle(h->GetFillStyle());
1523 // Find the first and last bin with data
1524 Int_t first = nBins+1;
1526 for (Int_t i = 1; i <= nBins; i++) {
1527 if (h->GetBinContent(i) <= 0) continue;
1528 first = TMath::Min(first, i);
1529 last = TMath::Max(last, i);
1532 Double_t xfirst = h->GetBinCenter(first-1);
1533 Int_t f1 = h->GetXaxis()->FindBin(-xfirst);
1534 Int_t l2 = s->GetXaxis()->FindBin(xfirst);
1535 for (Int_t i = f1, j=l2; i <= last; i++,j--) {
1536 s->SetBinContent(j, h->GetBinContent(i));
1537 s->SetBinError(j, h->GetBinError(i));
1539 // Fill in overlap bin
1540 s->SetBinContent(l2+1, h->GetBinContent(first));
1541 s->SetBinError(l2+1, h->GetBinError(first));
1544 //__________________________________________________________________
1546 * Calculate the left-right asymmetry of input histogram
1548 * @param h Input histogram
1549 * @param max On return, the maximum distance from 1 of the histogram
1553 TH1* Asymmetry(TH1* h, Double_t& max)
1557 TH1* ret = static_cast<TH1*>(h->Clone(Form("%s_leftright", h->GetName())));
1558 // Int_t oBins = h->GetNbinsX();
1559 // Double_t high = h->GetXaxis()->GetXmax();
1560 // Double_t low = h->GetXaxis()->GetXmin();
1561 // Double_t dBin = (high - low) / oBins;
1562 // Int_t tBins = Int_t(2*high/dBin+.5);
1563 // ret->SetBins(tBins, -high, high);
1564 ret->SetDirectory(0);
1566 ret->SetTitle(Form("%s (+/-)", h->GetTitle()));
1567 ret->SetYTitle("Right/Left");
1568 Int_t nBins = h->GetNbinsX();
1569 for (Int_t i = 1; i <= nBins; i++) {
1570 Double_t x = h->GetBinCenter(i);
1573 Double_t c1 = h->GetBinContent(i);
1574 Double_t e1 = h->GetBinError(i);
1575 if (c1 <= 0) continue;
1577 Int_t j = h->FindBin(-x);
1578 if (j <= 0 || j > nBins) continue;
1580 Double_t c2 = h->GetBinContent(j);
1581 Double_t e2 = h->GetBinError(j);
1583 Double_t c12 = c1*c1;
1584 Double_t e = TMath::Sqrt((e2*e2*c1*c1+e1*e1*c2*c2)/(c12*c12));
1586 Int_t k = ret->FindBin(x);
1587 ret->SetBinContent(k, c2/c1);
1588 ret->SetBinError(k, e);
1590 max = TMath::Max(max, RatioMax(ret));
1594 //__________________________________________________________________
1596 * Transform a graph into a histogram
1602 TH1* Graph2Hist(const TGraphAsymmErrors* g) const
1604 Int_t nBins = g->GetN();
1605 TArrayF bins(nBins+1);
1607 for (Int_t i = 0; i < nBins; i++) {
1608 Double_t x = g->GetX()[i];
1609 Double_t exl = g->GetEXlow()[i];
1610 Double_t exh = g->GetEXhigh()[i];
1611 bins.fArray[i] = x-exl;
1612 bins.fArray[i+1] = x+exh;
1613 Double_t dxi = exh+exl;
1614 if (i == 0) dx = dxi;
1615 else if (dxi != dx) dx = 0;
1617 TString name(g->GetName());
1618 TString title(g->GetTitle());
1621 h = new TH1D(name.Data(), title.Data(), nBins, bins[0], bins[nBins]);
1624 h = new TH1D(name.Data(), title.Data(), nBins, bins.fArray);
1626 h->SetMarkerStyle(g->GetMarkerStyle());
1627 h->SetMarkerColor(g->GetMarkerColor());
1628 h->SetMarkerSize(g->GetMarkerSize());
1633 //==================================================================
1636 * @name Ratio utility functions
1639 * Get the maximum diviation from 1 in the passed ratio
1641 * @param h Ratio histogram
1643 * @return Max diviation from 1
1645 Double_t RatioMax(TH1* h) const
1647 Int_t nBins = h->GetNbinsX();
1649 for (Int_t i = 1; i <= nBins; i++) {
1650 Double_t c = h->GetBinContent(i);
1651 if (c == 0) continue;
1652 Double_t e = h->GetBinError(i);
1653 Double_t d = TMath::Abs(1-c-e);
1654 ret = TMath::Max(d, ret);
1658 //__________________________________________________________________
1660 * Make the ratio of h1 to h2
1662 * @param o1 First object (numerator)
1663 * @param o2 Second object (denominator)
1664 * @param max Maximum diviation from 1
1668 TH1* Ratio(const TObject* o1, const TObject* o2, Double_t& max) const
1670 if (!o1 || !o2) return 0;
1673 const TAttMarker* m1 = 0;
1674 const TAttMarker* m2 = 0;
1675 const TH1* h1 = dynamic_cast<const TH1*>(o1);
1678 const TH1* h2 = dynamic_cast<const TH1*>(o2);
1684 const TGraph* g2 = dynamic_cast<const TGraph*>(o2);
1692 const TGraphAsymmErrors* g1 = dynamic_cast<const TGraphAsymmErrors*>(o1);
1695 const TGraphAsymmErrors* g2 =
1696 dynamic_cast<const TGraphAsymmErrors*>(o2);
1699 r = RatioGG(g1, g2);
1704 Warning("Ratio", "Don't know how to divide a %s (%s) with a %s (%s)",
1705 o1->ClassName(), o1->GetName(), o2->ClassName(), o2->GetName());
1708 // Check that the histogram isn't empty
1709 if (r->GetEntries() <= 0) {
1714 r->SetMarkerStyle(m2->GetMarkerStyle());
1715 r->SetMarkerColor(m1->GetMarkerColor());
1716 if (TString(o2->GetName()).Contains("truth", TString::kIgnoreCase))
1717 r->SetMarkerStyle(m1->GetMarkerStyle());
1718 r->SetMarkerSize(0.9*m1->GetMarkerSize());
1719 r->SetName(Form("%s_over_%s", o1->GetName(), o2->GetName()));
1720 r->SetTitle(Form("%s / %s", o1->GetTitle(), o2->GetTitle()));
1722 max = TMath::Max(RatioMax(r), max);
1727 //__________________________________________________________________
1729 * Compute the ratio of @a h to @a g. @a g is evaluated at the bin
1732 * @param h Numerator
1737 TH1* RatioHG(const TH1* h, const TGraph* g) const
1739 if (!h || !g) return 0;
1741 TH1* ret = static_cast<TH1*>(h->Clone("tmp"));
1743 Double_t xlow = g->GetX()[0];
1744 Double_t xhigh = g->GetX()[g->GetN()-1];
1745 if (xlow > xhigh) { Double_t t = xhigh; xhigh = xlow; xlow = t; }
1747 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
1748 Double_t c = h->GetBinContent(i);
1749 if (c <= 0) continue;
1751 Double_t x = h->GetBinCenter(i);
1752 if (x < xlow || x > xhigh) continue;
1754 Double_t f = g->Eval(x);
1755 if (f <= 0) continue;
1757 ret->SetBinContent(i, c / f);
1758 ret->SetBinError(i, h->GetBinError(i) / f);
1762 //__________________________________________________________________
1764 * Make the ratio of h1 to h2
1766 * @param h1 First histogram (numerator)
1767 * @param h2 Second histogram (denominator)
1771 TH1* RatioHH(const TH1* h1, const TH1* h2) const
1773 if (!h1 || !h2) return 0;
1774 TH1* t1 = static_cast<TH1*>(h1->Clone("tmp"));
1778 //__________________________________________________________________
1780 * Calculate the ratio of two graphs - g1 / g2
1782 * @param g1 Numerator
1783 * @param g2 Denominator
1785 * @return g1 / g2 in a histogram
1787 TH1* RatioGG(const TGraphAsymmErrors* g1,
1788 const TGraphAsymmErrors* g2) const
1790 Int_t nBins = g1->GetN();
1791 TArrayF bins(nBins+1);
1793 for (Int_t i = 0; i < nBins; i++) {
1794 Double_t x = g1->GetX()[i];
1795 Double_t exl = g1->GetEXlow()[i];
1796 Double_t exh = g1->GetEXhigh()[i];
1797 bins.fArray[i] = x-exl;
1798 bins.fArray[i+1] = x+exh;
1799 Double_t dxi = exh+exl;
1800 if (i == 0) dx = dxi;
1801 else if (dxi != dx) dx = 0;
1805 h = new TH1F("tmp", "tmp", nBins, bins[0], bins[nBins]);
1808 h = new TH1F("tmp", "tmp", nBins, bins.fArray);
1811 Double_t low = g2->GetX()[0];
1812 Double_t high = g2->GetX()[g2->GetN()-1];
1813 if (low > high) { Double_t t = low; low = high; high = t; }
1814 for (Int_t i = 0; i < nBins; i++) {
1815 Double_t x = g1->GetX()[i];
1816 if (x < low-dx || x > high+dx) continue;
1817 Double_t c1 = g1->GetY()[i];
1818 Double_t e1 = g1->GetErrorY(i);
1819 Double_t c2 = g2->Eval(x);
1821 h->SetBinContent(i+1, c1 / c2);
1822 h->SetBinError(i+1, e1 / c2);
1827 //==================================================================
1830 * @name Graphics utility functions
1833 * Find an X axis in a pad
1836 * @param name Histogram to find axis for
1838 * @return Found axis or null
1840 TAxis* FindXAxis(TVirtualPad* p, const char* name)
1842 TObject* o = p->GetListOfPrimitives()->FindObject(name);
1844 Warning("FindXAxis", "%s not found in pad", name);
1847 THStack* stack = dynamic_cast<THStack*>(o);
1849 Warning("FindXAxis", "%s is not a THStack", name);
1852 if (!stack->GetHistogram()) {
1853 Warning("FindXAxis", "%s has no histogram", name);
1856 TAxis* ret = stack->GetHistogram()->GetXaxis();
1860 //__________________________________________________________________
1862 * Fix the apperance of the axis in a stack
1864 * @param stack stack of histogram
1865 * @param yd How the canvas is cut
1866 * @param ytitle Y axis title
1867 * @param ynDiv Divisions on Y axis
1868 * @param force Whether to draw the stack first or not
1870 void FixAxis(THStack* stack, Double_t yd, const char* ytitle,
1871 Int_t ynDiv=210, Bool_t force=true)
1874 Warning("FixAxis", "No stack passed for %s!", ytitle);
1877 if (force) stack->Draw("nostack e1");
1879 TH1* h = stack->GetHistogram();
1881 Warning("FixAxis", "Stack %s has no histogram", stack->GetName());
1884 Double_t s = 1/yd/1.2;
1885 // Info("FixAxis", "for %s, s=1/%f=%f", stack->GetName(), yd, s);
1887 h->SetXTitle("#font[152]{#eta}");
1888 h->SetYTitle(ytitle);
1889 TAxis* xa = h->GetXaxis();
1890 TAxis* ya = h->GetYaxis();
1892 // Int_t npixels = 20
1893 // Float_t dy = gPad->AbsPixeltoY(0) - gPad->AbsPixeltoY(npixels);
1894 // Float_t ts = dy/(gPad->GetY2() - gPad->GetY1());
1897 // xa->SetTitle(h->GetXTitle());
1898 // xa->SetTicks("+-");
1899 xa->SetTitleSize(s*xa->GetTitleSize());
1900 xa->SetLabelSize(s*xa->GetLabelSize());
1901 xa->SetTickLength(s*xa->GetTickLength());
1902 // xa->SetTitleOffset(xa->GetTitleOffset()/s);
1904 if (stack != fResults) {
1905 TAxis* rxa = fResults->GetXaxis();
1906 xa->Set(rxa->GetNbins(), rxa->GetXmin(), rxa->GetXmax());
1910 // ya->SetTitle(h->GetYTitle());
1912 // ya->SetTicks("+-");
1913 ya->SetNdivisions(ynDiv);
1914 ya->SetTitleSize(s*ya->GetTitleSize());
1915 ya->SetTitleOffset(ya->GetTitleOffset()/s);
1916 ya->SetLabelSize(s*ya->GetLabelSize());
1919 //__________________________________________________________________
1921 * Merge two histograms into one
1923 * @param cen Central part
1924 * @param fwd Forward part
1925 * @param xlow On return, lower eta bound
1926 * @param xhigh On return, upper eta bound
1928 * @return Newly allocated histogram or null
1931 Merge(const TH1* cen, const TH1* fwd, Double_t& xlow, Double_t& xhigh)
1933 TH1* tmp = static_cast<TH1*>(fwd->Clone("tmp"));
1934 TString name(fwd->GetName());
1935 name.ReplaceAll("Forward", "Merged");
1938 // tmp->SetMarkerStyle(28);
1939 // tmp->SetMarkerColor(kBlack);
1940 tmp->SetDirectory(0);
1943 for (Int_t i = 1; i <= tmp->GetNbinsX(); i++) {
1944 Double_t cc = cen->GetBinContent(i);
1945 Double_t cf = fwd->GetBinContent(i);
1946 Double_t ec = cen->GetBinError(i);
1947 Double_t ef = fwd->GetBinError(i);
1950 if (cc < 0.001 && cf < 0.01) continue;
1951 xlow = TMath::Min(tmp->GetXaxis()->GetBinLowEdge(i),xlow);
1952 xhigh = TMath::Max(tmp->GetXaxis()->GetBinUpEdge(i),xhigh);
1958 ne = TMath::Sqrt(ec*ec + ef*ef);
1961 tmp->SetBinContent(i, nc);
1962 tmp->SetBinError(i, ne);
1966 //____________________________________________________________________
1968 * Fit @f$g(x;A_1,A_2,\sigma_1,\sigma_2)@f$ to histogram data
1970 * @param tmp Histogram
1971 * @param xlow Lower x bound
1972 * @param xhigh Upper x bound
1974 * @return Fitted function
1977 FitMerged(TH1* tmp, Double_t xlow, Double_t xhigh)
1979 TF1* tmpf = new TF1("tmpf", "gaus", xlow, xhigh);
1980 tmp->Fit(tmpf, "NQ", "");
1981 tmp->SetDirectory(0);
1983 TF1* fit = new TF1("f", myFunc, xlow, xhigh, 4);
1984 fit->SetParNames("a_{1}", "a_{2}", "#sigma_{1}", "#sigma_{2}");
1985 fit->SetParameters(tmpf->GetParameter(0),
1987 tmpf->GetParameter(2),
1988 tmpf->GetParameter(2)/4);
1989 fit->SetParLimits(3, 0, 100);
1990 fit->SetParLimits(4, 0, 100);
1991 tmp->Fit(fit,"0W","");
1996 //____________________________________________________________________
1998 * Make band of systematic errors
2000 * @param tmp Histogram
2001 * @param cen Central
2002 * @param fwd Forward
2006 MakeSysError(TH1* tmp, TH1* cen, TH1* fwd, TF1* fit)
2008 for (Int_t i = 1; i <= tmp->GetNbinsX(); i++) {
2009 Double_t tc = tmp->GetBinContent(i);
2010 if (tc < 0.01) continue;
2011 Double_t fc = fwd->GetBinContent(i);
2012 Double_t cc = cen->GetBinContent(i);
2013 Double_t sysErr = fFwdSysErr;
2014 if (cc > .01 && fc > 0.01)
2015 sysErr = (fFwdSysErr+fCenSysErr) / 2;
2017 sysErr = fCenSysErr;
2018 Double_t x = tmp->GetXaxis()->GetBinCenter(i);
2019 Double_t y = fit->Eval(x);
2020 tmp->SetBinContent(i, y);
2021 tmp->SetBinError(i,sysErr*y);
2023 TString name(tmp->GetName());
2024 name.ReplaceAll("Merged", "SysError");
2026 tmp->SetMarkerColor(SYSERR_COLOR);
2027 tmp->SetLineColor(SYSERR_COLOR);
2028 tmp->SetFillColor(SYSERR_COLOR);
2029 tmp->SetFillStyle(SYSERR_STYLE);
2030 tmp->SetMarkerStyle(0);
2031 tmp->SetLineWidth(0);
2033 void CorrectForward(TH1* h) const
2035 if (!fRemoveOuters) return;
2037 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
2038 Double_t eta = h->GetBinCenter(i);
2039 if (TMath::Abs(eta) < 2.3) {
2040 h->SetBinContent(i, 0);
2041 h->SetBinError(i, 0);
2045 void CorrectCentral(TH1* h) const
2047 if (fClusterScale.IsNull()) return;
2048 TString t(h->GetTitle());
2049 Info("CorrectCentral", "Replacing Central with Tracklets in %s", t.Data());
2050 t.ReplaceAll("Central", "Tracklets");
2053 TF1* cf = new TF1("clusterScale", fClusterScale);
2054 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
2055 Double_t eta = h->GetBinCenter(i);
2056 Double_t f = cf->Eval(eta);
2057 Double_t c = h->GetBinContent(i);
2059 h->SetBinContent(i, c / f);
2063 //____________________________________________________________________
2064 void Export(const char* basename)
2066 TString bname(basename);
2067 bname.ReplaceAll(" ", "_");
2068 bname.ReplaceAll("-", "_");
2069 TString fname(Form("%s.C", bname.Data()));
2071 std::ofstream outf(fname.Data());
2073 Error("Export", "Failed to open output file %s", fname.Data());
2076 outf << "// Create by dNdetaDrawer\n"
2077 << "void " << bname << "(THStack* stack, TLegend* l, Int_t m)\n"
2079 << " Int_t ma[] = { 24, 25, 26, 32,\n"
2080 << " 20, 21, 22, 33,\n"
2081 << " 34, 30, 29, 0, \n"
2083 << " Int_t mm = ((m < 20 || m > 34) ? 0 : ma[m-20]);\n\n";
2084 TList* hists = fResults->GetHists();
2087 while ((hist = static_cast<TH1*>(next()))) {
2088 TString hname = hist->GetName();
2089 hname.Append(Form("_%04x", (gRandom->Integer(0xffff) & 0xffff)));
2090 hist->SetName(hname);
2091 hist->GetListOfFunctions()->Clear();
2092 hist->SavePrimitive(outf, "nodraw");
2093 bool mirror = hname.Contains("mirror");
2094 bool syserr = hname.Contains("SysError");
2096 outf << " " << hname << "->SetMarkerStyle("
2097 << (mirror ? "mm" : "m") << ");\n";
2099 outf << " " << hname << "->SetMarkerStyle(1);\n";
2100 outf << " stack->Add(" << hname
2101 << (syserr ? ",\"e5\"" : "") << ");\n\n";
2103 UShort_t snn = fSNNString->GetUniqueID();
2104 // const char* sys = fSysString->GetTitle();
2106 if (snn == 2750) snn = 2760;
2107 if (snn < 1000) eS = Form("%3dGeV", snn);
2108 else if (snn % 1000 == 0) eS = Form("%dTeV", snn/1000);
2109 else eS = Form("%4.2fTeV", float(snn)/1000);
2110 outf << " if (l) {\n"
2111 << " TLegendEntry* e = l->AddEntry(\"\",\"" << eS << "\",\"pl\");\n"
2112 << " e->SetMarkerStyle(m);\n"
2113 << " e->SetMarkerColor(kBlack);\n"
2115 << "}\n" << std::endl;
2118 Bool_t HasCent() const { return fCentAxis && !fForceMB; }
2122 //__________________________________________________________________
2127 Bool_t fShowRatios; // Show ratios
2128 Bool_t fShowLeftRight;// Show asymmetry
2129 Bool_t fShowRings; // Show rings too
2130 Bool_t fExport; // Export results to file
2131 Bool_t fCutEdges; // Whether to cut edges
2132 Bool_t fRemoveOuters; // Whether to remove outers
2133 UShort_t fShowOthers; // Show other data
2134 Bool_t fMirror; // Whether to mirror
2135 Bool_t fForceMB; // Force min-bias
2141 UShort_t fRebin; // Rebinning factor
2142 Double_t fFwdSysErr; // Systematic error in forward range
2143 Double_t fCenSysErr; // Systematic error in central range
2144 TString fTitle; // Title on plot
2145 TString fClusterScale; // Scaling of clusters to tracklets
2146 TString fFinalMC; // Final MC correction file name
2147 TString fEmpirical; // Empirical correction file name
2151 * @name Read (or set) information
2153 TNamed* fTrigString; // Trigger string (read, or set)
2154 TNamed* fNormString; // Normalisation string (read, or set)
2155 TNamed* fSNNString; // Energy string (read, or set)
2156 TNamed* fSysString; // Collision system string (read or set)
2157 TAxis* fVtxAxis; // Vertex cuts (read or set)
2158 TAxis* fCentAxis; // Centrality axis
2162 * @name Resulting plots
2164 THStack* fResults; // Stack of results
2165 THStack* fRatios; // Stack of ratios
2166 THStack* fLeftRight; // Left-right asymmetry
2167 TMultiGraph* fOthers; // Older data
2168 TH1* fTriggers; // Number of triggers
2169 TH1* fTruth; // Pointer to truth
2171 RangeParam* fRangeParam; // Parameter object for range zoom
2174 //____________________________________________________________________
2176 * Function to calculate
2178 * g(x;A_1,A_2,\sigma_1,\sigma_2) =
2179 * A_1\left(\frac{1}{2\pi\sigma_1}e^{(x/\sigma_1)^2} -
2180 * A_2\frac{1}{2\pi\sigma_2}e^{(x/\sigma_2)^2}\right)
2183 * @param xp Pointer to x array
2184 * @param pp Pointer to parameter array
2186 * @return @f$g(x;A_1,A_2,\sigma_1,\sigma_2)@f$
2188 Double_t myFunc(Double_t* xp, Double_t* pp)
2191 Double_t a1 = pp[0];
2192 Double_t a2 = pp[1];
2193 Double_t s1 = pp[2];
2194 Double_t s2 = pp[3];
2195 return a1*(TMath::Gaus(x, 0, s1) - a2 * TMath::Gaus(x, 0, s2));
2198 //=== Stuff for auto zooming =========================================
2200 * Update canvas range
2202 * @param p Parameter
2204 void UpdateRange(dNdetaDrawer::RangeParam* p)
2207 Warning("UpdateRange", "No parameters %p", p);
2210 if (!p->fMasterAxis) {
2211 Warning("UpdateRange", "No master axis %p", p->fMasterAxis);
2214 Int_t first = p->fMasterAxis->GetFirst();
2215 Int_t last = p->fMasterAxis->GetLast();
2216 Double_t x1 = p->fMasterAxis->GetBinCenter(first);
2217 Double_t x2 = p->fMasterAxis->GetBinCenter(last);
2219 if (p->fSlave1Axis) {
2220 Int_t i1 = p->fSlave1Axis->FindBin(x1);
2221 Int_t i2 = p->fSlave1Axis->FindBin(x2);
2222 p->fSlave1Axis->SetRange(i1, i2);
2223 p->fSlave1Pad->Modified();
2224 p->fSlave1Pad->Update();
2226 if (p->fSlave2Axis) {
2227 Int_t i1 = p->fSlave2Axis->FindBin(x1);
2228 Int_t i2 = p->fSlave2Axis->FindBin(x2);
2229 p->fSlave2Axis->SetRange(i1, i2);
2230 p->fSlave2Pad->Modified();
2231 p->fSlave2Pad->Update();
2233 TCanvas* c = gPad->GetCanvas();
2237 //____________________________________________________________________
2239 * Called when user changes X range
2241 * @param p Parameter
2243 void RangeExec(dNdetaDrawer::RangeParam* p)
2250 // 11: Mouse release
2251 // dNdetaDrawer::RangeParam* p =
2252 // reinterpret_cast<dNdetaDrawer::RangeParam*>(addr);
2253 Int_t event = gPad->GetEvent();
2254 TObject *select = gPad->GetSelected();
2259 if (event != 11 || !select || select != p->fMasterAxis) return;
2263 //=== Steering functions
2264 //==============================================
2266 * Display usage information
2272 Info("DrawdNdeta", "Usage: DrawdNdeta(FILE,TITLE,REBIN,OTHERS,FLAGS)\n\n"
2273 " const char* FILE File name to open (\"forward_root\")\n"
2274 " const char* TITLE Title to put on plot (\"\")\n"
2275 " UShort_t REBIN Rebinning factor (1)\n"
2276 " UShort_t OTHERS Other data to draw - more below (0x7)\n"
2277 " UShort_t FLAGS Visualisation flags - more below (0x7)\n\n"
2278 " OTHERS is a bit mask of\n\n"
2279 " 0x1 Show UA5 data (INEL,NSD, ppbar, 900GeV)\n"
2280 " 0x2 Show CMS data (NSD, pp)\n"
2281 " 0x4 Show published ALICE data (INEL,INEL>0,NSD, pp)\n"
2282 " 0x8 Show event genertor data\n\n"
2283 " FLAGS is a bit mask of\n\n"
2284 " 0x1 Show ratios of data to other data and possibly MC\n"
2285 " 0x2 Show left-right asymmetry\n"
2286 " 0x4 Show systematic error band\n"
2287 " 0x8 Show individual ring results (INEL only)\n"
2288 " 0x10 Cut edges when rebinning\n"
2289 " 0x20 Remove FMDxO points\n"
2290 " 0x40 Do not make our own canvas\n"
2291 " 0x80 Force use of MB\n"
2292 " 0x100 Mirror data\n"
2293 " 0x200 Apply `final MC' correction\n"
2294 " 0x400 Apply `Emperical' correction\n\n"
2295 "0x200 requires the file forward_dndetamc.root\n"
2296 "0x400 requires the file EmpiricalCorrection.root\n"
2300 //____________________________________________________________________
2302 * Draw @f$ dN/d\eta@f$
2304 * @param filename File name
2305 * @param title Title
2306 * @param rebin Rebinning factor
2307 * @param others What other data to show
2308 * @param flags Flags
2309 * @param sNN (optional) Collision energy [GeV]
2310 * @param sys (optional) Collision system (1: pp, 2: PbPb)
2311 * @param trg (optional) Trigger (1: INEL, 2: INEL>0, 4: NSD)
2312 * @param vzMin Least @f$ v_z@f$
2313 * @param vzMax Largest @f$ v_z@f$
2315 * @ingroup pwglf_forward_dndeta
2318 DrawdNdeta(const char* filename="forward_dndeta.root",
2319 const char* title="",
2321 UShort_t others=0x7,
2322 UShort_t flags=0x187,
2329 TString fname(filename);
2331 if (fname.CompareTo("help") == 0 ||
2332 fname.CompareTo("--help") == 0) {
2336 dNdetaDrawer* pd = new dNdetaDrawer;
2337 dNdetaDrawer& d = *pd;
2340 d.SetShowOthers(others);
2341 d.SetShowRatios(flags & 0x1);
2342 d.SetShowLeftRight(flags & 0x2);
2343 d.SetForwardSysError(flags & 0x4 ? 0.076 : 0);
2344 d.SetShowRings(flags & 0x8);
2345 d.SetCutEdges(flags & 0x10);
2346 d.fRemoveOuters = (flags & 0x20);
2347 d.SetExport(flags & 0x40);
2348 d.SetForceMB(flags & 0x80);
2349 d.SetMirror(flags & 0x100);
2350 d.SetFinalMC(flags & 0x200 ? "forward_dndetamc.root" : "");
2351 d.SetEmpirical(flags & 0x400 ? "EmpiricalCorrection.root" : "");
2352 // d.fClusterScale = "1.06 -0.003*x +0.0119*x*x";
2353 // Do the below if your input data does not contain these settings
2354 if (sNN > 0) d.SetSNN(sNN); // Collision energy per nucleon pair (GeV)
2355 if (sys > 0) d.SetSys(sys); // Collision system (1:pp, 2:PbPB)
2356 if (trg > 0) d.SetTrigger(trg); // Collision trigger (1:INEL, 2:INEL>0, 4:NSD)
2357 if (vzMin < 999 && vzMax > -999)
2358 d.SetVertexRange(vzMin,vzMax); // Collision vertex range (cm)
2361 //____________________________________________________________________