16 #include "AliAODForwardMult.h"
19 * @defgroup pwg2_forward_analysis_scripts PWG2 Forward analysis - scripts
21 * @ingroup pwg2_forward_analysis
24 * Example macro to loop over the event-by-event 2D histogram of
26 * \frac{d^{2}N_{ch}}{d\eta\,d\phi}
30 * The class needs the files <<i>base</i>><tt>_hists.root</tt>
31 * containing the histograms generated by AliForwardMultiplicity and
32 * the file <<i>base</i>><tt>_aods.root</tt> containing the tree
33 * with AliAODEvent objects where AliAODForwardMult objects have been
34 * added to in the branch <tt>Forward</tt>
36 * @ingroup pwg2_forward_analysis_scripts
44 * @param special If true, add to the list of 'specials'
46 DrawRes(Bool_t special=true)
62 //__________________________________________________________________
64 * Open the files <<i>base</i>><tt>_hists.root</tt>
65 * containing the histograms generated by AliForwardMultiplicity and
66 * the file <<i>base</i>><tt>_aods.root</tt> containing the tree
67 * with AliAODEvent objects.
69 * @param base Base name of files
70 * @param vzMin Minimum collision vertex z position to use
71 * @param vzMax Maximum collision vertex z position to use
72 * @param rebin Rebinning factor
74 * @return true on success, false otherwise
76 Bool_t Open(const char* base,
84 if (fVzMax < fVzMin && fVzMin < 0) fVzMax = -fVzMin;
87 // Clear previously created data objects
89 if (fTotal1D) { delete fTotal1D; fTotal1D = 0; }
90 if (fTotal2D) { delete fTotal2D; fTotal2D = 0; }
91 if (fTree && fTree->GetCurrentFile()) {
92 fTree->GetCurrentFile()->Close();
98 TString fn = TString::Format("%s_aods.root", base);
99 TFile* file = TFile::Open(fn.Data(), "READ");
101 Error("Init", "Couldn't open %s", fn.Data());
106 fTree = static_cast<TTree*>(file->Get("aodTree"));
108 Error("Init", "Couldn't get the tree");
112 // Set the branch pointer
113 fTree->SetBranchAddress("Forward", &fAOD);
115 // Open the histogram file
116 fn = TString::Format("%s_hists.root", base);
117 file = TFile::Open(fn.Data(), "READ");
119 Error("Init", "Couldn't open %s", fn.Data());
123 // Get the list stored in the file
125 static_cast<TList*>(file->Get("PWG2forwardDnDeta/Forward"));
127 Error("Init", "Couldn't get forward list");
131 // Get the list from the collector
133 static_cast<TList*>(forward->FindObject("fmdHistCollector"));
135 Error("Init", "Couldn't get collector list");
139 // Get the event (by vertex bin) histogram
140 fEvents = static_cast<TH1I*>(forward->FindObject("nEventsTrVtx"));
142 Error("Init", "Couldn't get the event histogram");
146 // Find the min/max bins to use based on the cuts given
147 fBinVzMin = fEvents->FindBin(fVzMin);
148 fBinVzMax = fEvents->FindBin(fVzMax-.0000001);
149 Info("Open", "Selected vertex bins are [%d,%d]", fBinVzMin, fBinVzMax);
153 //__________________________________________________________________
155 * Check if the passed vertex bin number [1,nVtxBins] is within our
158 * @param bin Vertex bin [1,nVtxBins]
160 * @return true if within cut, false otherwise
162 Bool_t IsInsideVtxCut(Int_t bin) const
164 return bin >= fBinVzMin && bin <= fBinVzMax;
167 //__________________________________________________________________
169 * Make a 1D histogram of @f$ dN_{ch}/d\eta@f$ with the given name and
172 * @param name Name of histogram
173 * @param title Title of histogram
176 * @return Newly allocated 1D histogram object
178 TH1D* Make1D(const char* name, const char* title, const TAxis* a1)
180 TH1D* ret = new TH1D(name, title,
181 a1->GetNbins(), a1->GetXmin(), a1->GetXmax());
182 ret->SetXTitle("#eta");
183 ret->SetYTitle("#frac{1}{N}#frac{dN_{ch}}{d#eta}");
185 ret->SetMarkerColor(kRed+1);
186 ret->SetLineColor(kRed+1);
187 ret->SetMarkerStyle(24);
188 ret->SetMarkerSize(1);
190 ret->SetDirectory(0);
194 //__________________________________________________________________
196 * Make a 2D histogram of @f$ d^{2}N_{ch}/d\eta\,d\phi@f$
198 * @param name Name of histogram
199 * @param title Title of histogram
205 TH2D* Make2D(const char* name, const char* title,
206 const TAxis* a1, const TAxis* a2)
208 TH2D* ret = new TH2D(name, title,
209 a1->GetNbins(), a1->GetXmin(), a1->GetXmax(),
210 a2->GetNbins(), a2->GetXmin(), a2->GetXmax());
211 ret->SetXTitle("#eta");
212 ret->SetYTitle("#varphi");
213 ret->SetZTitle("#frac{1}{N}#frac{dN^{2}_{ch}}{d#etad#varphi}");
216 ret->SetDirectory(0);
220 //__________________________________________________________________
222 * Utility function to set-up histograms based on the input
223 * @f$ dd^{2}N_{ch}/d\eta\,d\phi@f$ histogram. This member function
224 * is called on the first event so that we have the proper binning
226 * @param templ Input histogram
228 * @return true on succcess
230 Bool_t FirstEvent(const TH2D& templ)
232 const TAxis* etaAxis = templ.GetXaxis();
233 const TAxis* phiAxis = templ.GetYaxis();
235 // Generate sum histograms.
236 // - fTotal1D will be the sum of projections on the X axis of the input
238 // - fTotal2D will be the direct sum of the input histograms.
239 // - fFromVtx will be the sum of the per vertex histograms after
240 // processing all events
241 fTotal1D = Make1D("dndeta",
242 "#frac{1}{N}#frac{dN_{ch}}{d#eta} direct sum", etaAxis);
243 fTotal2D = Make2D("d2ndetadphi",
244 "#frac{1}{N}#frac{dN^{2}_{ch}}{d#etad#phi} direct sum",
246 fFromVtx = Make1D("dndeta_test", "#frac{1}{N}#frac{dN_{ch}}{d#eta} "
247 "from VTX", etaAxis);
248 fTotal1D->SetMarkerStyle(25);
249 fTotal1D->SetMarkerSize(1.1);
250 fNorm = new TH1D("norm", "Normalisation",
254 fNorm->SetFillColor(kRed);
255 fNorm->SetFillStyle(3001);
256 fNorm->SetXTitle("#eta");
257 fNorm->SetYTitle("Normalisation");
259 fNorm->SetDirectory(0);
260 fVtx = new TH1D("vtx", "Events per vertex bin",
261 fEvents->GetXaxis()->GetNbins(),
262 fEvents->GetXaxis()->GetXmin(),
263 fEvents->GetXaxis()->GetXmax());
264 fVtx->SetXTitle("v_{z} [cm]");
265 fVtx->SetYTitle("Events");
266 fVtx->SetDirectory(0);
267 fVtx->SetFillColor(kRed+1);
268 fVtx->SetFillStyle(3001);
271 // Generate the per-vertex bin histograms. These will be the sum
272 // of each of the per-event input histograms for a given vertex range.
273 for (Int_t i = fBinVzMin; i <= fBinVzMax; i++) {
274 TH1* h1 = Make1D(Form("dndeta_vz%02d", i),
275 Form("#frac{1}{N}#frac{dN_{ch}}{d#eta}, vtxbin=%d", i),
277 fByVtx1D.AddAtAndExpand(h1, i);
283 //__________________________________________________________________
288 * @return true on success, false otherwise
292 // Get the number of events in the tree
293 Int_t nEntries = fTree->GetEntries();
296 // Loop over the events in the tree
297 for (Int_t event = 0; event < nEntries; event++) {
298 fTree->GetEntry(event);
300 // Get our input histogram
301 const TH2D& hist = fAOD->GetHistogram();
304 // If fTotal1D or fTotal2D are not made yet, do so (first event)
305 if (!fTotal2D || !fTotal1D) {
306 if (!FirstEvent(hist)) {
307 Error("Process", "Failed to initialize on first event");
313 if (!fAOD->IsTriggerBits(AliAODForwardMult::kInel)) {
314 // Info("Process", "Not an INEL event");
318 // Get the vertex bin - add 1 as we are using histogram bin
319 // numbers in this class
320 Int_t vtxBin = fAOD->GetVtxBin()+1;
322 // Check if we're within vertex cut
323 if (!IsInsideVtxCut(vtxBin)) {
324 Info("Process", "In event # %d, %d not within vertex cut "
326 event, vtxBin, fBinVzMin, fBinVzMax, fVzMin, fVzMax);
329 fVtx->AddBinContent(vtxBin);
331 // Increment our accepted counter
334 // Get the scale of this vertex range
335 Double_t vtxScale = fEvents->GetBinContent(vtxBin);
337 // Get 'by-vertex' histograms
338 TH1* tmp1 = static_cast<TH1D*>(fByVtx1D.At(vtxBin));
340 Warning("Process", "No histogram for vertex bin %d)",vtxBin);
344 Double_t scale = 1. / vtxScale;
345 if (tmp1->InheritsFrom(TProfile::Class()))
348 if (!AddContrib(hist, *tmp1, scale)) return kFALSE;
351 for (Int_t iVz = fBinVzMin; iVz <= fBinVzMax; iVz++) {
352 TList* l = static_cast<TList*>(fCollect
353 ->FindObject(Form("vtxbin%02d",iVz-1)));
355 Error("Process", "List vtxbin%02d not found in %s",
356 iVz-1, fCollect->GetName());
359 TH1F* ve = static_cast<TH1F*>(l->FindObject("etaAcceptance"));
361 Error("Process", "No eta acceptance histogram found in "
362 "vtxbin%02d/etaAcceptance", iVz-1);
366 fNorm->Add(ve, fVtx->GetBinContent(iVz));
368 for (Int_t i = 1; i <= fNorm->GetNbinsX(); i++)
369 fNorm->SetBinError(i, 0);
372 Info("Process", "Accepted %6d out of %6d events", fNAccepted, nEntries);
375 //__________________________________________________________________
376 Bool_t AddContrib(const TH2D& hist, TH1& vtx1D, Double_t scale)
378 // Make a projection on the X axis of the input histogram
379 TH1D* proj = hist.ProjectionX("_px", 0, -1, "e");
381 // Add to per-vertex histogram
382 vtx1D.Add(proj); // , scale);
384 #if defined(USE_NORM_HIST)
388 #if defined(USE_WEIGHTED_MEAN)
389 Int_t nBinPhi = hist.GetXaxis()->GetNbins();
390 for (Int_t binEta = 1; binEta <= nBinEta; binEta++) {
391 AddBinContrib(binEta, *proj, *fTotal1D);
392 for (Int_t binPhi = 1; binPhi < nBinPhi; binPhi++)
393 AddBinContrib(hist.GetBin(binEta, binPhi), hist, *fTotal2D);
396 // Add to 1D summed histogram
397 fTotal1D->Add(proj); // , scale);
399 // Add to 2D summed histogram
400 fTotal2D->Add(&hist); // , scale);
403 // Remove the projection
408 //__________________________________________________________________
409 Bool_t AddBinContrib(Int_t bin, const TH1& in, TH1& out)
411 Double_t ic = in.GetBinContent(bin);
412 Double_t ie = in.GetBinError(bin);
413 if (ie <= 0.00001) return kTRUE;
415 Double_t iw = 1 / (ie*ie);
416 Double_t oc = out.GetBinContent(bin);
417 Double_t oe = out.GetBinError(bin);
419 // Store weighted sum in histogram
420 out.SetBinContent(bin, oc + iw * ic);
421 // Store sum of weights in histogram
422 out.SetBinError(bin, oe + iw);
426 //__________________________________________________________________
427 Bool_t SetResult(TH1*)
429 #if defined(USE_WEIGHTED_MEAN)
431 Int_t nBinEta = fTotal2D->GetXaxis()->GetNbins();
432 Int_t nBinPhi = fTotal1D->GetXaxis()->GetNbins();
433 for (Int_t binEta = 1; binEta <= nBinEta; binEta++) {
434 SetBinResult(binEta, *fTotal1D);
435 for (Int_t binPhi = 1; binPhi < nBinPhi; binPhi++)
436 SetBinResult(fTotal2D->GetBin(binEta, binPhi), *fTotal2D);
438 #elif defined (USE_NORM_HIST)
439 fTotal1D->Divide(fNorm);
440 Int_t nBinEta = fTotal2D->GetXaxis()->GetNbins();
441 Int_t nBinPhi = fTotal1D->GetXaxis()->GetNbins();
442 for (Int_t binEta = 1; binEta <= nBinEta; binEta++) {
443 Double_t n = fNorm->GetBinContent(binEta);
444 for (Int_t binPhi = 1; binPhi < nBinPhi; binPhi++) {
446 fTotal2D->SetBinContent(binEta,binPhi,0);
449 Double_t c = fTotal2D->GetBinContent(binEta,binPhi);
450 fTotal2D->SetBinContent(binEta,binPhi,c/n);
455 // fTotal2D->Scale(1, "width");
459 //__________________________________________________________________
460 Bool_t SetBinResult(Int_t bin, TH1& in)
462 Double_t ic = in.GetBinContent(bin);
463 Double_t ie = in.GetBinError(bin);
464 if (ie <= 0.00001) return kTRUE;
466 Double_t av = ic / ie;
467 Double_t er = TMath::Sqrt(1/ie);
471 // \frac{\sum_i w_i c_i}{\sum_i w_i}
473 // where @f$ w_i = 1/e_i^2@f$, and set the error to be
475 // \sqrt{\frac{1}{\sum_i w_i}}
477 in.SetBinContent(bin, av);
478 in.SetBinError(bin, er);
482 //__________________________________________________________________
484 * Called at the end of the job.
486 * It plots the result of the analysis in tree canvases.
487 * - One shows the per-vertex accumalted histograms and compares them
488 * to the per-vertex histograms made in the analysis.
489 * - Another shows the final @f$ dN_{ch}/d\eta@f$ calculated in
490 * different ways and compare those to the @f$ dN_{ch}/d\eta@f$ made
491 * during the analysis.
492 * - The last canvas shows the @f$ dd^{2}N_{ch}/d\eta\,d\phi@f$ histogram.
494 * @return true on succes, false otherwise
498 TFile* out = TFile::Open("out.root", "RECREATE");
501 gStyle->SetOptTitle(0);
502 gStyle->SetPadColor(0);
503 gStyle->SetPadBorderSize(0);
504 gStyle->SetPadBorderMode(0);
505 gStyle->SetPadRightMargin(0.05);
506 gStyle->SetPadTopMargin(0.05);
507 gStyle->SetPalette(1);
509 // Get number of bins
510 Int_t nBin = fBinVzMax-fBinVzMin+1;
513 TCanvas* cVtx = new TCanvas("cVtx", "By Vertex", 1000, 700);
514 cVtx->SetBorderSize(0);
515 cVtx->SetBorderMode(0);
516 cVtx->Divide((nBin+.5)/2, 2, 0.0005, 0.0005);
518 // Loop over vertex histograms
520 for (Int_t i = fBinVzMin; i <= fBinVzMax; i++) {
521 TDirectory* vtxDir = out->mkdir(Form("vtx%02d", i));
524 TH1D* vh1 = static_cast<TH1D*>(fByVtx1D.At(i));
526 Error("Finish", "No histogram at %d", i);
532 // Scale and add to output
533 if (fVtx->GetBinContent(i) > 0)
534 vh1->Scale(1. / fVtx->GetBinContent(i), "width");
536 // Write to output file
540 TVirtualPad* pad = cVtx->cd(i-fBinVzMin+1);
541 pad->Divide(1,2,0.005,0);
543 // Draw the per-vertex histogram
547 // Get the same histogram from the analysis and draw it
549 static_cast<TProfile*>(fCollect
550 ->FindObject(Form("dndeta_vtx%02d",i-1)));
551 p->SetMarkerColor(kBlue+1);
552 p->SetLineColor(kBlue+1);
553 p->SetMarkerSize(0.8);
554 p->SetMarkerStyle(20);
558 // Make the ratio of the two histograms and draw it
560 TH1* ratio = static_cast<TH1*>(vh1->Clone(Form("ratio_vtx%02d", i-1)));
561 // ratio->Scale(1./fEvents->GetBinContent(i));
563 ratio->SetMarkerSize(.8);
564 ratio->SetLineColor(kGray);
570 // Get the number of events selected
571 // Int_t nEvSelected = fEvents->Integral(fBinVzMin, fBinVzMax);
574 TCanvas* cTotal1D = new TCanvas("total", "Result", 800, 800);
575 cTotal1D->SetFillColor(0);
576 cTotal1D->SetBorderMode(0);
577 cTotal1D->SetBorderSize(0);
581 TPad* p1 = new TPad("p1", "p1", 0, 0.3, 1.0, 1.0, 0, 0);
585 // Make a stack to 'auto-scale' when plotting more than 1 histogram.
586 THStack* stack = new THStack("results", "Results for #frac{dN_{ch}{d#eta}");
588 // Scale the histogram summed over the vertex bins. This must be
589 // divided by the number of bins we have summed over. If we do
590 // rebinning, we should scale it again.
591 fFromVtx->Divide(fNorm);
592 // fFromVtx->Scale(1.);
593 fFromVtx->Scale(1, "width");
596 if (fRebin > 1) { fFromVtx->Rebin(fRebin); fFromVtx->Scale(1. / fRebin); }
597 stack->Add(fFromVtx, "");
599 // Generate the projection from the direct sum of the input histograms,
600 // and scale it to the number of vertex bins and the bin width
601 TH1* proj = fTotal2D->ProjectionX("dndeta_proj", 0, -1, "e");
602 proj->SetLineColor(kGreen+1);
603 proj->SetMarkerColor(kGreen+1);
604 proj->SetMarkerStyle(24);
605 proj->SetMarkerSize(1.5);
606 proj->SetTitle(Form("%s directly", proj->GetTitle()));
608 proj->Scale(1., "width");
609 stack->Add(proj, "");
611 // Scale our direct sum of the projects of the input histograms to
612 // the number of vertex bins and the bin width. If we do rebinning,
613 // we must scale it one more time.
614 // fTotal1D->Scale(1. / fNAccepted, "width");
615 fTotal1D->Divide(fNorm);
616 fTotal1D->Scale(1., "width");
617 if (fRebin > 1) { fTotal1D->Rebin(fRebin); fTotal1D->Scale(1. / fRebin); }
618 stack->Add(fTotal1D);
620 // Get the result from the analysis and plit that too (after modifying
621 // the style and possible rebinning)
622 TProfile* dtotal = static_cast<TProfile*>(fCollect->FindObject("dndeta"));
624 Error("Finish", "Couldn't get the event histogram");
627 dtotal->SetTitle(Form("%s directly", dtotal->GetTitle()));
628 dtotal->SetLineColor(kBlue+1);
629 dtotal->SetMarkerColor(kBlue+1);
630 dtotal->SetMarkerStyle(20);
631 dtotal->SetMarkerSize(0.8);
632 if (fRebin > 1) { dtotal->Rebin(fRebin); }
633 stack->Add(dtotal, "");
636 stack->Draw("nostack e1");
640 TLegend* l = p1->BuildLegend(0.31, 0.15, 0.5, 0.6);
643 l->SetTextSize(0.04); // l->GetTextSize()/3);
646 // Generate our second pad
647 TPad* p2 = new TPad("p2", "p2", 0, 0.0, 1.0, 0.3, 0, 0);
651 // Create a new stack
652 stack = new THStack("ratios", "Ratios to old method");
653 // Calculate the ratio of our summed over vertex bins to the
654 // result from the analysis and draw it
655 TH1* ratioVtx = static_cast<TH1*>(fFromVtx->Clone("ratioVtx"));
656 ratioVtx->SetDirectory(0);
657 ratioVtx->Divide(dtotal);
658 stack->Add(ratioVtx, "");
660 // Calculate the ratio of our direct sum of input histograms
661 // result from the analysis and draw it
662 TH1* ratioSum = static_cast<TH1*>(fTotal1D->Clone("ratioSum"));
663 ratioSum->SetDirectory(0);
664 ratioSum->Divide(dtotal);
665 stack->Add(ratioSum, "");
667 // Calculate the ratio of our direct sum of input histograms
668 // result from the analysis and draw it
669 TH1* ratioProj = static_cast<TH1*>(proj->Clone("ratioProj"));
670 ratioProj->SetDirectory(0);
671 ratioProj->Divide(dtotal);
672 stack->Add(ratioProj, "");
674 stack->Draw("nostack e1");
680 // Generate the last canvas and show the summed input histogram
681 TCanvas* other = new TCanvas("other", "Other", 800, 600);
682 other->SetFillColor(0);
683 other->SetBorderMode(0);
684 other->SetBorderSize(0);
695 // fTotal2D->Draw("lego2 e");
699 //__________________________________________________________________
701 * Run the post-processing.
703 * This will open the files <<i>base</i>><tt>_hists.root</tt>
704 * containing the histograms generated by AliForwardMultiplicity and
705 * the file <<i>base</i>><tt>_aods.root</tt> containing the
706 * tree with AliAODEvent objects.
708 * Then it will loop over the events, accepting only INEL events
709 * that have a primary collision point along z within @a vzMin and
712 * After the processing, the result will be shown in 3 canvases,
713 * possibly rebinning the result by the factor @a rebin.
715 * @param base Base name of files
716 * @param vzMin Minimum collision vertex z position to use
717 * @param vzMax Maximum collision vertex z position to use
718 * @param rebin Rebinning factor
720 * @return true on success, false otherwise
722 Bool_t Run(const char* base,
727 if (!Open(base,vzMin,vzMax,rebin)) return kFALSE;
728 if (!Process()) return kFALSE;
729 if (!Finish()) return kFALSE;
734 Double_t fVzMin; // Minimum vertex
735 Double_t fVzMax; // Maximum vertex
736 Int_t fBinVzMin; // Corresponding bin to min vertex
737 Int_t fBinVzMax; // Corresponding bin to max vertex
738 Int_t fRebin; // Rebin factor
739 TTree* fTree; // Event tree
740 AliAODForwardMult* fAOD; // Our event-by-event data
741 TH1I* fEvents; // histogram of event counts per vertex
742 TList* fCollect; // List of analysis histograms
743 TObjArray fByVtx1D; // List of per-vertex 1D histograms
744 TH1D* fTotal1D; // Direct sum of input histograms
745 TH2D* fTotal2D; // Direct sum of input histograms
746 TH1D* fFromVtx; // Sum of per-vertex histograms
747 TH1D* fNorm; // Histogram of # events with data per bin
749 Int_t fNAccepted; // # of accepted events