]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/FORWARD/analysis2/DrawdNdeta.C
Use new sub-algos to do hits from track-refs
[u/mrichter/AliRoot.git] / PWG2 / FORWARD / analysis2 / DrawdNdeta.C
CommitLineData
e1f47419 1/**
ffca499d 2 * @file DrawdNdeta.C
3 * @author Christian Holm Christensen <cholm@dalsgaard.hehi.nbi.dk>
4 * @date Wed Mar 23 14:07:10 2011
5 *
5bb5d1f6 6 * @brief Script to visualise the dN/deta for pp and PbPb
e1f47419 7 *
ffca499d 8 * This script is independent of any AliROOT code - and should stay
9 * that way.
10 *
5bb5d1f6 11 * The script is <emph>very</emph> long - sigh - the joy of drawing
12 * things nicely in ROOT
ffca499d 13 *
14 * @ingroup pwg2_forward_dndeta
e1f47419 15 */
b2e7f2d6 16#include <TH1.h>
17#include <THStack.h>
18#include <TGraphErrors.h>
19#include <TGraphAsymmErrors.h>
20#include <TMultiGraph.h>
21#include <TFile.h>
22#include <TList.h>
23#include <TString.h>
24#include <TError.h>
25#include <TSystem.h>
26#include <TROOT.h>
27#include <TMath.h>
28#include <TCanvas.h>
29#include <TPad.h>
30#include <TStyle.h>
31#include <TLegend.h>
32#include <TLegendEntry.h>
33#include <TLatex.h>
34#include <TImage.h>
35
2f92ff0e 36/**
37 * Class to draw dN/deta results
38 *
ffca499d 39 * @ingroup pwg2_forward_tasks_dndeta
40 * @ingroup pwg2_forward_dndeta
2f92ff0e 41 */
b2e7f2d6 42struct dNdetaDrawer
43{
2f92ff0e 44 /**
45 * POD of data for range zooming
46 */
b2e7f2d6 47 struct RangeParam
48 {
49 TAxis* fMasterAxis; // Master axis
50 TAxis* fSlave1Axis; // First slave axis
51 TVirtualPad* fSlave1Pad; // First slave pad
52 TAxis* fSlave2Axis; // Second slave axis
53 TVirtualPad* fSlave2Pad; // Second slave pad
54 };
55 //__________________________________________________________________
2f92ff0e 56 /**
57 * Constructor
58 *
59 */
b2e7f2d6 60 dNdetaDrawer()
61 : fShowOthers(false), // Bool_t
62 fShowAlice(false), // Bool_t
63 fShowRatios(false), // Bool_t
64 fShowLeftRight(false), // Bool_t
65 fRebin(5), // UShort_t
66 fCutEdges(false), // Bool_t
67 fTitle(""), // TString
b2e7f2d6 68 fTrigString(0), // TNamed*
0be6c8cd 69 fNormString(0), // TNamed*
b2e7f2d6 70 fSNNString(0), // TNamed*
71 fSysString(0), // TNamed*
72 fVtxAxis(0), // TAxis*
ffca499d 73 fCentAxis(0), // TAxis*
b2e7f2d6 74 fTriggers(0), // TH1*
75 fRangeParam(0)
76
77 {
78 fRangeParam = new RangeParam;
79 fRangeParam->fMasterAxis = 0;
80 fRangeParam->fSlave1Axis = 0;
81 fRangeParam->fSlave1Pad = 0;
82 fRangeParam->fSlave2Axis = 0;
83 fRangeParam->fSlave2Pad = 0;
84 }
ffca499d 85 //__________________________________________________________________
86 virtual ~dNdetaDrawer()
87 {
88 if (fRatios && fRatios->GetHists()) fRatios->GetHists()->Delete();
89 if (fResults && fResults->GetHists()) fResults->GetHists()->Delete();
90
91 if (fTrigString) { delete fTrigString; fTrigString = 0; }
92 if (fSNNString) { delete fSNNString; fSNNString = 0; }
93 if (fSysString) { delete fSysString; fSysString = 0; }
94 if (fVtxAxis) { delete fVtxAxis; fVtxAxis = 0; }
95 if (fCentAxis) { delete fCentAxis; fCentAxis = 0; }
96 if (fResults) { delete fResults; fResults = 0; }
97 if (fRatios) { delete fRatios; fRatios = 0; }
98 if (fOthers) { delete fOthers; fOthers = 0; }
99 if (fTriggers) { delete fTriggers; fTriggers = 0; }
100 fRangeParam = 0;
101 }
102
2f92ff0e 103 //==================================================================
104 /**
105 * @{
106 * @name Set parameters
107 */
108 /**
109 * Show other (UA5, CMS, ...) data
110 *
111 * @param x Whether to show or not
112 */
b2e7f2d6 113 void SetShowOthers(Bool_t x) { fShowOthers = x; }
2f92ff0e 114 //__________________________________________________________________
115 /**
116 * Show ALICE published data
117 *
118 * @param x Wheter to show or not
119 */
b2e7f2d6 120 void SetShowAlice(Bool_t x) { fShowAlice = x; }
2f92ff0e 121 //__________________________________________________________________
122 /**
123 * Whether to show ratios or not. If there's nothing to compare to,
124 * the ratio panel will be implicitly disabled
125 *
126 * @param x Whether to show or not
127 */
b2e7f2d6 128 void SetShowRatios(Bool_t x) { fShowRatios = x; }
2f92ff0e 129 //__________________________________________________________________
130 /**
131 *
132 * Whether to show the left/right asymmetry
133 *
134 * @param x To show or not
135 */
b2e7f2d6 136 void SetShowLeftRight(Bool_t x) { fShowLeftRight = x; }
2f92ff0e 137 //__________________________________________________________________
138 /**
139 * Set the rebinning factor
140 *
141 * @param x Rebinning factor (must be a divisor in the number of bins)
142 */
b2e7f2d6 143 void SetRebin(UShort_t x) { fRebin = x; }
2f92ff0e 144 //__________________________________________________________________
145 /**
146 * Wheter to cut away the edges
147 *
148 * @param x Whether or not to cut away edges
149 */
b2e7f2d6 150 void SetCutEdges(Bool_t x) { fCutEdges = x; }
2f92ff0e 151 //__________________________________________________________________
152 /**
153 * Set the title of the plot
154 *
155 * @param x Title
156 */
b2e7f2d6 157 void SetTitle(TString x) { fTitle = x; }
2f92ff0e 158 /* @} */
159 //==================================================================
160 /**
161 * @{
162 * @name Override settings from input
163 */
164 /**
165 * Override setting from file
166 *
167 * @param sNN Center of mass energy per nucleon pair (GeV)
168 */
169 void SetSNN(UShort_t sNN)
170 {
cdb9e20f 171 fSNNString = new TNamed("sNN", Form("%04dGeV", sNN));
2f92ff0e 172 fSNNString->SetUniqueID(sNN);
173 }
174 //__________________________________________________________________
175 /**
176 * Set the collision system
177 * - 1: pp
178 * - 2: PbPb
179 *
180 * @param sys collision system
181 */
182 void SetSys(UShort_t sys)
183 {
fe52e455 184 fSysString = new TNamed("sys", (sys == 1 ? "pp" :
2f92ff0e 185 sys == 2 ? "PbPb" : "unknown"));
fe52e455 186 fSysString->SetUniqueID(sys);
2f92ff0e 187 }
188 //__________________________________________________________________
189 /**
190 * Set the vertex range in centimeters
191 *
192 * @param vzMin Min @f$ v_z@f$
193 * @param vzMax Max @f$ v_z@f$
194 */
195 void SetVertexRange(Double_t vzMin, Double_t vzMax)
196 {
197 fVtxAxis = new TAxis(10, vzMin, vzMax);
198 fVtxAxis->SetName("vtxAxis");
199 fVtxAxis->SetTitle(Form("v_{z}#in[%+5.1f,%+5.1f]cm", vzMin, vzMax));
200 }
b2e7f2d6 201 //__________________________________________________________________
2f92ff0e 202 void SetTrigger(UShort_t trig)
203 {
204 fTrigString = new TNamed("trigString", (trig & 0x1 ? "INEL" :
205 trig & 0x2 ? "INEL>0" :
206 trig & 0x4 ? "NSD" :
207 "unknown"));
208 fTrigString->SetUniqueID(trig);
209 }
210
211
212 //==================================================================
213 /**
214 * @{
215 * @name Main steering functions
216 */
217 /**
218 * Run the code to produce the final result.
219 *
220 * @param filename File containing the data
221 */
e308a636 222 void Run(const char* filename="forward_dndeta.root")
b2e7f2d6 223 {
e308a636 224 Double_t max = 0, rmax=0, amax=0;
b2e7f2d6 225
e308a636 226 gStyle->SetPalette(1);
e1f47419 227
e308a636 228 // --- Open input file -------------------------------------------
229 TFile* file = TFile::Open(filename, "READ");
230 if (!file) {
231 Error("Open", "Cannot open %s", filename);
232 return;
233 }
234 // --- Get forward list ------------------------------------------
235 TList* forward = static_cast<TList*>(file->Get("ForwardResults"));
236 if (!forward) {
237 Error("Open", "Couldn't find list ForwardResults");
238 return;
239 }
240 // --- Get information on the run --------------------------------
241 FetchInformation(forward);
242 // --- Set the macro pathand load other data script --------------
243 gROOT->SetMacroPath(Form("%s:$(ALICE_ROOT)/PWG2/FORWARD/analysis2",
244 gROOT->GetMacroPath()));
245 gROOT->LoadMacro("OtherData.C");
246
247 // --- Get the central results -----------------------------------
248 TList* clusters = static_cast<TList*>(file->Get("CentralResults"));
249 if (!clusters) Warning("Open", "Couldn't find list CentralResults");
b2e7f2d6 250
e308a636 251 // --- Make our containtes ---------------------------------------
252 fResults = new THStack("results", "Results");
253 fRatios = new THStack("ratios", "Ratios");
254 fLeftRight = new THStack("asymmetry", "Left-right asymmetry");
255 fOthers = new TMultiGraph();
b2e7f2d6 256
e308a636 257 // --- Loop over input data --------------------------------------
258 FetchResults(forward, "Forward", max, rmax, amax);
259 FetchResults(clusters, "Central", max, rmax, amax);
b2e7f2d6 260
e308a636 261 // --- Get trigger information -----------------------------------
262 TList* sums = static_cast<TList*>(file->Get("ForwardSums"));
263 if (sums) {
264 TList* all = static_cast<TList*>(sums->FindObject("all"));
265 if (all) {
266 fTriggers = FetchResult(all, "triggers");
267 if (!fTriggers) all->ls();
268 }
269 else {
270 Warning("Run", "List all not found in ForwardSums");
271 sums->ls();
272 }
273 }
274 else {
275 Warning("Run", "No ForwardSums directory found in %s", file->GetName());
276 file->ls();
277 }
278
279 // --- Check our stacks ------------------------------------------
280 if (!fResults->GetHists() ||
281 fResults->GetHists()->GetEntries() <= 0) {
282 Error("Run", "No histograms in result stack!");
283 return;
284 }
285 if (!fOthers->GetListOfGraphs() ||
286 fOthers->GetListOfGraphs()->GetEntries() <= 0) {
287 Warning("Run", "No other data found - disabling that");
288 fShowOthers = false;
289 }
290 if (!fRatios->GetHists() ||
291 fRatios->GetHists()->GetEntries() <= 0) {
292 Warning("Run", "No ratio data found - disabling that");
293 // fRatios->ls();
294 fShowRatios = false;
295 }
296 if (!fLeftRight->GetHists() ||
297 fLeftRight->GetHists()->GetEntries() <= 0) {
298 Warning("Run", "No left/right data found - disabling that");
299 // fLeftRight->ls();
300 fShowLeftRight = false;
301 }
302
303 // --- Close the input file --------------------------------------
304 file->Close();
305
306
b2e7f2d6 307
e308a636 308 // --- Plot results ----------------------------------------------
309 Plot(max, rmax, amax);
b2e7f2d6 310 }
e1f47419 311
b2e7f2d6 312 //__________________________________________________________________
2f92ff0e 313 /**
e1f47419 314 * Fetch the information on the run from the results list
2f92ff0e 315 *
e1f47419 316 * @param results Results list
2f92ff0e 317 */
e1f47419 318 void FetchInformation(const TList* results)
b2e7f2d6 319 {
2f92ff0e 320 if (!fTrigString)
0be6c8cd 321 fTrigString = static_cast<TNamed*>(results->FindObject("trigger"));
322 if (!fNormString)
323 fNormString = static_cast<TNamed*>(results->FindObject("scheme"));
2f92ff0e 324 if (!fSNNString)
325 fSNNString = static_cast<TNamed*>(results->FindObject("sNN"));
326 if (!fSysString)
327 fSysString = static_cast<TNamed*>(results->FindObject("sys"));
328 if (!fVtxAxis)
329 fVtxAxis = static_cast<TAxis*>(results->FindObject("vtxAxis"));
e308a636 330 if (!fCentAxis)
331 fCentAxis = static_cast<TAxis*>(results->FindObject("centAxis"));
c25b5e1b 332
333 TNamed* options = static_cast<TAxis*>(results->FindObject("options"));
0be6c8cd 334 if (!fTrigString) fTrigString = new TNamed("trigger", "unknown");
335 if (!fNormString) fNormString = new TNamed("scheme", "unknown");
bad9a3c1 336 if (!fSNNString) fSNNString = new TNamed("sNN", "unknown");
337 if (!fSysString) fSysString = new TNamed("sys", "unknown");
338 if (!fVtxAxis) {
339 fVtxAxis = new TAxis(1,0,0);
340 fVtxAxis->SetName("vtxAxis");
341 fVtxAxis->SetTitle("v_{z} range unspecified");
342 }
b2e7f2d6 343
0be6c8cd 344 TString centTxt("none");
e308a636 345 if (fCentAxis) {
346 Int_t nCent = fCentAxis->GetNbins();
0be6c8cd 347 centTxt = Form("%d bins", nCent);
e308a636 348 for (Int_t i = 0; i <= nCent; i++)
0be6c8cd 349 centTxt.Append(Form("%c%d", i == 0 ? ' ' : '-',
ffca499d 350 int(fCentAxis->GetXbins()->At(i))));
e308a636 351 }
e1f47419 352 Info("FetchInformation",
fe52e455 353 "Initialized for\n"
0be6c8cd 354 " Trigger: %-30s (%d)\n"
355 " sqrt(sNN): %-30s (%dGeV)\n"
356 " System: %-30s (%d)\n"
357 " Vz range: %-30s (%f,%f)\n"
358 " Normalization: %-30s (%d)\n"
c25b5e1b 359 " Centrality: %s\n"
360 " Options: %s",
fe52e455 361 fTrigString->GetTitle(), fTrigString->GetUniqueID(),
362 fSNNString->GetTitle(), fSNNString->GetUniqueID(),
363 fSysString->GetTitle(), fSysString->GetUniqueID(),
e308a636 364 fVtxAxis->GetTitle(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax(),
0be6c8cd 365 fNormString->GetTitle(), fNormString->GetUniqueID(),
c25b5e1b 366 centTxt.Data(), (options ? options->GetTitle() : "none"));
e1f47419 367 }
e308a636 368 //__________________________________________________________________
369 TMultiGraph* FetchOthers(UShort_t centLow, UShort_t centHigh)
370 {
371 TMultiGraph* thisOther = 0;
372 if (!fShowOthers && !fShowAlice) return 0;
373
374 Bool_t onlya = (fShowOthers ? false : true);
375 UShort_t sys = (fSysString ? fSysString->GetUniqueID() : 0);
376 UShort_t trg = (fTrigString ? fTrigString->GetUniqueID() : 0);
377 UShort_t snn = (fSNNString ? fSNNString->GetUniqueID() : 0);
378 Long_t ret = gROOT->ProcessLine(Form("GetData(%d,%d,%d,%d,%d,%d);",
379 sys,snn,trg,
380 centLow,centHigh,onlya));
381 if (!ret) {
5bb5d1f6 382#if 0
e308a636 383 Warning("FetchResults", "No other data found for sys=%d, sNN=%d, "
384 "trigger=%d %d%%-%d%% central %s",
385 sys, snn, trg, centLow, centHigh,
386 onlya ? " (ALICE results)" : "all");
5bb5d1f6 387#endif
e308a636 388 return 0;
389 }
390 thisOther = reinterpret_cast<TMultiGraph*>(ret);
e1f47419 391
e308a636 392 return thisOther;
393 }
e1f47419 394 //__________________________________________________________________
395 /**
e308a636 396 * Get the results from the top-level list
e1f47419 397 *
e308a636 398 * @param list List
399 * @param name name
400 * @param max On return, maximum of data
401 * @param rmax On return, maximum of ratios
402 * @param amax On return, maximum of left-right comparisons
e1f47419 403 */
e308a636 404 void FetchResults(const TList* list,
405 const char* name,
406 Double_t& max,
407 Double_t& rmax,
408 Double_t& amax)
e1f47419 409 {
e308a636 410 UShort_t n = fCentAxis ? fCentAxis->GetNbins() : 0;
411 if (n == 0) {
412 TList* all = static_cast<TList*>(list->FindObject("all"));
413 if (!all)
414 Error("FetchResults", "Couldn't find list 'all' in %s",
415 list->GetName());
416 else
5bb5d1f6 417 FetchResults(all, name, FetchOthers(0,0), -1000, 0, max, rmax, amax);
e308a636 418 return;
b2e7f2d6 419 }
e1f47419 420
e308a636 421 for (UShort_t i = 0; i < n; i++) {
5bb5d1f6 422 UShort_t centLow = fCentAxis->GetBinLowEdge(i+1);
423 UShort_t centHigh = fCentAxis->GetBinUpEdge(i+1);
e308a636 424 TString lname = Form("cent%03d_%03d", centLow, centHigh);
425 TList* thisCent = static_cast<TList*>(list->FindObject(lname));
5bb5d1f6 426 Int_t col = GetCentralityColor(i+1);
e308a636 427
428 TString centTxt = Form("%3d%%-%3d%% central", centLow, centHigh);
429 if (!thisCent)
430 Error("FetchResults", "Couldn't find list '%s' in %s",
431 lname.Data(), list->GetName());
432 else
433 FetchResults(thisCent, name, FetchOthers(centLow, centHigh),
434 col, centTxt.Data(), max, rmax, amax);
e1f47419 435 }
e308a636 436 }
437 //__________________________________________________________________
5bb5d1f6 438 Int_t GetCentralityColor(Int_t bin) const
439 {
440 UShort_t centLow = fCentAxis->GetBinLowEdge(bin);
441 UShort_t centHigh = fCentAxis->GetBinUpEdge(bin);
442 Float_t fc = (centLow+double(centHigh-centLow)/2) / 100;
443 Int_t nCol = gStyle->GetNumberOfColors();
444 Int_t icol = TMath::Min(nCol-1,int(fc * nCol + .5));
445 Int_t col = gStyle->GetColorPalette(icol);
446 //Info("GetCentralityColor","%3d: %3d-%3d -> %3d",bin,centLow,centHigh,col);
447 return col;
448 }
449 //__________________________________________________________________
e308a636 450 void SetAttributes(TH1* h, Int_t color)
451 {
452 if (!h) return;
453 if (color < 0) return;
ffca499d 454 // h->SetLineColor(color);
e308a636 455 h->SetMarkerColor(color);
ffca499d 456 // h->SetFillColor(color);
e308a636 457 }
458 //__________________________________________________________________
459 void SetAttributes(TGraph* g, Int_t color)
460 {
461 if (!g) return;
462 if (color < 0) return;
ffca499d 463 // g->SetLineColor(color);
e308a636 464 g->SetMarkerColor(color);
ffca499d 465 // g->SetFillColor(color);
b2e7f2d6 466 }
467 //__________________________________________________________________
e308a636 468 void ModifyTitle(TNamed* h, const char* centTxt)
469 {
5bb5d1f6 470 return;
471 // if (!centTxt || !h) return;
472 // h->SetTitle(Form("%s, %s", h->GetTitle(), centTxt));
e308a636 473 }
474
475 //__________________________________________________________________
476 /**
477 * Fetch results for a particular centrality bin
478 *
479 * @param list List
480 * @param name Name
ffca499d 481 * @param thisOther Other graphs
482 * @param color Color
483 * @param centTxt Centrality text
e308a636 484 * @param max On return, data maximum
485 * @param rmax On return, ratio maximum
486 * @param amax On return, left-right maximum
487 */
488 void FetchResults(const TList* list,
489 const char* name,
490 TMultiGraph* thisOther,
491 Int_t color,
492 const char* centTxt,
493 Double_t& max,
494 Double_t& rmax,
495 Double_t& amax)
b2e7f2d6 496 {
e1f47419 497 TH1* dndeta = FetchResult(list, Form("dndeta%s", name));
498 TH1* dndetaMC = FetchResult(list, Form("dndeta%sMC", name));
499 TH1* dndetaTruth = FetchResult(list, "dndetaTruth");
500 TH1* dndetaSym = 0;
501 TH1* dndetaMCSym = 0;
e308a636 502 TH1* tracks = FetchResult(list, "tracks");
ffca499d 503 if (tracks) tracks->SetTitle("ALICE Tracks");
e308a636 504 SetAttributes(dndeta, color);
5bb5d1f6 505 SetAttributes(dndetaMC, fCentAxis ? color : color+2);
e308a636 506 SetAttributes(dndetaTruth,color);
507 SetAttributes(dndetaSym, color);
5bb5d1f6 508 SetAttributes(dndetaMCSym,fCentAxis ? color : color+2);
509 SetAttributes(tracks, fCentAxis ? color : color+3);
510 if (dndetaMC && fCentAxis)
511 dndetaMC->SetMarkerStyle(dndetaMC->GetMarkerStyle()+2);
512 if (dndetaMCSym && fCentAxis)
513 dndetaMCSym->SetMarkerStyle(dndetaMCSym->GetMarkerStyle()+2);
514 if (dndetaTruth && fCentAxis)
515 dndetaTruth->SetMarkerStyle(34);
e308a636 516 ModifyTitle(dndeta, centTxt);
517 ModifyTitle(dndetaMC, centTxt);
518 ModifyTitle(dndetaTruth,centTxt);
519 ModifyTitle(dndetaSym, centTxt);
520 ModifyTitle(dndetaMCSym,centTxt);
521 ModifyTitle(tracks, centTxt);
522
e1f47419 523
e308a636 524 max = TMath::Max(max, AddHistogram(fResults, dndetaTruth, "e5 p"));
525 max = TMath::Max(max, AddHistogram(fResults, dndetaMC, dndetaMCSym));
526 max = TMath::Max(max, AddHistogram(fResults, dndeta, dndetaSym));
527 max = TMath::Max(max, AddHistogram(fResults, tracks));
5bb5d1f6 528
529 THStack* rings = static_cast<THStack*>(list->FindObject("dndetaRings"));
530 if (rings) {
531 TIter next(rings->GetHists());
532 TH1* hist = 0;
533 while ((hist = static_cast<TH1*>(next())))
534 max = TMath::Max(max, AddHistogram(fResults, hist));
535 }
e308a636 536 // Info("FetchResults", "Got %p, %p, %p from %s with name %s, max=%f",
537 // dndeta, dndetaMC, dndetaTruth, list->GetName(), name, max);
b2e7f2d6 538
e308a636 539 if (fShowLeftRight) {
540 fLeftRight->Add(Asymmetry(dndeta, amax));
541 fLeftRight->Add(Asymmetry(dndetaMC, amax));
542 fLeftRight->Add(Asymmetry(tracks, amax));
e1f47419 543 }
b2e7f2d6 544
e308a636 545 if (thisOther) {
546 TIter next(thisOther->GetListOfGraphs());
547 TGraph* g = 0;
548 while ((g = static_cast<TGraph*>(next()))) {
549 fRatios->Add(Ratio(dndeta, g, rmax));
550 fRatios->Add(Ratio(dndetaSym, g, rmax));
551 SetAttributes(g, color);
552 ModifyTitle(g, centTxt);
553 if (!fOthers->GetListOfGraphs() ||
ffca499d 554 !fOthers->GetListOfGraphs()->FindObject(g->GetName())) {
555 max = TMath::Max(max,TMath::MaxElement(g->GetN(), g->GetY()));
e308a636 556 fOthers->Add(g);
ffca499d 557 }
b2e7f2d6 558 }
e308a636 559 // fOthers->Add(thisOther);
b2e7f2d6 560 }
e308a636 561 if (tracks) {
ffca499d 562 if (!fRatios->GetHists() ||
563 !fRatios->GetHists()->FindObject(tracks->GetName()))
e308a636 564 fRatios->Add(Ratio(dndeta, tracks, rmax));
b2e7f2d6 565 }
b2e7f2d6 566
5bb5d1f6 567 if (dndetaMC) {
568 fRatios->Add(Ratio(dndeta, dndetaMC, rmax));
569 fRatios->Add(Ratio(dndetaSym, dndetaMCSym, rmax));
570 }
e308a636 571 if (dndetaTruth) {
572 fRatios->Add(Ratio(dndeta, dndetaTruth, rmax));
573 fRatios->Add(Ratio(dndetaSym, dndetaTruth, rmax));
b2e7f2d6 574 }
b2e7f2d6 575 }
576 //__________________________________________________________________
2f92ff0e 577 /**
578 * Plot the results
2f92ff0e 579 * @param max Max value
2f92ff0e 580 * @param rmax Maximum diviation from 1 of ratios
2f92ff0e 581 * @param amax Maximum diviation from 1 of asymmetries
582 */
e308a636 583 void Plot(Double_t max,
b2e7f2d6 584 Double_t rmax,
b2e7f2d6 585 Double_t amax)
586 {
587 gStyle->SetOptTitle(0);
588 gStyle->SetTitleFont(132, "xyz");
589 gStyle->SetLabelFont(132, "xyz");
590
e308a636 591 Int_t h = 800;
592 Int_t w = 800; // h / TMath::Sqrt(2);
593 Double_t y1 = 0;
594 Double_t y2 = 0;
595 Double_t y3 = 0;
596 if (!fShowRatios) w *= 1.4;
597 else y1 = 0.3;
598 if (!fShowLeftRight) w *= 1.4;
599 else {
600 Double_t y11 = y1;
601 y1 = (y11 > 0.0001 ? 0.4 : 0.2);
ffca499d 602 y2 = (y11 > 0.0001 ? 0.2 : 0.3);
e308a636 603 }
b2e7f2d6 604 TCanvas* c = new TCanvas("Results", "Results", w, h);
605 c->SetFillColor(0);
606 c->SetBorderSize(0);
607 c->SetBorderMode(0);
608
e308a636 609 PlotResults(max, y1);
b2e7f2d6 610 c->cd();
611
e308a636 612 PlotRatios(rmax, y2, y1);
b2e7f2d6 613 c->cd( );
614
e308a636 615 PlotLeftRight(amax, y3, y2);
b2e7f2d6 616 c->cd();
bad9a3c1 617
618
619 Int_t vMin = fVtxAxis->GetXmin();
620 Int_t vMax = fVtxAxis->GetXmax();
621 TString trg(fTrigString->GetTitle());
e308a636 622 Int_t nev = 0;
ffca499d 623 if (fTriggers) nev = fTriggers->GetBinContent(1);
bad9a3c1 624 trg = trg.Strip(TString::kBoth);
625 TString base(Form("dndeta_%s_%s_%s_%c%02d%c%02dcm_%09dev",
626 fSysString->GetTitle(),
627 fSNNString->GetTitle(),
628 trg.Data(),
629 vMin < 0 ? 'm' : 'p', TMath::Abs(vMin),
630 vMax < 0 ? 'm' : 'p', TMath::Abs(vMax),
631 nev));
632 c->SaveAs(Form("%s.png", base.Data()));
633 c->SaveAs(Form("%s.root", base.Data()));
634 c->SaveAs(Form("%s.C", base.Data()));
b2e7f2d6 635 }
636 //__________________________________________________________________
e308a636 637 /**
638 * Build main legend
639 *
ffca499d 640 * @param stack Stack to include
641 * @param mg (optional) Multi graph to include
642 * @param x1 Lower X coordinate in the range [0,1]
643 * @param y1 Lower Y coordinate in the range [0,1]
644 * @param x2 Upper X coordinate in the range [0,1]
645 * @param y2 Upper Y coordinate in the range [0,1]
e308a636 646 */
ffca499d 647 void BuildLegend(THStack* stack, TMultiGraph* mg,
648 Double_t x1, Double_t y1, Double_t x2, Double_t y2)
e308a636 649 {
650 TLegend* l = new TLegend(x1,y1,x2,y2);
5bb5d1f6 651 l->SetNColumns(fCentAxis ? 1 : 2);
e308a636 652 l->SetFillColor(0);
653 l->SetFillStyle(0);
654 l->SetBorderSize(0);
655 l->SetTextFont(132);
656
ffca499d 657 TIter next(stack->GetHists());
5bb5d1f6 658 TH1* hist = 0;
659 TObjArray unique;
660 unique.SetOwner();
661 while ((hist = static_cast<TH1*>(next()))) {
e308a636 662 TString n(hist->GetTitle());
663 if (n.Contains("mirrored")) continue;
5bb5d1f6 664 if (unique.FindObject(n.Data())) continue;
665 TObjString* s = new TObjString(n);
666 s->SetUniqueID(((hist->GetMarkerStyle() & 0xFFFF) << 16) |
667 ((hist->GetMarkerColor() & 0xFFFF) << 0));
668 unique.Add(s);
669 // l->AddEntry(hist, hist->GetTitle(), "pl");
e308a636 670 }
ffca499d 671 if (mg) {
672 TIter nexto(mg->GetListOfGraphs());
5bb5d1f6 673 TGraph* g = 0;
674 while ((g = static_cast<TGraph*>(nexto()))) {
675 TString n(g->GetTitle());
ffca499d 676 if (n.Contains("mirrored")) continue;
5bb5d1f6 677 if (unique.FindObject(n.Data())) continue;
678 TObjString* s = new TObjString(n);
679 s->SetUniqueID(((g->GetMarkerStyle() & 0xFFFF) << 16) |
680 ((g->GetMarkerColor() & 0xFFFF) << 0));
681 unique.Add(s);
682 // l->AddEntry(hist, hist->GetTitle(), "pl");
ffca499d 683 }
e308a636 684 }
5bb5d1f6 685 unique.ls();
686 TIter nextu(&unique);
687 TObject* s = 0;
688 Int_t i = 0;
689 while ((s = nextu())) {
690 TLegendEntry* dd = l->AddEntry(Form("data%2d", i++),
691 s->GetName(), "lp");
692 Int_t style = (s->GetUniqueID() >> 16) & 0xFFFF;
693 Int_t color = (s->GetUniqueID() >> 0) & 0xFFFF;
694 dd->SetLineColor(kBlack);
695 if (fCentAxis) dd->SetMarkerColor(kBlack);
696 else dd->SetMarkerColor(color);
697 dd->SetMarkerStyle(style);
698 }
e308a636 699 TLegendEntry* d1 = l->AddEntry("d1", "Data", "lp");
700 d1->SetLineColor(kBlack);
701 d1->SetMarkerColor(kBlack);
702 d1->SetMarkerStyle(20);
703 TLegendEntry* d2 = l->AddEntry("d2", "Mirrored data", "lp");
704 d2->SetLineColor(kBlack);
705 d2->SetMarkerColor(kBlack);
706 d2->SetMarkerStyle(24);
707
708 l->Draw();
709 }
710 //__________________________________________________________________
5bb5d1f6 711 /**
712 * Build centrality legend
713 *
714 * @param axis Stack to include
715 * @param x1 Lower X coordinate in the range [0,1]
716 * @param y1 Lower Y coordinate in the range [0,1]
717 * @param x2 Upper X coordinate in the range [0,1]
718 * @param y2 Upper Y coordinate in the range [0,1]
719 */
720 void BuildCentLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
721 {
722 if (!fCentAxis) return;
723
724 TLegend* l = new TLegend(x1,y1,x2,y2);
725 l->SetNColumns(1);
726 l->SetFillColor(0);
727 l->SetFillStyle(0);
728 l->SetBorderSize(0);
729 l->SetTextFont(132);
730
731 Int_t n = fCentAxis->GetNbins();
732 for (Int_t i = 1; i <= n; i++) {
733 Double_t low = fCentAxis->GetBinLowEdge(i);
734 Double_t upp = fCentAxis->GetBinUpEdge(i);
735 TLegendEntry* e = l->AddEntry(Form("dummy%02d", i),
736 Form("%3d%% - %3d%%",
737 int(low), int(upp)), "pl");
738 e->SetMarkerColor(GetCentralityColor(i));
739 }
740 l->Draw();
741 }
742 //__________________________________________________________________
2f92ff0e 743 /**
744 * Plot the results
745 *
2f92ff0e 746 * @param max Maximum
747 * @param yd Bottom position of pad
748 */
e308a636 749 void PlotResults(Double_t max, Double_t yd)
b2e7f2d6 750 {
751 // Make a sub-pad for the result itself
752 TPad* p1 = new TPad("p1", "p1", 0, yd, 1.0, 1.0, 0, 0, 0);
753 p1->SetTopMargin(0.05);
754 p1->SetBorderSize(0);
755 p1->SetBorderMode(0);
756 p1->SetBottomMargin(yd > 0.001 ? 0.001 : 0.1);
757 p1->SetRightMargin(0.05);
758 p1->SetGridx();
759 p1->SetTicks(1,1);
760 p1->SetNumber(1);
761 p1->Draw();
762 p1->cd();
763
e308a636 764 // Info("PlotResults", "Plotting results with max=%f", max);
765 fResults->SetMaximum(1.15*max);
766 fResults->SetMinimum(yd > 0.00001 ? -0.1 : 0);
b2e7f2d6 767
e308a636 768 FixAxis(fResults, 1/(1-yd)/1.7, "#frac{1}{N} #frac{dN_{ch}}{d#eta}");
b2e7f2d6 769
770 p1->Clear();
e308a636 771 fResults->DrawClone("nostack e1");
b2e7f2d6 772
e308a636 773 fRangeParam->fSlave1Axis = fResults->GetXaxis();
b2e7f2d6 774 fRangeParam->fSlave1Pad = p1;
775
776 // Draw other data
e308a636 777 if (fShowOthers || fShowAlice) {
b2e7f2d6 778 TGraphAsymmErrors* o = 0;
e308a636 779 TIter nextG(fOthers->GetListOfGraphs());
b2e7f2d6 780 while ((o = static_cast<TGraphAsymmErrors*>(nextG())))
781 o->DrawClone("same p");
782 }
783
784 // Make a legend in the main result pad
5bb5d1f6 785 BuildCentLegend(.12, 1-p1->GetTopMargin()-.01-.5,
786 .35, 1-p1->GetTopMargin()-.01-.1);
787 Double_t x1 = (fCentAxis ? .7 : .15);
788 Double_t x2 = (fCentAxis ? 1-p1->GetRightMargin()-.01: .90);
789 Double_t y1 = (fCentAxis ? .5: p1->GetBottomMargin()+.01);
790 Double_t y2 = (fCentAxis ? 1-p1->GetTopMargin()-.01-.15 : .35);
791
792 BuildLegend(fResults, fOthers, x1, y1, x2, y2);
b2e7f2d6 793
794 // Put a title on top
ffca499d 795 fTitle.ReplaceAll("@", " ");
b2e7f2d6 796 TLatex* tit = new TLatex(0.10, 0.95, fTitle.Data());
797 tit->SetNDC();
798 tit->SetTextFont(132);
799 tit->SetTextSize(0.05);
800 tit->Draw();
801
802 // Put a nice label in the plot
803 TString eS;
bad9a3c1 804 UShort_t snn = fSNNString->GetUniqueID();
805 const char* sys = fSysString->GetTitle();
5bb5d1f6 806 if (snn == 2750) snn = 2760;
b2e7f2d6 807 if (snn > 1000) eS = Form("%4.2fTeV", float(snn)/1000);
808 else eS = Form("%3dGeV", snn);
5bb5d1f6 809 TLatex* tt = new TLatex(.93, .93, Form("%s #sqrt{s%s}=%s, %s",
b2e7f2d6 810 sys,
5bb5d1f6 811 (fCentAxis ? "_{NN}" : ""),
b2e7f2d6 812 eS.Data(),
5bb5d1f6 813 fCentAxis ? "by centrality" :
bad9a3c1 814 fTrigString->GetTitle()));
b2e7f2d6 815 tt->SetNDC();
816 tt->SetTextFont(132);
817 tt->SetTextAlign(33);
818 tt->Draw();
819
820 // Put number of accepted events on the plot
e308a636 821 Int_t nev = 0;
ffca499d 822 if (fTriggers) nev = fTriggers->GetBinContent(1);
b2e7f2d6 823 TLatex* et = new TLatex(.93, .83, Form("%d events", nev));
824 et->SetNDC();
825 et->SetTextFont(132);
826 et->SetTextAlign(33);
827 et->Draw();
828
829 // Put number of accepted events on the plot
830 if (fVtxAxis) {
831 TLatex* vt = new TLatex(.93, .88, fVtxAxis->GetTitle());
832 vt->SetNDC();
833 vt->SetTextFont(132);
834 vt->SetTextAlign(33);
835 vt->Draw();
836 }
837 // results->Draw("nostack e1 same");
838
e308a636 839 fRangeParam->fSlave1Axis = FindXAxis(p1, fResults->GetName());
b2e7f2d6 840 fRangeParam->fSlave1Pad = p1;
841
842
843 // Mark the plot as preliminary
844 TLatex* pt = new TLatex(.12, .93, "Preliminary");
845 pt->SetNDC();
846 pt->SetTextFont(22);
847 pt->SetTextSize(0.07);
848 pt->SetTextColor(kRed+1);
849 pt->SetTextAlign(13);
850 pt->Draw();
851
852 if (!gSystem->AccessPathName("ALICE.png")) {
bad9a3c1 853 TPad* logo = new TPad("logo", "logo", .12, .65, .25, .85, 0, 0, 0);
b2e7f2d6 854 logo->SetFillStyle(0);
855 logo->Draw();
856 logo->cd();
857 TImage* i = TImage::Create();
858 i->ReadImage("ALICE.png");
859 i->Draw();
860 }
861 p1->cd();
862 }
863 //__________________________________________________________________
2f92ff0e 864 /**
865 * Plot the ratios
866 *
2f92ff0e 867 * @param max Maximum diviation from 1
868 * @param y1 Lower y coordinate of pad
869 * @param y2 Upper y coordinate of pad
870 */
e308a636 871 void PlotRatios(Double_t max, Double_t y1, Double_t y2)
b2e7f2d6 872 {
e308a636 873 if (!fShowRatios) return;
874
b2e7f2d6 875 bool isBottom = (y1 < 0.0001);
876 Double_t yd = y2 - y1;
877 // Make a sub-pad for the result itself
878 TPad* p2 = new TPad("p2", "p2", 0, y1, 1.0, y2, 0, 0, 0);
879 p2->SetTopMargin(0.001);
880 p2->SetRightMargin(0.05);
881 p2->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
882 p2->SetGridx();
883 p2->SetTicks(1,1);
884 p2->SetNumber(2);
885 p2->Draw();
886 p2->cd();
887
888 // Fix up axis
e308a636 889 FixAxis(fRatios, 1/yd/1.7, "Ratios", 7);
b2e7f2d6 890
e308a636 891 fRatios->SetMaximum(1+TMath::Max(.22,1.05*max));
892 fRatios->SetMinimum(1-TMath::Max(.32,1.05*max));
b2e7f2d6 893 p2->Clear();
e308a636 894 fRatios->DrawClone("nostack e1");
b2e7f2d6 895
896
897 // Make a legend
ffca499d 898 BuildLegend(fRatios, 0, .15,p2->GetBottomMargin()+.01,.9,
899 isBottom ? .6 : .4);
900#if 0
b2e7f2d6 901 TLegend* l2 = p2->BuildLegend(.15,p2->GetBottomMargin()+.01,.9,
902 isBottom ? .6 : .4);
903 l2->SetNColumns(2);
904 l2->SetFillColor(0);
905 l2->SetFillStyle(0);
906 l2->SetBorderSize(0);
907 l2->SetTextFont(132);
ffca499d 908#endif
b2e7f2d6 909 // Make a nice band from 0.9 to 1.1
910 TGraphErrors* band = new TGraphErrors(2);
e1f47419 911 band->SetPoint(0, fResults->GetXaxis()->GetXmin(), 1);
912 band->SetPoint(1, fResults->GetXaxis()->GetXmax(), 1);
b2e7f2d6 913 band->SetPointError(0, 0, .1);
914 band->SetPointError(1, 0, .1);
915 band->SetFillColor(kYellow+2);
916 band->SetFillStyle(3002);
917 band->SetLineStyle(2);
918 band->SetLineWidth(1);
919 band->Draw("3 same");
920 band->DrawClone("X L same");
921
922 // Replot the ratios on top
e308a636 923 fRatios->DrawClone("nostack e1 same");
b2e7f2d6 924
925 if (isBottom) {
e308a636 926 fRangeParam->fMasterAxis = FindXAxis(p2, fRatios->GetName());
b2e7f2d6 927 p2->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)",
928 fRangeParam));
929 }
930 else {
e308a636 931 fRangeParam->fSlave2Axis = FindXAxis(p2, fRatios->GetName());
b2e7f2d6 932 fRangeParam->fSlave2Pad = p2;
933 }
934 }
935 //__________________________________________________________________
2f92ff0e 936 /**
937 * Plot the asymmetries
938 *
2f92ff0e 939 * @param max Maximum diviation from 1
940 * @param y1 Lower y coordinate of pad
941 * @param y2 Upper y coordinate of pad
942 */
e308a636 943 void PlotLeftRight(Double_t max, Double_t y1, Double_t y2)
b2e7f2d6 944 {
e308a636 945 if (!fShowLeftRight) return;
946
b2e7f2d6 947 bool isBottom = (y1 < 0.0001);
948 Double_t yd = y2 - y1;
949 // Make a sub-pad for the result itself
950 TPad* p3 = new TPad("p3", "p3", 0, y1, 1.0, y2, 0, 0, 0);
951 p3->SetTopMargin(0.001);
952 p3->SetRightMargin(0.05);
953 p3->SetBottomMargin(isBottom ? 1/yd * 0.07 : 0.0001);
954 p3->SetGridx();
955 p3->SetTicks(1,1);
956 p3->SetNumber(2);
957 p3->Draw();
958 p3->cd();
959
b2e7f2d6 960 // Fix up axis
e308a636 961 FixAxis(fLeftRight, 1/yd/1.7, "Right/Left", 4);
b2e7f2d6 962
e308a636 963 fLeftRight->SetMaximum(1+TMath::Max(.12,1.05*max));
964 fLeftRight->SetMinimum(1-TMath::Max(.15,1.05*max));
b2e7f2d6 965 p3->Clear();
e308a636 966 fLeftRight->DrawClone("nostack e1");
b2e7f2d6 967
968
969 // Make a legend
5bb5d1f6 970 Double_t xx1 = (fCentAxis ? .7 : .15);
971 Double_t xx2 = (fCentAxis ? 1-p3->GetRightMargin()-.01 : .90);
972 Double_t yy1 = p3->GetBottomMargin()+.01;
973 Double_t yy2 = (fCentAxis ? 1-p3->GetTopMargin()-.01-.15 : .5);
974 BuildLegend(fLeftRight, 0, xx1, yy1, xx2, yy2);
975 // TLegend* l2 = p3->BuildLegend(.15,p3->GetBottomMargin()+.01,.9,.5);
976 // l2->SetNColumns(2);
977 // l2->SetFillColor(0);
978 // l2->SetFillStyle(0);
979 // l2->SetBorderSize(0);
980 // l2->SetTextFont(132);
ffca499d 981
b2e7f2d6 982 // Make a nice band from 0.9 to 1.1
983 TGraphErrors* band = new TGraphErrors(2);
e1f47419 984 band->SetPoint(0, fResults->GetXaxis()->GetXmin(), 1);
985 band->SetPoint(1, fResults->GetXaxis()->GetXmax(), 1);
b2e7f2d6 986 band->SetPointError(0, 0, .05);
987 band->SetPointError(1, 0, .05);
988 band->SetFillColor(kYellow+2);
989 band->SetFillStyle(3002);
990 band->SetLineStyle(2);
991 band->SetLineWidth(1);
992 band->Draw("3 same");
993 band->DrawClone("X L same");
994
e308a636 995 fLeftRight->DrawClone("nostack e1 same");
b2e7f2d6 996 if (isBottom) {
e308a636 997 fRangeParam->fMasterAxis = FindXAxis(p3, fLeftRight->GetName());
b2e7f2d6 998 p3->AddExec("range", Form("RangeExec((dNdetaDrawer::RangeParam*)%p)",
999 fRangeParam));
1000 }
1001 else {
e308a636 1002 fRangeParam->fSlave2Axis = FindXAxis(p3, fLeftRight->GetName());
b2e7f2d6 1003 fRangeParam->fSlave2Pad = p3;
1004 }
1005 }
2f92ff0e 1006 /** @} */
1007 //==================================================================
1008 /**
1009 * @{
1010 * @name Data utility functions
1011 */
1012 /**
1013 * Get a result from the passed list
1014 *
1015 * @param list List to search
1016 * @param name Object name to search for
1017 *
1018 * @return
1019 */
e1f47419 1020 TH1* FetchResult(const TList* list, const char* name) const
2f92ff0e 1021 {
1022 if (!list) return 0;
1023
e308a636 1024 TH1* ret = static_cast<TH1*>(list->FindObject(name));
5bb5d1f6 1025#if 0
e1f47419 1026 if (!ret) {
1027 // all->ls();
1028 Warning("GetResult", "Histogram %s not found", name);
2f92ff0e 1029 }
5bb5d1f6 1030#endif
b2e7f2d6 1031
e1f47419 1032 return ret;
2f92ff0e 1033 }
b2e7f2d6 1034 //__________________________________________________________________
2f92ff0e 1035 /**
1036 * Add a histogram to the stack after possibly rebinning it
1037 *
1038 * @param stack Stack to add to
1039 * @param hist histogram
1040 * @param option Draw options
1041 *
1042 * @return Maximum of histogram
1043 */
e308a636 1044 Double_t AddHistogram(THStack* stack, TH1* hist, Option_t* option="") const
b2e7f2d6 1045 {
1046 // Check if we have input
1047 if (!hist) return 0;
1048
1049 // Rebin if needed
1050 Rebin(hist);
1051
1052 stack->Add(hist, option);
1053 return hist->GetMaximum();
1054 }
1055 //__________________________________________________________________
2f92ff0e 1056 /**
1057 * Add a histogram to the stack after possibly rebinning it
1058 *
1059 * @param stack Stack to add to
1060 * @param hist histogram
1061 * @param option Draw options
1062 * @param sym On return, the data symmetriced (added to stack)
1063 *
1064 * @return Maximum of histogram
1065 */
e308a636 1066 Double_t AddHistogram(THStack* stack, TH1* hist, TH1*& sym,
1067 Option_t* option="") const
b2e7f2d6 1068 {
1069 // Check if we have input
1070 if (!hist) return 0;
1071
1072 // Rebin if needed
1073 Rebin(hist);
1074 stack->Add(hist, option);
1075
1076 // Now symmetrice the histogram
1077 sym = Symmetrice(hist);
1078 stack->Add(sym, option);
1079
1080 return hist->GetMaximum();
1081 }
1082
1083 //__________________________________________________________________
1084 /**
1085 * Rebin a histogram
1086 *
1087 * @param h Histogram to rebin
b2e7f2d6 1088 *
1089 * @return
1090 */
1091 virtual void Rebin(TH1* h) const
1092 {
1093 if (fRebin <= 1) return;
1094
1095 Int_t nBins = h->GetNbinsX();
1096 if(nBins % fRebin != 0) {
1097 Warning("Rebin", "Rebin factor %d is not a devisor of current number "
1098 "of bins %d in the histogram %s", fRebin, nBins, h->GetName());
1099 return;
1100 }
1101
1102 // Make a copy
1103 TH1* tmp = static_cast<TH1*>(h->Clone("tmp"));
1104 tmp->Rebin(fRebin);
1105 tmp->SetDirectory(0);
e28f5fc5 1106 tmp->Reset();
b2e7f2d6 1107 // The new number of bins
1108 Int_t nBinsNew = nBins / fRebin;
1109 for(Int_t i = 1;i<= nBinsNew; i++) {
1110 Double_t content = 0;
1111 Double_t sumw = 0;
1112 Double_t wsum = 0;
1113 Int_t nbins = 0;
1114 for(Int_t j = 1; j<=fRebin;j++) {
1115 Int_t bin = (i-1)*fRebin + j;
1116 Double_t c = h->GetBinContent(bin);
1117
1118 if (c <= 0) continue;
1119
1120 if (fCutEdges) {
1121 if (h->GetBinContent(bin+1)<=0 ||
1122 h->GetBinContent(bin-1)) {
1123 Warning("Rebin", "removing bin %d=%f of %s (%d=%f,%d=%f)",
1124 bin, c, h->GetName(),
1125 bin+1, h->GetBinContent(bin+1),
1126 bin-1, h->GetBinContent(bin-1));
1127 continue;
1128 }
1129 }
1130 Double_t e = h->GetBinError(bin);
1131 Double_t w = 1 / (e*e); // 1/c/c
1132 content += c;
1133 sumw += w;
1134 wsum += w * c;
1135 nbins++;
1136 }
1137
e28f5fc5 1138 if(content > 0 && nbins > 1 ) {
b2e7f2d6 1139 tmp->SetBinContent(i, wsum / sumw);
1140 tmp->SetBinError(i,1./TMath::Sqrt(sumw));
1141 }
1142 }
1143
1144 // Finally, rebin the histogram, and set new content
1145 h->Rebin(fRebin);
1146 h->Reset();
1147 for(Int_t i = 1; i<= nBinsNew; i++) {
1148 h->SetBinContent(i,tmp->GetBinContent(i));
1149 h->SetBinError(i, tmp->GetBinError(i));
1150 }
1151
1152 delete tmp;
1153 }
1154 //__________________________________________________________________
1155 /**
1156 * Make an extension of @a h to make it symmetric about 0
1157 *
1158 * @param h Histogram to symmertrice
1159 *
1160 * @return Symmetric extension of @a h
1161 */
1162 TH1* Symmetrice(const TH1* h) const
1163 {
1164 Int_t nBins = h->GetNbinsX();
1165 TH1* s = static_cast<TH1*>(h->Clone(Form("%s_mirror", h->GetName())));
1166 s->SetTitle(Form("%s (mirrored)", h->GetTitle()));
1167 s->Reset();
1168 s->SetBins(nBins, -h->GetXaxis()->GetXmax(), -h->GetXaxis()->GetXmin());
1169 s->SetMarkerColor(h->GetMarkerColor());
1170 s->SetMarkerSize(h->GetMarkerSize());
1171 s->SetMarkerStyle(h->GetMarkerStyle()+4);
1172 s->SetFillColor(h->GetFillColor());
1173 s->SetFillStyle(h->GetFillStyle());
1174 s->SetDirectory(0);
1175
1176 // Find the first and last bin with data
1177 Int_t first = nBins+1;
1178 Int_t last = 0;
1179 for (Int_t i = 1; i <= nBins; i++) {
1180 if (h->GetBinContent(i) <= 0) continue;
1181 first = TMath::Min(first, i);
1182 last = TMath::Max(last, i);
1183 }
1184
1185 Double_t xfirst = h->GetBinCenter(first-1);
1186 Int_t f1 = h->GetXaxis()->FindBin(-xfirst);
1187 Int_t l2 = s->GetXaxis()->FindBin(xfirst);
1188 for (Int_t i = f1, j=l2; i <= last; i++,j--) {
1189 s->SetBinContent(j, h->GetBinContent(i));
1190 s->SetBinError(j, h->GetBinError(i));
1191 }
1192 // Fill in overlap bin
1193 s->SetBinContent(l2+1, h->GetBinContent(first));
1194 s->SetBinError(l2+1, h->GetBinError(first));
1195 return s;
1196 }
1197 //__________________________________________________________________
2f92ff0e 1198 /**
1199 * Calculate the left-right asymmetry of input histogram
1200 *
1201 * @param h Input histogram
1202 * @param max On return, the maximum distance from 1 of the histogram
1203 *
1204 * @return Asymmetry
1205 */
1206 TH1* Asymmetry(TH1* h, Double_t& max)
1207 {
1208 if (!h) return 0;
1209
1210 TH1* ret = static_cast<TH1*>(h->Clone(Form("%s_leftright", h->GetName())));
1211 // Int_t oBins = h->GetNbinsX();
1212 // Double_t high = h->GetXaxis()->GetXmax();
1213 // Double_t low = h->GetXaxis()->GetXmin();
1214 // Double_t dBin = (high - low) / oBins;
1215 // Int_t tBins = Int_t(2*high/dBin+.5);
1216 // ret->SetBins(tBins, -high, high);
e308a636 1217 ret->SetDirectory(0);
2f92ff0e 1218 ret->Reset();
1219 ret->SetTitle(Form("%s (+/-)", h->GetTitle()));
1220 ret->SetYTitle("Right/Left");
1221 Int_t nBins = h->GetNbinsX();
1222 for (Int_t i = 1; i <= nBins; i++) {
1223 Double_t x = h->GetBinCenter(i);
1224 if (x > 0) break;
1225
1226 Double_t c1 = h->GetBinContent(i);
1227 Double_t e1 = h->GetBinError(i);
1228 if (c1 <= 0) continue;
1229
1230 Int_t j = h->FindBin(-x);
1231 if (j <= 0 || j > nBins) continue;
1232
1233 Double_t c2 = h->GetBinContent(j);
1234 Double_t e2 = h->GetBinError(j);
1235
1236 Double_t c12 = c1*c1;
1237 Double_t e = TMath::Sqrt((e2*e2*c1*c1+e1*e1*c2*c2)/(c12*c12));
1238
1239 Int_t k = ret->FindBin(x);
1240 ret->SetBinContent(k, c2/c1);
1241 ret->SetBinError(k, e);
1242 }
1243 max = TMath::Max(max, RatioMax(ret));
1244
1245 return ret;
1246 }
1247 //__________________________________________________________________
1248 /**
1249 * Transform a graph into a histogram
1250 *
1251 * @param g
1252 *
1253 * @return
1254 */
1255 TH1* Graph2Hist(const TGraphAsymmErrors* g) const
1256 {
1257 Int_t nBins = g->GetN();
1258 TArrayF bins(nBins+1);
1259 Double_t dx = 0;
1260 for (Int_t i = 0; i < nBins; i++) {
1261 Double_t x = g->GetX()[i];
1262 Double_t exl = g->GetEXlow()[i];
1263 Double_t exh = g->GetEXhigh()[i];
1264 bins.fArray[i] = x-exl;
1265 bins.fArray[i+1] = x+exh;
1266 Double_t dxi = exh+exl;
1267 if (i == 0) dx = dxi;
1268 else if (dxi != dx) dx = 0;
1269 }
1270 TString name(g->GetName());
1271 TString title(g->GetTitle());
1272 TH1D* h = 0;
1273 if (dx != 0) {
1274 h = new TH1D(name.Data(), title.Data(), nBins, bins[0], bins[nBins]);
1275 }
1276 else {
1277 h = new TH1D(name.Data(), title.Data(), nBins, bins.fArray);
1278 }
1279 h->SetMarkerStyle(g->GetMarkerStyle());
1280 h->SetMarkerColor(g->GetMarkerColor());
1281 h->SetMarkerSize(g->GetMarkerSize());
1282
1283 return h;
1284 }
1285 /* @} */
1286 //==================================================================
1287 /**
1288 * @{
1289 * @name Ratio utility functions
1290 */
1291 /**
1292 * Get the maximum diviation from 1 in the passed ratio
1293 *
1294 * @param h Ratio histogram
1295 *
1296 * @return Max diviation from 1
1297 */
b2e7f2d6 1298 Double_t RatioMax(TH1* h) const
1299 {
1300 Int_t nBins = h->GetNbinsX();
1301 Double_t ret = 0;
1302 for (Int_t i = 1; i <= nBins; i++) {
1303 Double_t c = h->GetBinContent(i);
1304 if (c == 0) continue;
1305 Double_t e = h->GetBinError(i);
1306 Double_t d = TMath::Abs(1-c-e);
1307 ret = TMath::Max(d, ret);
1308 }
1309 return ret;
1310 }
1311 //__________________________________________________________________
e1f47419 1312 /**
1313 * Make the ratio of h1 to h2
1314 *
ffca499d 1315 * @param o1 First object (numerator)
1316 * @param o2 Second object (denominator)
1317 * @param max Maximum diviation from 1
e1f47419 1318 *
ffca499d 1319 * @return o1 / o2
e1f47419 1320 */
1321 TH1* Ratio(const TObject* o1, const TObject* o2, Double_t& max) const
1322 {
b30dee70 1323 if (!o1 || !o2) return 0;
1324
5bb5d1f6 1325 TH1* r = 0;
1326 const TAttMarker* m1 = 0;
1327 const TAttMarker* m2 = 0;
e1f47419 1328 const TH1* h1 = dynamic_cast<const TH1*>(o1);
1329 if (h1) {
5bb5d1f6 1330 m1 = h1;
e1f47419 1331 const TH1* h2 = dynamic_cast<const TH1*>(o2);
ffca499d 1332 if (h2) {
5bb5d1f6 1333 m2 = h2;
1334 r = RatioHH(h1,h2);
ffca499d 1335 }
1336 else {
1337 const TGraph* g2 = dynamic_cast<const TGraph*>(o2);
1338 if (g2) {
5bb5d1f6 1339 m2 = g2;
1340 r = RatioHG(h1,g2);
ffca499d 1341 }
1342 }
e1f47419 1343 }
ffca499d 1344 else {
1345 const TGraphAsymmErrors* g1 = dynamic_cast<const TGraphAsymmErrors*>(o1);
1346 if (g1) {
5bb5d1f6 1347 m1 = g1;
ffca499d 1348 const TGraphAsymmErrors* g2 =
1349 dynamic_cast<const TGraphAsymmErrors*>(o2);
1350 if (g2) {
5bb5d1f6 1351 m2 = g2;
1352 r = RatioGG(g1, g2);
ffca499d 1353 }
1354 }
e1f47419 1355 }
ffca499d 1356 if (!r) {
1357 Warning("Ratio", "Don't know how to divide a %s (%s) with a %s (%s)",
1358 o1->ClassName(), o1->GetName(), o2->ClassName(), o2->GetName());
1359 return 0;
1360 }
1361 // Check that the histogram isn't empty
1362 if (r->GetEntries() <= 0) {
1363 delete r;
1364 r = 0;
1365 }
5bb5d1f6 1366 if (r) {
1367 r->SetMarkerStyle(m1->GetMarkerStyle());
1368 r->SetMarkerColor(m2->GetMarkerColor());
1369 r->SetMarkerSize(0.9*m1->GetMarkerSize());
1370 r->SetName(Form("%s_over_%s", o1->GetName(), o2->GetName()));
1371 r->SetTitle(Form("%s / %s", o1->GetTitle(), o2->GetTitle()));
1372 r->SetDirectory(0);
1373 max = TMath::Max(RatioMax(r), max);
1374 }
1375
ffca499d 1376 return r;
e1f47419 1377 }
1378 //__________________________________________________________________
b2e7f2d6 1379 /**
1380 * Compute the ratio of @a h to @a g. @a g is evaluated at the bin
1381 * centers of @a h
1382 *
1383 * @param h Numerator
1384 * @param g Divisor
1385 *
1386 * @return h/g
1387 */
5bb5d1f6 1388 TH1* RatioHG(const TH1* h, const TGraph* g) const
b2e7f2d6 1389 {
1390 if (!h || !g) return 0;
1391
1392 TH1* ret = static_cast<TH1*>(h->Clone("tmp"));
b2e7f2d6 1393 ret->Reset();
b2e7f2d6 1394 Double_t xlow = g->GetX()[0];
1395 Double_t xhigh = g->GetX()[g->GetN()-1];
1396 if (xlow > xhigh) { Double_t t = xhigh; xhigh = xlow; xlow = t; }
1397
1398 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
1399 Double_t c = h->GetBinContent(i);
1400 if (c <= 0) continue;
1401
1402 Double_t x = h->GetBinCenter(i);
1403 if (x < xlow || x > xhigh) continue;
1404
1405 Double_t f = g->Eval(x);
1406 if (f <= 0) continue;
1407
1408 ret->SetBinContent(i, c / f);
1409 ret->SetBinError(i, h->GetBinError(i) / f);
1410 }
b2e7f2d6 1411 return ret;
1412 }
1413 //__________________________________________________________________
1414 /**
1415 * Make the ratio of h1 to h2
1416 *
1417 * @param h1 First histogram (numerator)
1418 * @param h2 Second histogram (denominator)
1419 *
1420 * @return h1 / h2
1421 */
5bb5d1f6 1422 TH1* RatioHH(const TH1* h1, const TH1* h2) const
b2e7f2d6 1423 {
1424 if (!h1 || !h2) return 0;
5bb5d1f6 1425 TH1* t1 = static_cast<TH1*>(h1->Clone("tmp"));
b2e7f2d6 1426 t1->Divide(h2);
b2e7f2d6 1427 return t1;
1428 }
1429 //__________________________________________________________________
1430 /**
1431 * Calculate the ratio of two graphs - g1 / g2
1432 *
1433 * @param g1 Numerator
1434 * @param g2 Denominator
1435 *
1436 * @return g1 / g2 in a histogram
1437 */
ffca499d 1438 TH1* RatioGG(const TGraphAsymmErrors* g1,
5bb5d1f6 1439 const TGraphAsymmErrors* g2) const
b2e7f2d6 1440 {
1441 Int_t nBins = g1->GetN();
1442 TArrayF bins(nBins+1);
1443 Double_t dx = 0;
1444 for (Int_t i = 0; i < nBins; i++) {
1445 Double_t x = g1->GetX()[i];
1446 Double_t exl = g1->GetEXlow()[i];
1447 Double_t exh = g1->GetEXhigh()[i];
1448 bins.fArray[i] = x-exl;
1449 bins.fArray[i+1] = x+exh;
1450 Double_t dxi = exh+exl;
1451 if (i == 0) dx = dxi;
1452 else if (dxi != dx) dx = 0;
1453 }
b2e7f2d6 1454 TH1* h = 0;
1455 if (dx != 0) {
5bb5d1f6 1456 h = new TH1F("tmp", "tmp", nBins, bins[0], bins[nBins]);
b2e7f2d6 1457 }
1458 else {
5bb5d1f6 1459 h = new TH1F("tmp", "tmp", nBins, bins.fArray);
b2e7f2d6 1460 }
b2e7f2d6 1461
1462 Double_t low = g2->GetX()[0];
1463 Double_t high = g2->GetX()[g2->GetN()-1];
1464 if (low > high) { Double_t t = low; low = high; high = t; }
1465 for (Int_t i = 0; i < nBins; i++) {
1466 Double_t x = g1->GetX()[i];
1467 if (x < low-dx || x > high+dx) continue;
1468 Double_t c1 = g1->GetY()[i];
1469 Double_t e1 = g1->GetErrorY(i);
1470 Double_t c2 = g2->Eval(x);
1471
1472 h->SetBinContent(i+1, c1 / c2);
1473 h->SetBinError(i+1, e1 / c2);
1474 }
b2e7f2d6 1475 return h;
2f92ff0e 1476 }
1477 /* @} */
1478 //==================================================================
1479 /**
1480 * @{
1481 * @name Graphics utility functions
1482 */
1483 /**
1484 * Find an X axis in a pad
1485 *
1486 * @param p Pad
1487 * @param name Histogram to find axis for
1488 *
1489 * @return Found axis or null
1490 */
1491 TAxis* FindXAxis(TVirtualPad* p, const char* name)
b2e7f2d6 1492 {
2f92ff0e 1493 TObject* o = p->GetListOfPrimitives()->FindObject(name);
1494 if (!o) {
1495 Warning("FindXAxis", "%s not found in pad", name);
1496 return 0;
b2e7f2d6 1497 }
2f92ff0e 1498 THStack* stack = dynamic_cast<THStack*>(o);
1499 if (!stack) {
1500 Warning("FindXAxis", "%s is not a THStack", name);
1501 return 0;
b2e7f2d6 1502 }
2f92ff0e 1503 if (!stack->GetHistogram()) {
1504 Warning("FindXAxis", "%s has no histogram", name);
1505 return 0;
b2e7f2d6 1506 }
2f92ff0e 1507 TAxis* ret = stack->GetHistogram()->GetXaxis();
1508 return ret;
b2e7f2d6 1509 }
2f92ff0e 1510
b2e7f2d6 1511 //__________________________________________________________________
2f92ff0e 1512 /**
1513 * Fix the apperance of the axis in a stack
1514 *
1515 * @param stack stack of histogram
1516 * @param s Scaling factor
1517 * @param ytitle Y axis title
1518 * @param force Whether to draw the stack first or not
1519 * @param ynDiv Divisions on Y axis
1520 */
1521 void FixAxis(THStack* stack, Double_t s, const char* ytitle,
1522 Int_t ynDiv=210, Bool_t force=true)
b2e7f2d6 1523 {
e308a636 1524 if (!stack) {
1525 Warning("FixAxis", "No stack passed for %s!", ytitle);
1526 return;
1527 }
2f92ff0e 1528 if (force) stack->Draw("nostack e1");
b2e7f2d6 1529
2f92ff0e 1530 TH1* h = stack->GetHistogram();
e308a636 1531 if (!h) {
1532 Warning("FixAxis", "Stack %s has no histogram", stack->GetName());
1533 return;
1534 }
1535
2f92ff0e 1536 h->SetXTitle("#eta");
1537 h->SetYTitle(ytitle);
1538 TAxis* xa = h->GetXaxis();
1539 TAxis* ya = h->GetYaxis();
1540 if (xa) {
1541 xa->SetTitle("#eta");
1542 // xa->SetTicks("+-");
1543 xa->SetTitleSize(s*xa->GetTitleSize());
1544 xa->SetLabelSize(s*xa->GetLabelSize());
1545 xa->SetTickLength(s*xa->GetTickLength());
e308a636 1546
1547 if (stack != fResults) {
1548 TAxis* rxa = fResults->GetXaxis();
1549 xa->Set(rxa->GetNbins(), rxa->GetXmin(), rxa->GetXmax());
1550 }
2f92ff0e 1551 }
1552 if (ya) {
1553 ya->SetTitle(ytitle);
1554 ya->SetDecimals();
1555 // ya->SetTicks("+-");
1556 ya->SetNdivisions(ynDiv);
1557 ya->SetTitleSize(s*ya->GetTitleSize());
1558 ya->SetTitleOffset(ya->GetTitleOffset()/s);
1559 ya->SetLabelSize(s*ya->GetLabelSize());
b2e7f2d6 1560 }
b2e7f2d6 1561 }
2f92ff0e 1562 /* @} */
1563
b2e7f2d6 1564
1565
1566 //__________________________________________________________________
e308a636 1567 Bool_t fShowOthers; // Show other data
1568 Bool_t fShowAlice; // Show ALICE published data
1569 Bool_t fShowRatios; // Show ratios
1570 Bool_t fShowLeftRight;// Show asymmetry
1571 UShort_t fRebin; // Rebinning factor
1572 Bool_t fCutEdges; // Whether to cut edges
1573 TString fTitle; // Title on plot
1574 TNamed* fTrigString; // Trigger string (read, or set)
0be6c8cd 1575 TNamed* fNormString; // Normalisation string (read, or set)
e308a636 1576 TNamed* fSNNString; // Energy string (read, or set)
1577 TNamed* fSysString; // Collision system string (read or set)
1578 TAxis* fVtxAxis; // Vertex cuts (read or set)
1579 TAxis* fCentAxis; // Centrality axis
1580 THStack* fResults; // Stack of results
1581 THStack* fRatios; // Stack of ratios
1582 THStack* fLeftRight; // Left-right asymmetry
1583 TMultiGraph* fOthers; // Older data
1584 TH1* fTriggers; // Number of triggers
1585 RangeParam* fRangeParam; // Parameter object for range zoom
b2e7f2d6 1586
1587};
1588
1589//=== Stuff for auto zooming =========================================
1590void UpdateRange(dNdetaDrawer::RangeParam* p)
1591{
1592 if (!p) {
1593 Warning("UpdateRange", "No parameters %p", p);
1594 return;
1595 }
1596 if (!p->fMasterAxis) {
1597 Warning("UpdateRange", "No master axis %p", p->fMasterAxis);
1598 return;
1599 }
1600 Int_t first = p->fMasterAxis->GetFirst();
1601 Int_t last = p->fMasterAxis->GetLast();
1602 Double_t x1 = p->fMasterAxis->GetBinCenter(first);
1603 Double_t x2 = p->fMasterAxis->GetBinCenter(last);
b2e7f2d6 1604
1605 if (p->fSlave1Axis) {
1606 Int_t i1 = p->fSlave1Axis->FindBin(x1);
1607 Int_t i2 = p->fSlave1Axis->FindBin(x2);
1608 p->fSlave1Axis->SetRange(i1, i2);
1609 p->fSlave1Pad->Modified();
1610 p->fSlave1Pad->Update();
1611 }
1612 if (p->fSlave2Axis) {
1613 Int_t i1 = p->fSlave2Axis->FindBin(x1);
1614 Int_t i2 = p->fSlave2Axis->FindBin(x2);
1615 p->fSlave2Axis->SetRange(i1, i2);
1616 p->fSlave2Pad->Modified();
1617 p->fSlave2Pad->Update();
1618 }
1619 TCanvas* c = gPad->GetCanvas();
1620 c->cd();
1621}
1622
1623//____________________________________________________________________
1624void RangeExec(dNdetaDrawer::RangeParam* p)
1625{
1626 // Event types:
1627 // 51: Mouse move
1628 // 53:
1629 // 1: Button down
1630 // 21: Mouse drag
1631 // 11: Mouse release
1632 // dNdetaDrawer::RangeParam* p =
1633 // reinterpret_cast<dNdetaDrawer::RangeParam*>(addr);
1634 Int_t event = gPad->GetEvent();
1635 TObject *select = gPad->GetSelected();
1636 if (event == 53) {
1637 UpdateRange(p);
1638 return;
1639 }
1640 if (event != 11 || !select || select != p->fMasterAxis) return;
1641 UpdateRange(p);
1642}
1643
1644//=== Steering function ==============================================
ffca499d 1645/**
1646 * Draw @f$ dN/d\eta@f$
1647 *
1648 * @param filename File name
1649 * @param flags Flags
1650 * @param title Title
1651 * @param rebin Rebinning factor
1652 * @param cutEdges Whether to cut edges when rebinning
1653 * @param sNN (optional) Collision energy [GeV]
1654 * @param sys (optional) Collision system (1: pp, 2: PbPb)
1655 * @param trg (optional) Trigger (1: INEL, 2: INEL>0, 4: NSD)
1656 * @param vzMin Least @f$ v_z@f$
1657 * @param vzMax Largest @f$ v_z@f$
1658 *
1659 * @ingroup pwg2_forward_dndeta
1660 */
b2e7f2d6 1661void
1662DrawdNdeta(const char* filename="forward_dndeta.root",
1663 Int_t flags=0xf,
bad9a3c1 1664 const char* title="",
b2e7f2d6 1665 UShort_t rebin=5,
fe52e455 1666 Bool_t cutEdges=false,
1667 UShort_t sNN=0,
1668 UShort_t sys=0,
ffca499d 1669 UShort_t trg=0,
fe52e455 1670 Float_t vzMin=999,
1671 Float_t vzMax=-999)
b2e7f2d6 1672{
ffca499d 1673 dNdetaDrawer* pd = new dNdetaDrawer;
1674 dNdetaDrawer& d = *pd;
b2e7f2d6 1675 d.SetRebin(rebin);
1676 d.SetCutEdges(cutEdges);
1677 d.SetTitle(title);
b2e7f2d6 1678 d.SetShowOthers(flags & 0x1);
1679 d.SetShowAlice(flags & 0x2);
1680 d.SetShowRatios(flags & 0x4);
1681 d.SetShowLeftRight(flags & 0x8);
2f92ff0e 1682 // Do the below if your input data does not contain these settings
fe52e455 1683 if (sNN > 0) d.SetSNN(sNN); // Collision energy per nucleon pair (GeV)
1684 if (sys > 0) d.SetSys(sys); // Collision system (1:pp, 2:PbPB)
1685 if (trg > 0) d.SetTrigger(trg); // Collision trigger (1:INEL, 2:INEL>0, 4:NSD)
1686 if (vzMin < 999 && vzMax > -999)
1687 d.SetVertexRange(vzMin,vzMax); // Collision vertex range (cm)
b2e7f2d6 1688 d.Run(filename);
1689}
2f92ff0e 1690//____________________________________________________________________
1691//
1692// EOF
1693//
1694