]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWG2/FORWARD/analysis2/AnalyseAOD.C
Added central dN/deta task based on tracks
[u/mrichter/AliRoot.git] / PWG2 / FORWARD / analysis2 / AnalyseAOD.C
CommitLineData
7c1a1f1d 1/**
2 * @file
3 *
4 * @ingroup pwg2_forward_scripts
5 */
7e4038b5 6#include <TH1D.h>
7#include <TH2D.h>
8#include <TCanvas.h>
9#include <TPad.h>
10#include <TFile.h>
11#include <TTree.h>
95985fc4 12#include <TChain.h>
7e4038b5 13#include <TError.h>
95985fc4 14#include <TSystemDirectory.h>
15#include <TROOT.h>
7e4038b5 16#include <TStyle.h>
17#include <THStack.h>
18#include <TLegend.h>
19#include <TMath.h>
20#include <TMultiGraph.h>
21#include <TGraph.h>
22#include <TGraphErrors.h>
23#include <TLatex.h>
65a1e0cd 24#include <TSystem.h>
7e4038b5 25#include "AliAODForwardMult.h"
26#include "OtherData.C"
27
28/**
29 * Draw the data stored in the AOD
30 *
31 * To use this, do
32 *
33 * @code
34 * Root> .L $ALICE_ROOT/PWG2/FORWARD/analysis2/Compile.C
270764db 35 * Root> Compile("$ALICE_ROOT/PWG2/FORWARD/analysis2/AnalyseAOD.C")
36 * Root> AnalyseAOD dr
7e4038b5 37 * Root> dr.Run("AliAODs.root",-10,10,5,AliAODForwardMult::kInel,900)
38 * @endcode
39 *
40 * The output is stored in a ROOT file
41 *
42 * See also the script Pass2.C
43 *
7c1a1f1d 44 * @ingroup pwg2_forward_scripts
7e4038b5 45 */
270764db 46struct AnalyseAOD
7e4038b5 47{
48public:
49 /** AOD tree */
50 TTree* fTree;
51 /** AOD object */
52 AliAODForwardMult* fAOD;
270764db 53 /** AOD object */
54 AliAODForwardMult* fMCAOD;
7e4038b5 55 /** Output file */
56 TFile* fOut;
57 /** Summed histogram */
58 TH2D* fSum;
270764db 59 /** Summed histogram */
60 TH2D* fMCSum;
4cbdf467 61 /** Primary information */
62 TH2D* fPrimary;
63 /** Sum primary information */
64 TH2D* fSumPrimary;
3a08cca0 65 /** Central region */
66 TH2D* fCentral;
67 /** Central region */
68 TH2D* fSumCentral;
7e4038b5 69 /** Vertex efficiency */
70 Double_t fVtxEff;
71 /** Title to put on the plot */
72 TString fTitle;
f4494b7a 73 /** Do HHD comparison */
74 Bool_t fDoHHD;
4cbdf467 75 /** Number of events with a trigger */
76 Int_t fNTriggered;
77 /** Number of events with a vertex */
78 Int_t fNWithVertex;
79 /** Number of events accepted */
80 Int_t fNAccepted;
e333578d 81 /** Number of events accepted */
82 Int_t fNAll;
1174780f 83 /** Min vertex */
84 Double_t fVtxMin;
85 /** Max vertex */
86 Double_t fVtxMax;
87
e333578d 88
7e4038b5 89 //__________________________________________________________________
90 /**
91 * Constructor
92 *
93 */
270764db 94 AnalyseAOD()
7e4038b5 95 : fTree(0),
96 fAOD(0),
270764db 97 fMCAOD(0),
7e4038b5 98 fOut(0),
99 fSum(0),
270764db 100 fMCSum(0),
4cbdf467 101 fPrimary(0),
102 fSumPrimary(0),
3a08cca0 103 fCentral(0),
104 fSumCentral(0),
7e4038b5 105 fVtxEff(0),
f4494b7a 106 fTitle(""),
107 fDoHHD(kTRUE)
7e4038b5 108 {}
109 //__________________________________________________________________
110 /**
111 * Reset internal structures
112 *
113 */
114 void Clear(Option_t* )
115 {
116 if (fTree && fTree->GetCurrentFile()) {
117 fTree->GetCurrentFile()->Close();
118 delete fTree;
119 }
120 if (fOut) {
121 fOut->Close();
122 delete fOut;
123 }
4cbdf467 124 if (fSum) delete fSum;
125 if (fMCSum) delete fMCSum;
126 if (fSumPrimary) delete fSumPrimary;
3a08cca0 127 if (fCentral) delete fCentral;
128 if (fSumCentral) delete fSumCentral;
4cbdf467 129 fTree = 0;
130 fOut = 0;
131 fSum = 0;
132 fMCSum = 0;
3a08cca0 133 fPrimary = 0;
4cbdf467 134 fSumPrimary = 0;
3a08cca0 135 fCentral = 0;
136 fSumCentral = 0;
4cbdf467 137 fVtxEff = 0;
7e4038b5 138
139 }
140 //__________________________________________________________________
141 /**
142 * Run
143 *
95985fc4 144 * @param file Input path for files with AOD trees
7e4038b5 145 * @param vzMin Minimum interaction point z coordinate
146 * @param vzMax Maximum interaction point z coordinate
147 * @param rebin How many times to re-bin the @f$ dN_{ch}/d\eta@f$
148 * @param mask Trigger mask
149 * @param energy Collision energy @f$ \sqrt{s}@f$ or @f$\sqrt{s_{NN}}@f$
150 * @param title Title to put on the plot
c389303e 151 * @param doHHD Whether to do HHD comparison
152 * @param doComp Whether to do comparisons
7e4038b5 153 *
154 * @return True on success, false otherwise
155 */
95985fc4 156 Bool_t Run(const char* file=".",
7e4038b5 157 Double_t vzMin=-10, Double_t vzMax=10, Int_t rebin=1,
158 Int_t mask=AliAODForwardMult::kInel, Int_t energy=900,
f4494b7a 159 const char* title="", Bool_t doHHD=false, Bool_t doComp=false)
7e4038b5 160 {
161 TString trgName;
162 if (mask & AliAODForwardMult::kInel) trgName.Append("inel-");
163 if (mask & AliAODForwardMult::kInelGt0) trgName.Append("inelgt0-");
164 if (mask & AliAODForwardMult::kNSD) trgName.Append("nsd-");
165 if (trgName.EndsWith("-")) trgName.Remove(trgName.Length()-1);
166 if (trgName.IsNull()) trgName = "unknown";
167 TString outName =
168 TString::Format("dndeta_%04dGeV_%c%02d-%c%02dcm_rb%02d_%s.root",
169 energy,
170 vzMin < 0 ? 'm' : 'p', Int_t(TMath::Abs(vzMin)+.5),
171 vzMax < 0 ? 'm' : 'p', Int_t(TMath::Abs(vzMax)+.5),
172 rebin, trgName.Data());
1174780f 173 fTitle = title;
174 fVtxMin = vzMin;
175 fVtxMax = vzMax;
7e4038b5 176 if (!Open(file, outName)) return kFALSE;
1174780f 177 if (!Process(mask)) return kFALSE;
f4494b7a 178 if (!Finish(rebin, mask, energy,doHHD,doComp)) return kFALSE;
7e4038b5 179
180 return kTRUE;
181 }
95985fc4 182 //__________________________________________________________________
183 /**
184 * Scan directory @a dir for AODs
185 *
186 * @param dir Directory to scan
187 * @param chain Chain to add to
188 * @param recursive Whether to scan recusively
189 */
190 void ScanDirectory(TSystemDirectory* dir, TChain* chain, bool recursive)
191 {
cc83fca2 192 // gROOT->IndentLevel();
193 // printf("Scanning %s ...\n", dir->GetName());
194 // gROOT->IncreaseDirLevel();
95985fc4 195
196 // Get list of files, and go back to old working directory
197 TString oldDir(gSystem->WorkingDirectory());
198 TList* files = dir->GetListOfFiles();
199 gSystem->ChangeDirectory(oldDir);
200
201 // Sort list of files and check if we should add it
202 files->Sort();
203 TIter next(files);
204 TSystemFile* file = 0;
205 while ((file = static_cast<TSystemFile*>(next()))) {
206 TString name(file->GetName());
207
208 // Ignore special links
209 if (name == "." || name == "..") continue;
210
211 // Check if this is a directory
212 if (file->IsDirectory()) {
213 if (recursive)
214 ScanDirectory(static_cast<TSystemDirectory*>(file),chain,recursive);
215 continue;
216 }
217
218 // If this is not a root file, ignore
219 if (!name.EndsWith(".root")) continue;
220
221 // If this file does not contain AliESDs, ignore
222 if (!name.Contains("AliAOD")) continue;
223
224 // Get the path
225 TString aod(Form("%s/%s", file->GetTitle(), name.Data()));
226
227 // Print and add
cc83fca2 228 // gROOT->IndentLevel();
229 // printf("adding %s\n", aod.Data());
95985fc4 230 chain->Add(aod);
231
232 }
cc83fca2 233 // gROOT->DecreaseDirLevel();
95985fc4 234 }
235
236 //__________________________________________________________________
237 /**
238 * Make a chain of AOD files
239 *
240 * @param aoddir Directory so search
241 * @param recursive Whether to scan recusively
242 *
243 * @return The new chain
244 */
245 TChain*
246 MakeChain(const char* aoddir, bool recursive=false)
247 {
248 // --- Our data chain ----------------------------------------------
249 TChain* chain = new TChain("aodTree");
250
251 // --- Get list of AODs --------------------------------------------
252 // Open source directory, and make sure we go back to were we were
253 TString oldDir(gSystem->WorkingDirectory());
254 TSystemDirectory d(aoddir, aoddir);
255 ScanDirectory(&d, chain, recursive);
256
257 chain->GetListOfFiles()->ls();
258 if (chain->GetListOfFiles()->GetEntries() <= 0) {
259 delete chain;
260 chain = 0;
261 }
262 return chain;
263 }
264
265 //__________________________________________________________________
266 /**
267 * Open data. Make a chain of all AOD files in the given path
268 * and below.
269 *
270 * @param path Path to search
271 * @param outname Output name
272 *
273 * @return
274 */
275 Bool_t Open(const char* path, const char* outname)
276 {
277 Clear("");
278
279 // Get the AOD tree
280 fTree = MakeChain(path, true);
281 if (!fTree) {
282 Error("Init", "Couldn't get the tree");
283 return kFALSE;
284 }
285
286 // Set the branch pointer
287 fTree->SetBranchAddress("Forward", &fAOD);
288
289 // Set the branch pointer
cc83fca2 290 if (fTree->GetBranch("ForwardMC"))
291 fTree->SetBranchAddress("ForwardMC", &fMCAOD);
95985fc4 292
293 // Set the branch pointer
cc83fca2 294 if (fTree->GetBranch("primary"))
295 fTree->SetBranchAddress("primary", &fPrimary);
3a08cca0 296
297 // Set branch pointer
298 if (fTree->GetBranch("Central"))
299 fTree->SetBranchAddress("Central", &fCentral);
95985fc4 300
301 fOut = TFile::Open(outname, "RECREATE");
302 if (!fOut) {
303 Error("Open", "Couldn't open %s", outname);
304 return kFALSE;
305 }
306 return kTRUE;
307
308 }
309
310#if 0
7e4038b5 311 //__________________________________________________________________
312 /**
313 * Open the files @a fname containg the tree with AliAODEvent objects,
314 * and also open the output file @a outname for writting.
315 *
316 * @param fname Input file name
317 * @param outname Output file name
318 *
319 * @return true on success, false otherwise
320 */
321 Bool_t Open(const char* fname, const char* outname)
322 {
323 Clear("");
324
325 TFile* file = TFile::Open(fname, "READ");
326 if (!file) {
327 Error("Open", "Cannot open file %s", fname);
328 return kFALSE;
329 }
330
331 // Get the AOD tree
332 fTree = static_cast<TTree*>(file->Get("aodTree"));
333 if (!fTree) {
334 Error("Init", "Couldn't get the tree");
335 return kFALSE;
336 }
337
338 // Set the branch pointer
339 fTree->SetBranchAddress("Forward", &fAOD);
340
270764db 341 // Set the branch pointer
95985fc4 342 if (fTree->GetBranch("ForwardMC"))
343 fTree->SetBranchAddress("ForwardMC", &fMCAOD);
270764db 344
4cbdf467 345 // Set the branch pointer
95985fc4 346 if (fTree->GetBranch("primary"))
347 fTree->SetBranchAddress("primary", &fPrimary);
4cbdf467 348
7e4038b5 349 fOut = TFile::Open(outname, "RECREATE");
350 if (!fOut) {
351 Error("Open", "Couldn't open %s", outname);
352 return kFALSE;
353 }
354 return kTRUE;
355 }
95985fc4 356#endif
357
7e4038b5 358 //__________________________________________________________________
359 /**
360 * Process the events
361 *
362 * @param vzMin Minimum interaction point z coordinate
363 * @param vzMax Maximum interaction point z coordinate
364 * @param mask Trigger mask
365 *
366 * @return true on success, false otherwise
367 */
1174780f 368 Bool_t Process(Int_t mask)
7e4038b5 369 {
4cbdf467 370 fNTriggered = 0; // # of triggered ev.
371 fNWithVertex = 0; // # of ev. w/vertex
372 fNAccepted = 0; // # of ev. used
fa4236ed 373 Int_t nAvailable = fTree->GetEntries(); // How many entries
7e4038b5 374
375 for (int i = 0; i < nAvailable; i++) {
376 fTree->GetEntry(i);
65a1e0cd 377 if (((i+1) % 100) == 0) {
378 fprintf(stdout,"Event # %9d of %9d, %9d accepted so far\r",
4cbdf467 379 i+1, nAvailable, fNAccepted);
65a1e0cd 380 fflush(stdout);
381 }
7e4038b5 382
383 // Create sum histogram on first event - to match binning to input
384 if (!fSum) {
385 fSum = static_cast<TH2D*>(fAOD->GetHistogram().Clone("d2ndetadphi"));
386 Info("Process", "Created sum histogram (%d,%f,%f)x(%d,%f,%f)",
387 fSum->GetNbinsX(),
388 fSum->GetXaxis()->GetXmin(),
389 fSum->GetXaxis()->GetXmax(),
390 fSum->GetNbinsY(),
391 fSum->GetYaxis()->GetXmin(),
392 fSum->GetYaxis()->GetXmax());
393 }
270764db 394 if (!fMCSum && fTree->GetBranch("ForwardMC")) {
395 fMCSum =
396 static_cast<TH2D*>(fMCAOD->GetHistogram().Clone("d2ndetadphiMC"));
397 Info("Process", "Created MC sum histogram (%d,%f,%f)x(%d,%f,%f)",
398 fMCSum->GetNbinsX(),
399 fMCSum->GetXaxis()->GetXmin(),
400 fMCSum->GetXaxis()->GetXmax(),
401 fMCSum->GetNbinsY(),
402 fMCSum->GetYaxis()->GetXmin(),
403 fMCSum->GetYaxis()->GetXmax());
404 }
4cbdf467 405 if (!fSumPrimary && fTree->GetBranch("primary")) {
406 fSumPrimary =
407 static_cast<TH2D*>(fPrimary->Clone("primarySum"));
408 Info("Process", "Created MC truth histogram (%d,%f,%f)x(%d,%f,%f)",
3a08cca0 409 fSumPrimary->GetNbinsX(),
410 fSumPrimary->GetXaxis()->GetXmin(),
411 fSumPrimary->GetXaxis()->GetXmax(),
412 fSumPrimary->GetNbinsY(),
413 fSumPrimary->GetYaxis()->GetXmin(),
414 fSumPrimary->GetYaxis()->GetXmax());
415 }
416 if (!fSumCentral && fTree->GetBranch("Central")) {
417 fSumCentral =
418 static_cast<TH2D*>(fCentral->Clone("centralSum"));
419 Info("Process", "Created Cental histogram (%d,%f,%f)x(%d,%f,%f)",
420 fSumCentral->GetNbinsX(),
421 fSumCentral->GetXaxis()->GetXmin(),
422 fSumCentral->GetXaxis()->GetXmax(),
423 fSumCentral->GetNbinsY(),
424 fSumCentral->GetYaxis()->GetXmin(),
425 fSumCentral->GetYaxis()->GetXmax());
4cbdf467 426 }
e333578d 427
428 // Add contribution from this event
429 if (fSumPrimary) fSumPrimary->Add(fPrimary);
430
431 fNAll++;
432
7e4038b5 433 // fAOD->Print();
434 // Other trigger/event requirements could be defined
435 if (!fAOD->IsTriggerBits(mask)) continue;
4cbdf467 436 fNTriggered++;
fa4236ed 437
438 // Check if there's a vertex
439 if (!fAOD->HasIpZ()) continue;
4cbdf467 440 fNWithVertex++;
fa4236ed 441
7e4038b5 442 // Select vertex range (in centimeters)
1174780f 443 if (!fAOD->InRange(fVtxMin, fVtxMax)) continue;
4cbdf467 444 fNAccepted++;
7e4038b5 445
446 // Add contribution from this event
447 fSum->Add(&(fAOD->GetHistogram()));
270764db 448
449 // Add contribution from this event
450 if (fMCSum) fMCSum->Add(&(fMCAOD->GetHistogram()));
4cbdf467 451
3a08cca0 452 // Add contribution from this event
453 if (fSumCentral) fSumCentral->Add(fCentral);
7e4038b5 454 }
65a1e0cd 455 printf("\n");
4cbdf467 456 fVtxEff = Double_t(fNWithVertex)/fNTriggered;
7e4038b5 457
fa4236ed 458 Info("Process", "Total of %9d events\n"
459 " %9d has a trigger\n"
460 " %9d has a vertex\n"
461 " %9d was used\n",
4cbdf467 462 nAvailable, fNTriggered, fNWithVertex, fNAccepted);
7e4038b5 463
464 return kTRUE;
465 }
466 //__________________________________________________________________
467 /**
468 * Finish the stuff and draw
469 *
470 * @param rebin How many times to rebin
471 * @param energy Collision energy
472 * @param mask Trigger mask
c389303e 473 * @param doHHD Whether to do HHD comparison
474 * @param doComp Whether to do comparisons
7e4038b5 475 *
476 * @return true on success, false otherwise
477 */
f4494b7a 478 Bool_t Finish(Int_t rebin, Int_t mask, Int_t energy,
479 Bool_t doHHD, Bool_t doComp)
7e4038b5 480 {
481 fOut->cd();
482
483 // Get acceptance normalisation from underflow bins
484 TH1D* norm = fSum->ProjectionX("norm", 0, 1, "");
485 // Project onto eta axis - _ignoring_underflow_bins_!
486 TH1D* dndeta = fSum->ProjectionX("dndeta", 1, -1, "e");
270764db 487 dndeta->SetTitle("ALICE Forward");
7e4038b5 488 // Normalize to the acceptance
489 dndeta->Divide(norm);
490 // Scale by the vertex efficiency
491 dndeta->Scale(fVtxEff, "width");
492 dndeta->SetMarkerColor(kRed+1);
493 dndeta->SetMarkerStyle(20);
494 dndeta->SetMarkerSize(1);
495 dndeta->SetFillStyle(0);
82fc512a 496 Rebin(dndeta, rebin);
270764db 497
498 TH1D* dndetaMC = 0;
499 if (fMCSum) {
500 // Get acceptance normalisation from underflow bins
501 norm = fMCSum->ProjectionX("norm", 0, 1, "");
502 // Project onto eta axis - _ignoring_underflow_bins_!
503 dndetaMC = fMCSum->ProjectionX("dndetaMC", 1, -1, "e");
504 dndetaMC->SetTitle("ALICE Forward (MC)");
505 // Normalize to the acceptance
506 dndetaMC->Divide(norm);
507 // Scale by the vertex efficiency
508 dndetaMC->Scale(fVtxEff, "width");
509 dndetaMC->SetMarkerColor(kRed+3);
510 dndetaMC->SetMarkerStyle(21);
511 dndetaMC->SetMarkerSize(1);
512 dndetaMC->SetFillStyle(0);
513 Rebin(dndetaMC, rebin);
514 }
515
4cbdf467 516 TH1D* dndetaTruth = 0;
517 if (fSumPrimary) {
518 dndetaTruth = fSumPrimary->ProjectionX("dndetaTruth", -1, -1, "e");
e333578d 519 //dndetaTruth->Scale(1./fNTriggered, "width");
520 dndetaTruth->Scale(1./fNAll, "width");
4cbdf467 521 dndetaTruth->SetMarkerColor(kGray+3);
522 dndetaTruth->SetMarkerStyle(22);
523 dndetaTruth->SetMarkerSize(1);
524 dndetaTruth->SetFillStyle(0);
525 Rebin(dndetaTruth, rebin);
526 }
3a08cca0 527 TH1D* dndetaCentral = 0;
528 if (fSumCentral) {
529 dndetaCentral = fSumCentral->ProjectionX("dndetaCentral", -1, -1, "e");
530 dndetaCentral->SetTitle("ALICE Central");
531 dndetaCentral->Scale(1./fNTriggered, "width");
532 dndetaCentral->SetMarkerColor(kGray+3);
533 dndetaCentral->SetMarkerStyle(22);
534 dndetaCentral->SetMarkerSize(1);
535 dndetaCentral->SetFillStyle(0);
536 Rebin(dndetaCentral, rebin <= 1 ? 1 : 2*(rebin/2));
537 // 1 -> 1
538 // 2 -> 2*2/2 -> 2*1 -> 2
539 // 3 -> 2*3/2 -> 2*1 -> 2
540 // 4 -> 2*4/2 -> 2*2 -> 4
541 // 5 -> 2*5/2 -> 2*2 -> 4
542 // 6 -> 2*6/2 -> 2*3 -> 6
543 }
4cbdf467 544
3a08cca0 545 DrawIt(dndeta, dndetaMC, dndetaTruth, dndetaCentral,
546 mask, energy, doHHD, doComp);
7e4038b5 547
82fc512a 548 return kTRUE;
549 }
550 //__________________________________________________________________
551 /**
552 */
3a08cca0 553 void DrawIt(TH1* dndeta, TH1* dndetaMC, TH1* dndetaTruth, TH1* dndetaCentral,
4cbdf467 554 Int_t mask, Int_t energy, Bool_t doHHD,
e333578d 555 Bool_t doComp)
82fc512a 556 {
557 // --- 1st part - prepare data -----------------------------------
e333578d 558 TH1* dndetaSym = Symmetrice(dndeta);
7e4038b5 559
270764db 560 Double_t max = dndeta->GetMaximum();
561
562 // Make our histogram stack
7e4038b5 563 THStack* stack = new THStack("results", "Results");
270764db 564
e333578d 565 TH1* dndetaTruthSym = 0;
566 if (dndetaTruth) {
567 dndetaTruth->SetFillColor(kGray);
568 dndetaTruth->SetFillStyle(3001);
569 dndetaTruthSym = Symmetrice(dndetaTruth);
8329a584 570 stack->Add(dndetaTruthSym, "e5 p");
571 stack->Add(dndetaTruth, "e5 p");
4cbdf467 572 Info("DrawIt", "Maximum of MC dndeta (truth): %f, was %f",
e333578d 573 dndetaTruth->GetMaximum(),dndeta->GetMaximum());
574 max = TMath::Max(dndetaTruth->GetMaximum(),max);
4cbdf467 575 }
7e4038b5 576
82fc512a 577 // Get the data from HHD's analysis - if available
e333578d 578 TH1* dndetaHHD = 0;
579 TH1* dndetaHHDSym = 0;
8329a584 580 // Info("DrawIt", "Will %sdraw HHD results", (doHHD ? "" : "not "));
f4494b7a 581 if (doHHD) {
582 TString hhdName(fOut->GetName());
583 hhdName.ReplaceAll("dndeta", "hhd");
e333578d 584 dndetaHHD = GetHHD(hhdName.Data(), mask & AliAODForwardMult::kNSD);
585 dndetaHHDSym = 0;
586 if (dndetaHHD) {
f4494b7a 587 // Symmetrice and add to stack
e333578d 588 dndetaHHD->SetTitle("ALICE Forward (HHD)");
589 dndetaHHDSym = Symmetrice(dndetaHHD);
590 stack->Add(dndetaHHDSym);
591 stack->Add(dndetaHHD);
592 max = TMath::Max(dndetaHHD->GetMaximum(),max);
f4494b7a 593 }
594 else
595 Warning("DrawIt", "No HHD data found");
270764db 596 fOut->cd();
7e4038b5 597 }
598
270764db 599 // If we have MC analysed data, plot it
600 if (dndetaMC) {
e333578d 601 TH1* dndetaMCSym = Symmetrice(dndetaMC);
602 stack->Add(dndetaMCSym);
270764db 603 stack->Add(dndetaMC);
270764db 604 max = TMath::Max(dndetaMC->GetMaximum(),max);
605 }
606
607 // Add the analysis results to the list
e333578d 608 stack->Add(dndetaSym);
270764db 609 stack->Add(dndeta);
270764db 610
3a08cca0 611 // If we have central region data, add that
612 if (dndetaCentral) {
613 stack->Add(dndetaCentral);
614 max = TMath::Max(dndetaCentral->GetMaximum(),max);
615 }
616
617
82fc512a 618 // Get graph of 'other' data - e.g., UA5, CMS, ... - and check if
619 // there's any graphs. Set the pad division based on that.
8329a584 620 // Info("DrawIt", "Will %sdraw other results", (doComp ? "" : "not "));
f4494b7a 621 TMultiGraph* other = (doComp ? GetData(energy, mask) : 0);
e333578d 622 THStack* ratios = MakeRatios(dndeta, dndetaSym,
623 dndetaHHD, dndetaHHDSym,
624 dndetaTruth, dndetaTruthSym,
625 other);
7e4038b5 626
82fc512a 627 // Check if we have ratios
628
629 // --- 2nd part - Draw in canvas ---------------------------------
630 // Make a canvas
7e4038b5 631 gStyle->SetOptTitle(0);
f4494b7a 632 gStyle->SetTitleFont(132, "xyz");
633 gStyle->SetLabelFont(132, "xyz");
7e4038b5 634 TCanvas* c = new TCanvas("c", "C", 900, 800);
635 c->SetFillColor(0);
636 c->SetBorderMode(0);
637 c->SetBorderSize(0);
638 c->cd();
639
82fc512a 640 Double_t yd = (ratios ? 0.3 : 0);
641
642 // Make a sub-pad for the result itself
7e4038b5 643 TPad* p1 = new TPad("p1", "p1", 0, yd, 1.0, 1.0, 0, 0);
644 p1->SetTopMargin(0.05);
82fc512a 645 p1->SetBottomMargin(ratios ? 0.001 : 0.1);
7e4038b5 646 p1->SetRightMargin(0.05);
647 p1->SetGridx();
648 p1->SetTicks(1,1);
649 p1->Draw();
650 p1->cd();
82fc512a 651
652 // Fix the apperance of the stack and redraw.
270764db 653 if (other) {
654 TGraphAsymmErrors* o = 0;
655 TIter nextG(other->GetListOfGraphs());
656 while ((o = static_cast<TGraphAsymmErrors*>(nextG()))) {
657 Double_t gmax = TMath::MaxElement(o->GetN(), o->GetY());
8329a584 658 //Info("DrawIt", "Maximum of %s is %f, was %f", o->GetName(),gmax,max);
270764db 659 max = TMath::Max(max, gmax);
660 }
661 }
662 max *= 1.1;
8329a584 663 // Info("DrawIt", "Setting maximum to %f", max);
82fc512a 664 stack->SetMinimum(ratios ? -0.1 : 0);
270764db 665 stack->SetMaximum(max);
1174780f 666 FixAxis(stack, 1/(1-yd)/1.5,
667 "#frac{1}{#it{N}} #frac{#it{dN}_{ch}}{#it{d#eta}}");
7e4038b5 668 p1->Clear();
669 stack->DrawClone("nostack e1");
670
82fc512a 671 // Draw other data
672 if (other) {
673 TGraphAsymmErrors* o = 0;
674 TIter nextG(other->GetListOfGraphs());
270764db 675 while ((o = static_cast<TGraphAsymmErrors*>(nextG())))
82fc512a 676 o->Draw("same p");
fa4236ed 677 }
678
82fc512a 679 // Make a legend in the main result pad
7e4038b5 680 TString trigs(AliAODForwardMult::GetTriggerString(mask));
65a1e0cd 681 TLegend* l = p1->BuildLegend(.15,p1->GetBottomMargin()+.01,.90,.35);
682 l->SetNColumns(2);
7e4038b5 683 l->SetFillColor(0);
684 l->SetFillStyle(0);
685 l->SetBorderSize(0);
f4494b7a 686 l->SetTextFont(132);
7e4038b5 687 p1->cd();
65a1e0cd 688
82fc512a 689 // Put a title on top
690 TLatex* tit = new TLatex(0.10, 0.95, fTitle.Data());
691 tit->SetNDC();
f4494b7a 692 tit->SetTextFont(132);
82fc512a 693 tit->SetTextSize(0.05);
694 tit->Draw();
695
696 // Put a nice label in the plot
1174780f 697 TString eS;
698 if (energy > 1000) eS = Form("%4.2fTeV", float(energy)/1000);
699 else eS = Form("%3dGeV", energy);
f4494b7a 700 TLatex* tt = new TLatex(.93, .93,
1174780f 701 Form("#sqrt{s}=%s, %s", eS.Data(),
65a1e0cd 702 AliAODForwardMult::GetTriggerString(mask)));
703 tt->SetNDC();
f4494b7a 704 tt->SetTextFont(132);
705 tt->SetTextAlign(33);
65a1e0cd 706 tt->Draw();
707
1174780f 708 // Put number of accepted events on the plot
709 TLatex* et = new TLatex(.93, .83, Form("%d events", fNAccepted));
710 et->SetNDC();
711 et->SetTextFont(132);
712 et->SetTextAlign(33);
713 et->Draw();
714
715 // Put number of accepted events on the plot
716 TLatex* vt = new TLatex(.93, .88,
717 Form("v_{z}#in[%+5.1f,%+5.1f]cm", fVtxMin, fVtxMax));
718 vt->SetNDC();
719 vt->SetTextFont(132);
720 vt->SetTextAlign(33);
721 vt->Draw();
722
723 // Mark the plot as preliminary
724 TLatex* pt = new TLatex(.12, .93, "Preliminary");
65a1e0cd 725 pt->SetNDC();
f4494b7a 726 pt->SetTextFont(22);
65a1e0cd 727 pt->SetTextSize(0.07);
728 pt->SetTextColor(kRed+1);
1174780f 729 pt->SetTextAlign(13);
65a1e0cd 730 pt->Draw();
7e4038b5 731 c->cd();
732
82fc512a 733 // If we do not have the ratios, fix up the display
734 // p1->SetPad(0, 0, 1, 1);
735 // p1->SetBottomMargin(0.1);
736 // l->SetY1(0.11);
737 // stack->SetMinimum(0);
738 // FixAxis(stack, (1-yd)/1, "#frac{1}{N} #frac{dN_{ch}}{#eta}",10,false);
739 if (ratios) {
740 // If we do have the ratios, then make a new pad and draw the
741 // ratios there
7e4038b5 742 c->cd();
7e4038b5 743 TPad* p2 = new TPad("p2", "p2", 0, 0.0, 1.0, yd, 0, 0);
744 p2->SetTopMargin(0.001);
745 p2->SetRightMargin(0.05);
746 p2->SetBottomMargin(1/yd * 0.07);
747 p2->SetGridx();
748 p2->SetTicks(1,1);
749 p2->Draw();
750 p2->cd();
82fc512a 751
752 // Fix up axis
65a1e0cd 753 FixAxis(ratios, 1/yd/1.5, "Ratios", 5);
82fc512a 754
755 // Fix up y range and redraw
65a1e0cd 756 ratios->SetMinimum(.58);
757 ratios->SetMaximum(1.22);
7e4038b5 758 p2->Clear();
759 ratios->DrawClone("nostack e1");
760
82fc512a 761 // Make a legend
65a1e0cd 762 TLegend* l2 = p2->BuildLegend(.15,p2->GetBottomMargin()+.01,.9,.6);
763 l2->SetNColumns(2);
7e4038b5 764 l2->SetFillColor(0);
765 l2->SetFillStyle(0);
766 l2->SetBorderSize(0);
f4494b7a 767 l2->SetTextFont(132);
768
82fc512a 769 // Make a nice band from 0.9 to 1.1
7e4038b5 770 TGraphErrors* band = new TGraphErrors(2);
e333578d 771 band->SetPoint(0, dndetaSym->GetXaxis()->GetXmin(), 1);
7e4038b5 772 band->SetPoint(1, dndeta->GetXaxis()->GetXmax(), 1);
773 band->SetPointError(0, 0, .1);
774 band->SetPointError(1, 0, .1);
775 band->SetFillColor(kYellow+2);
776 band->SetFillStyle(3002);
777 band->Draw("3 same");
82fc512a 778
779 // Replot the ratios on top
7e4038b5 780 ratios->DrawClone("nostack e1 same");
781
782 c->cd();
783 }
7e4038b5 784
82fc512a 785 // Plot to disk
7e4038b5 786 TString imgName(fOut->GetName());
787 imgName.ReplaceAll(".root", ".png");
788 c->SaveAs(imgName.Data());
f4494b7a 789 imgName.ReplaceAll(".png", ".C");
790 c->SaveAs(imgName.Data());
270764db 791
792 fOut->cd();
7e4038b5 793 stack->Write();
82fc512a 794 if (other) other->Write();
795 if (ratios) ratios->Write();
7e4038b5 796
82fc512a 797 // Close our file
7e4038b5 798 fOut->Close();
7e4038b5 799 }
800 //__________________________________________________________________
801 /**
802 * Get the result from previous analysis code
803 *
c389303e 804 * @param fn File to open
805 * @param nsd Whether this is NSD
7e4038b5 806 *
807 * @return null or result of previous analysis code
808 */
809 TH1* GetHHD(const char* fn="fmd_dNdeta_mult.root", bool nsd=false)
810 {
811 TDirectory* savdir = gDirectory;
65a1e0cd 812 if (gSystem->AccessPathName(fn)) {
813 Warning("GetHHD", "Output of HHD analysis (%s) not available", fn);
814 return 0;
815 }
7e4038b5 816 TFile* file = TFile::Open(fn, "READ");
817 if (!file) {
818 Warning("GetHHD", "couldn't open HHD file %s", fn);
819 savdir->cd();
820 return 0;
821 }
822 TString hist(Form("dNdeta_dNdeta%s", (nsd ? "NSD" : "")));
823 TH1* h = static_cast<TH1*>(file->Get(hist.Data()));
824 if (!h) {
825 Warning("GetHHD", "Couldn't find HHD histogram %s in %s",
826 hist.Data(), fn);
7e4038b5 827 file->Close();
828 savdir->cd();
829 return 0;
830 }
831 TH1* r = static_cast<TH1*>(h->Clone("dndeta_hhd"));
832 r->SetTitle("1/N dN_{ch}/d#eta (HHD)");
833 r->SetFillStyle(0);
834 r->SetFillColor(0);
835 r->SetMarkerStyle(21);
836 r->SetMarkerColor(kPink+1);
837 r->SetDirectory(savdir);
838
839 file->Close();
840 savdir->cd();
841 return r;
842 }
82fc512a 843 //__________________________________________________________________
844 /**
845 */
846 THStack* MakeRatios(const TH1* dndeta, const TH1* sym,
847 const TH1* hhd, const TH1* hhdsym,
270764db 848 const TH1* mc, const TH1* mcsym,
82fc512a 849 TMultiGraph* other) const
850 {
851 // If we have 'other' data, then do the ratio of the results to that
852 Bool_t hasOther = (other && other->GetListOfGraphs() &&
853 other->GetListOfGraphs()->GetEntries() > 0);
854 Bool_t hasHhd = (hhd && hhdsym);
270764db 855 if (!hasOther && !hasHhd && !mc && !mcsym) return 0;
82fc512a 856
857 THStack* ratios = new THStack("ratios", "Ratios");
858 if (hasOther) {
859 TGraphAsymmErrors* o = 0;
860 TIter nextG(other->GetListOfGraphs());
861 while ((o = static_cast<TGraphAsymmErrors*>(nextG()))) {
862 ratios->Add(Ratio(dndeta, o));
863 ratios->Add(Ratio(sym, o));
864 ratios->Add(Ratio(hhd, o));
865 ratios->Add(Ratio(hhdsym, o));
866 }
867 }
868
869 // If we have data from HHD's analysis, then do the ratio of
870 // our result to that data.
871 if (hasHhd) {
872 TH1F* t1 = static_cast<TH1F*>(dndeta->Clone(Form("%s_%s",
873 dndeta->GetName(),
874 hhd->GetName())));
82fc512a 875 TH1F* t2 = static_cast<TH1F*>(sym->Clone(Form("%s_%s",
876 sym->GetName(),
877 hhdsym->GetName())));
270764db 878 t1->SetTitle(Form("%s / %s", dndeta->GetTitle(), hhd->GetTitle()));
82fc512a 879 t2->SetTitle(Form("%s / %s", sym->GetTitle(), hhdsym->GetTitle()));
880 t1->Divide(hhd);
881 t2->Divide(hhdsym);
270764db 882 t1->SetMarkerColor(hhd->GetMarkerColor());
883 t2->SetMarkerColor(hhdsym->GetMarkerColor());
884 ratios->Add(t1);
885 ratios->Add(t2);
886 }
887
888 // Do comparison to MC
889 if (mc) {
890 TH1D* t1 = static_cast<TH1D*>(dndeta->Clone(Form("%s_%s",
891 dndeta->GetName(),
892 mc->GetName())));
893 TH1D* t2 = static_cast<TH1D*>(sym->Clone(Form("%s_%s",
894 sym->GetName(),
895 mcsym->GetName())));
896 t1->SetTitle(Form("%s / %s", dndeta->GetTitle(), mc->GetTitle()));
897 t2->SetTitle(Form("%s / %s", sym->GetTitle(), mcsym->GetTitle()));
898 t1->Divide(mc);
899 t2->Divide(mcsym);
900 t1->SetMarkerColor(mc->GetMarkerColor());
901 t2->SetMarkerColor(mcsym->GetMarkerColor());
82fc512a 902 ratios->Add(t1);
903 ratios->Add(t2);
904 }
905
906 // Check if we have ratios
907 Bool_t hasRatios = (ratios->GetHists() &&
908 (ratios->GetHists()->GetEntries() > 0));
8329a584 909#if 0
82fc512a 910 Info("MakeRatios", "Got a total of %d ratios", !hasRatios ? 0 :
911 ratios->GetHists()->GetEntries());
8329a584 912#endif
82fc512a 913
914 if (!hasRatios) { delete ratios; ratios = 0; }
915 return ratios;
916 }
917
7e4038b5 918 //__________________________________________________________________
919 /**
920 * Fix the apperance of the axis in a stack
921 *
922 * @param stack stack of histogram
923 * @param s Scaling factor
924 * @param ytitle Y axis title
925 * @param force Whether to draw the stack first or not
c389303e 926 * @param ynDiv Divisions on Y axis
7e4038b5 927 */
928 void FixAxis(THStack* stack, Double_t s, const char* ytitle,
65a1e0cd 929 Int_t ynDiv=10, Bool_t force=true)
7e4038b5 930 {
931 if (force) stack->Draw("nostack e1");
932
933 TH1* h = stack->GetHistogram();
934 if (!h) return;
935
936 h->SetXTitle("#eta");
937 h->SetYTitle(ytitle);
938 TAxis* xa = h->GetXaxis();
939 TAxis* ya = h->GetYaxis();
940 if (xa) {
941 xa->SetTitle("#eta");
942 // xa->SetTicks("+-");
943 xa->SetTitleSize(s*xa->GetTitleSize());
944 xa->SetLabelSize(s*xa->GetLabelSize());
945 xa->SetTickLength(s*xa->GetTickLength());
946 }
947 if (ya) {
948 ya->SetTitle(ytitle);
65a1e0cd 949 ya->SetDecimals();
7e4038b5 950 // ya->SetTicks("+-");
65a1e0cd 951 ya->SetNdivisions(ynDiv);
7e4038b5 952 ya->SetTitleSize(s*ya->GetTitleSize());
953 ya->SetLabelSize(s*ya->GetLabelSize());
954 }
955 }
956 //__________________________________________________________________
957 /**
958 * Compute the ratio of @a h to @a g. @a g is evaluated at the bin
959 * centers of @a h
960 *
961 * @param h Numerator
962 * @param g Divisor
963 *
964 * @return h/g
965 */
966 TH1* Ratio(const TH1* h, const TGraph* g) const
967 {
968 if (!h || !g) return 0;
969
970 TH1* ret = static_cast<TH1*>(h->Clone("tmp"));
971 ret->SetName(Form("%s_over_%s", h->GetName(), g->GetName()));
972 ret->SetTitle(Form("%s / %s", h->GetTitle(), g->GetTitle()));
973 ret->Reset();
974 ret->SetMarkerStyle(h->GetMarkerStyle());
975 ret->SetMarkerColor(g->GetMarkerColor());
65a1e0cd 976 ret->SetMarkerSize(0.9*g->GetMarkerSize());
7e4038b5 977 Double_t xlow = g->GetX()[0];
978 Double_t xhigh = g->GetX()[g->GetN()-1];
979 if (xlow > xhigh) { Double_t t = xhigh; xhigh = xlow; xlow = t; }
980
981 for (Int_t i = 1; i <= h->GetNbinsX(); i++) {
982 Double_t c = h->GetBinContent(i);
983 if (c <= 0) continue;
984
985 Double_t x = h->GetBinCenter(i);
986 if (x < xlow || x > xhigh) continue;
987
988 Double_t f = g->Eval(x);
989 if (f <= 0) continue;
990
991 ret->SetBinContent(i, c / f);
992 ret->SetBinError(i, h->GetBinError(i) / f);
993 }
994 if (ret->GetEntries() <= 0) { delete ret; ret = 0; }
995 return ret;
996 }
997
998 //__________________________________________________________________
999 /**
1000 * Make an extension of @a h to make it symmetric about 0
1001 *
1002 * @param h Histogram to symmertrice
1003 *
1004 * @return Symmetric extension of @a h
1005 */
1006 TH1* Symmetrice(const TH1* h) const
1007 {
270764db 1008 fOut->cd();
1009
7e4038b5 1010 Int_t nBins = h->GetNbinsX();
1011 TH1* s = new TH1D(Form("%s_mirror", h->GetName()),
1012 Form("%s (mirrored)", h->GetTitle()),
1013 nBins,
1014 -h->GetXaxis()->GetXmax(),
1015 -h->GetXaxis()->GetXmin());
1016 s->SetMarkerColor(h->GetMarkerColor());
1017 s->SetMarkerSize(h->GetMarkerSize());
1018 s->SetMarkerStyle(h->GetMarkerStyle()+4);
1019 s->SetFillColor(h->GetFillColor());
1020 s->SetFillStyle(h->GetFillStyle());
270764db 1021 // s->SetDirectory(0);
7e4038b5 1022
1023 // Find the first and last bin with data
1024 Int_t first = nBins+1;
1025 Int_t last = 0;
1026 for (Int_t i = 1; i <= nBins; i++) {
1027 if (h->GetBinContent(i) <= 0) continue;
1028 first = TMath::Min(first, i);
1029 last = TMath::Max(last, i);
1030 }
1031
1032 Double_t xfirst = h->GetBinCenter(first-1);
1033 Int_t f1 = h->GetXaxis()->FindBin(-xfirst);
1034 Int_t l2 = s->GetXaxis()->FindBin(xfirst);
1035 for (Int_t i = f1, j=l2; i <= last; i++,j--) {
1036 s->SetBinContent(j, h->GetBinContent(i));
1037 s->SetBinError(j, h->GetBinError(i));
1038 }
e333578d 1039 // Fill in overlap bin
1040 s->SetBinContent(l2+1, h->GetBinContent(first));
1041 s->SetBinError(l2+1, h->GetBinError(first));
7e4038b5 1042 return s;
1043 }
1044 //__________________________________________________________________
1045 /**
1046 * Rebin a histogram
1047 *
1048 * @param h Histogram to rebin
1049 * @param rebin Rebinning factor
1050 *
1051 * @return
1052 */
1053 virtual void Rebin(TH1* h, Int_t rebin) const
1054 {
1055 if (rebin <= 1) return;
1056
1057 Int_t nBins = h->GetNbinsX();
1058 if(nBins % rebin != 0) {
1059 Warning("Rebin", "Rebin factor %d is not a devisor of current number "
1060 "of bins %d in the histogram %s", rebin, nBins, h->GetName());
1061 return;
1062 }
1063
1064 // Make a copy
1065 TH1* tmp = static_cast<TH1*>(h->Clone("tmp"));
1066 tmp->Rebin(rebin);
1067 tmp->SetDirectory(0);
1068
1069 // The new number of bins
1070 Int_t nBinsNew = nBins / rebin;
1071 for(Int_t i = 1;i<= nBinsNew; i++) {
1072 Double_t content = 0;
1073 Double_t sumw = 0;
1074 Double_t wsum = 0;
1075 Int_t nbins = 0;
1076 for(Int_t j = 1; j<=rebin;j++) {
1077 Int_t bin = (i-1)*rebin + j;
1078 if(h->GetBinContent(bin) <= 0) continue;
1079 Double_t c = h->GetBinContent(bin);
cc83fca2 1080 Double_t e = h->GetBinError(bin);
1081 Double_t w = 1 / (e*e); // 1/c/c
7e4038b5 1082 content += c;
1083 sumw += w;
1084 wsum += w * c;
1085 nbins++;
1086 }
1087
cc83fca2 1088 if(content > 0 && nbins > 0) {
7e4038b5 1089 tmp->SetBinContent(i, wsum / sumw);
cc83fca2 1090 tmp->SetBinError(i,1./TMath::Sqrt(sumw));
7e4038b5 1091 }
1092 }
1093
1094 // Finally, rebin the histogram, and set new content
1095 h->Rebin(rebin);
1c762251 1096 h->Reset();
cc83fca2 1097 for(Int_t i = 1; i<= nBinsNew; i++) {
7e4038b5 1098 h->SetBinContent(i,tmp->GetBinContent(i));
cc83fca2 1099 h->SetBinError(i, tmp->GetBinError(i));
7e4038b5 1100 }
1101
1102 delete tmp;
1103 }
1104};
1105
1106//____________________________________________________________________
1107//
1108// EOF
1109//
1110