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