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