3 // Calculate flow in the forward and central regions using the Q cumulants method.
9 // - AnalysisResults.root or forward_flow.root
13 #include <TInterpreter.h>
19 #include <TProfile2D.h>
20 #include <TParameter.h>
25 #include "AliForwardFlowTaskQC.h"
26 #include "AliAnalysisManager.h"
27 #include "AliAODHandler.h"
28 #include "AliAODInputHandler.h"
29 #include "AliAODForwardMult.h"
30 #include "AliAODCentralMult.h"
31 #include "AliAODEvent.h"
32 #include "AliForwardUtil.h"
33 #include "AliVVZERO.h"
34 #include "AliAODVertex.h"
35 #include "AliCentrality.h"
36 #include "AliESDEvent.h"
37 #include "AliVTrack.h"
38 #include "AliESDtrackCuts.h"
39 #include "AliAODTrack.h"
41 ClassImp(AliForwardFlowTaskQC)
46 AliForwardFlowTaskQC::AliForwardFlowTaskQC()
47 : AliAnalysisTaskSE(),
48 fVtxAxis(), // Axis to control vertex binning
49 fCentAxis(), // Axis to control centrality/multiplicity binning
50 fFMDCut(-1), // FMD sigma cut
51 fSPDCut(-1), // SPD sigma cut
52 fFlowFlags(0), // Flow flags
53 fEtaGap(-1), // Eta gap value
54 fBinsForward(), // List with forward flow hists
55 fBinsCentral(), // List with central flow hists
56 fSumList(0), // Event sum list
57 fOutputList(0), // Result output list
58 fAOD(0), // AOD input event
59 fESDTrackCuts(0), // ESD track cuts
60 fMaxMoment(0), // Max flow moment
61 fVtx(1111), // Z vertex coordinate
62 fCent(-1), // Centrality
63 fHistdNdedpV0(), // Hist for v0
64 fHistdNdedp3Cor(), // Hist for combining detectors
65 fHistFMDSPDCorr(), // FMD SPD correlation
66 fHistCent(), // Hist for centrality
67 fHistVertexSel(), // Hist for selected vertices
68 fHistEventSel() // Hist for event selection
71 // Default constructor
74 //_____________________________________________________________________
75 AliForwardFlowTaskQC::AliForwardFlowTaskQC(const char* name)
76 : AliAnalysisTaskSE(name),
77 fVtxAxis(), // Axis to control vertex binning
78 fCentAxis(), // Axis to control centrality/multiplicity binning
79 fFMDCut(-1), // FMD sigma cut
80 fSPDCut(-1), // SPD sigma cut
81 fFlowFlags(0x0), // Flow flags
82 fEtaGap(2.), // Eta gap value
83 fBinsForward(), // List with forward flow hists
84 fBinsCentral(), // List with central flow hists
85 fSumList(0), // Event sum list
86 fOutputList(0), // Result output list
87 fAOD(0), // AOD input event
88 fESDTrackCuts(0), // ESD track cuts
89 fMaxMoment(4), // Max flow moment
90 fVtx(1111), // Z vertex coordinate
91 fCent(-1), // Centrality
92 fHistdNdedpV0(), // Histo for v0
93 fHistdNdedp3Cor(), // Histo for combining detectors
94 fHistFMDSPDCorr(), // FMD SPD correlation
95 fHistCent(), // Hist for centrality
96 fHistVertexSel(), // Hist for selected vertices
97 fHistEventSel() // Hist for event selection
103 // name: Name of task
105 DefineOutput(1, TList::Class());
106 DefineOutput(2, TList::Class());
108 //_____________________________________________________________________
109 AliForwardFlowTaskQC::AliForwardFlowTaskQC(const AliForwardFlowTaskQC& o)
110 : AliAnalysisTaskSE(o),
111 fVtxAxis(o.fVtxAxis), // Axis to control vertex binning
112 fCentAxis(o.fCentAxis), // Array to control centrality/multiplicity binning
113 fFMDCut(o.fFMDCut), // FMD sigma cut
114 fSPDCut(o.fSPDCut), // SPD sigma cut
115 fFlowFlags(o.fFlowFlags), // Flow flags
116 fEtaGap(o.fEtaGap), // Eta gap value
117 fBinsForward(), // List with forward flow hists
118 fBinsCentral(), // List with central flow hists
119 fSumList(o.fSumList), // Event sum list
120 fOutputList(o.fOutputList), // Result output list
121 fAOD(o.fAOD), // AOD input event
122 fESDTrackCuts(o.fESDTrackCuts), // ESD track cuts
123 fMaxMoment(o.fMaxMoment), // Flow moments
124 fVtx(o.fVtx), // Z vertex coordinate
125 fCent(o.fCent), // Centrality
126 fHistdNdedpV0(o.fHistdNdedpV0), // Histo for v0
127 fHistdNdedp3Cor(o.fHistdNdedp3Cor),// Histo for combining detectors
128 fHistFMDSPDCorr(o.fHistFMDSPDCorr),// FMD SPD correlation
129 fHistCent(o.fHistCent), // Hist for centrality
130 fHistVertexSel(o.fHistVertexSel), // Hist for selected vertices
131 fHistEventSel(o.fHistEventSel) // Hist for event selection
137 // o: Object to copy from
140 //_____________________________________________________________________
141 AliForwardFlowTaskQC&
142 AliForwardFlowTaskQC::operator=(const AliForwardFlowTaskQC& o)
145 // Assignment operator
147 if (&o == this) return *this;
148 fVtxAxis = o.fVtxAxis;
149 fCentAxis = o.fCentAxis;
152 fFlowFlags = o.fFlowFlags;
154 fSumList = o.fSumList;
155 fOutputList = o.fOutputList;
157 fESDTrackCuts = o.fESDTrackCuts;
158 fMaxMoment = o.fMaxMoment;
161 fHistdNdedpV0 = o.fHistdNdedpV0;
162 fHistdNdedp3Cor = o.fHistdNdedp3Cor;
163 fHistFMDSPDCorr = o.fHistFMDSPDCorr;
164 fHistCent = o.fHistCent;
165 fHistVertexSel = o.fHistVertexSel;
166 fHistEventSel = o.fHistEventSel;
170 //_____________________________________________________________________
171 void AliForwardFlowTaskQC::SetFlowFlags(UShort_t flags)
174 // Set flow flags, making sure the detector setup is right
179 if ((flags & kFMD) && (flags & kVZERO))
180 AliFatal("Cannot do analysis on more than one forward detector!");
181 else if (!(flags & kFMD) && !(flags & kVZERO))
182 AliFatal("You need to add a forward detector!");
183 else fFlowFlags = flags;
185 //_____________________________________________________________________
186 void AliForwardFlowTaskQC::UserCreateOutputObjects()
189 // Create output objects
193 if (fFlowFlags & kTPC) {
194 fESDTrackCuts = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts();
198 PostData(1, fSumList);
200 //_____________________________________________________________________
201 void AliForwardFlowTaskQC::InitVertexBins()
204 // Init vertexbin objects for forward and central detectors, and add them to the lists
206 for (Int_t v = 1; v <= fVtxAxis->GetNbins(); v++) {
207 Int_t vL = Int_t(fVtxAxis->GetBinLowEdge(v));
208 Int_t vH = Int_t(fVtxAxis->GetBinUpEdge(v));
209 if ((fFlowFlags & kFMD)) {
210 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "FMD", fFlowFlags, fFMDCut, fEtaGap));
211 if (!(fFlowFlags & k3Cor)) fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-FMD", fFlowFlags|kNUAcorr|kSPD, fSPDCut, fEtaGap));
213 else if ((fFlowFlags & kVZERO)) {
214 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "VZERO", fFlowFlags, 0, fEtaGap));
215 if ((fFlowFlags & kEtaGap)) fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-VZERO", fFlowFlags|kNUAcorr|kSPD, fSPDCut, fEtaGap));
219 //_____________________________________________________________________
220 void AliForwardFlowTaskQC::InitHists()
223 // Init histograms and add vertex bin histograms to the sum list
226 fSumList = new TList();
227 fSumList->SetName("Sums");
228 fSumList->SetOwner();
230 if (!fVtxAxis) fVtxAxis = new TAxis(20, -10, 10);
231 fVtxAxis->SetName("VtxAxis");
232 if (!fCentAxis) fCentAxis = new TAxis(20, 0, 100);
233 fVtxAxis->SetName("CentAxis");
235 fHistCent = new TH1D("hCent", "Centralities", 100, 0, 100);
236 fHistVertexSel = new TH1D("hVertexSel", "Selected vertices", fVtxAxis->GetNbins(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
237 fHistEventSel = new TH1I("hEventSel", "Event Selection", kOK, 0.5, kOK+0.5);
238 fHistEventSel->GetXaxis()->SetBinLabel(kNoEvent, "No AOD event");
239 fHistEventSel->GetXaxis()->SetBinLabel(kNoForward, "No forward det");
240 fHistEventSel->GetXaxis()->SetBinLabel(kNoCentral, "No central det");
241 fHistEventSel->GetXaxis()->SetBinLabel(kNoTrigger, "Not triggered");
242 fHistEventSel->GetXaxis()->SetBinLabel(kNoCent, "No centrality");
243 fHistEventSel->GetXaxis()->SetBinLabel(kInvCent, "Centrality outside range");
244 fHistEventSel->GetXaxis()->SetBinLabel(kNoVtx, "No vertex");
245 fHistEventSel->GetXaxis()->SetBinLabel(kInvVtx, "Vtx outside range");
246 fHistEventSel->GetXaxis()->SetBinLabel(kOK, "OK!");
248 fHistFMDSPDCorr = new TH2D("hFMDSPDCorr", "hFMDSPCCorr", 200, 0., 20000., 200, 0, 7500);
250 TList* dList = new TList();
251 dList->SetName("Diagnostics");
252 dList->Add(fHistCent);
253 dList->Add(fHistVertexSel);
254 dList->Add(fHistEventSel);
255 dList->Add(fHistFMDSPDCorr);
256 fSumList->Add(dList);
258 fHistdNdedp3Cor = TH2D(Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)), Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)),
259 200, -4., 6., 20, 0., TMath::TwoPi());
260 if ((fFlowFlags & kVZERO)) {
261 Double_t bins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
262 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
263 fHistdNdedpV0 = TH2D(Form("hdNdedpv0%s", GetQCType(fFlowFlags)), Form("hdNdedpv0%s", GetQCType(fFlowFlags)),
264 11, -6, 6, 8, 0, TMath::TwoPi());
265 fHistdNdedpV0.GetXaxis()->Set(11, bins);
266 if ((fFlowFlags & k3Cor)) {
267 Double_t bins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
268 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
269 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
270 fHistdNdedp3Cor.GetXaxis()->Set(19, bins2);
271 fHistdNdedp3Cor.GetYaxis()->Set(8, 0., TMath::TwoPi());
275 TIter nextForward(&fBinsForward);
277 while ((bin = static_cast<VertexBin*>(nextForward()))) {
278 bin->AddOutput(fSumList, fCentAxis);
280 TIter nextCentral(&fBinsCentral);
281 while ((bin = static_cast<VertexBin*>(nextCentral()))) {
282 bin->AddOutput(fSumList, fCentAxis);
285 //_____________________________________________________________________
286 void AliForwardFlowTaskQC::UserExec(Option_t */*option*/)
289 // Calls the analyze function - called every event
295 // Reset data members
301 PostData(1, fSumList);
305 //_____________________________________________________________________
306 Bool_t AliForwardFlowTaskQC::Analyze()
309 // Load forward and central detector objects from aod tree and call the
310 // cumulants calculation for the correct vertex bin
312 // Return: true on success
316 fAOD = dynamic_cast<AliAODEvent*>(AliForwardUtil::GetAODEvent(this));
318 fHistEventSel->Fill(kNoEvent);
322 // Get detector objects
323 AliAODForwardMult* aodfmult = static_cast<AliAODForwardMult*>(fAOD->FindListObject("Forward"));
324 AliAODCentralMult* aodcmult = static_cast<AliAODCentralMult*>(fAOD->FindListObject("CentralClusters"));
325 AliVVZERO* vzero = GetVZERO();
326 if ((fFlowFlags & kVZERO)) {
328 fHistdNdedpV0.Reset();
329 FillVZEROHist(vzero);
333 // We make sure that the necessary forward object is there
334 if ((fFlowFlags & kFMD) && !aodfmult) {
335 fHistEventSel->Fill(kNoForward);
338 else if ((fFlowFlags & kVZERO) && !vzero) {
339 fHistEventSel->Fill(kNoForward);
342 if (!aodcmult) fHistEventSel->Fill(kNoCentral);
344 // Check event for triggers, get centrality, vtx etc.
345 if (!CheckEvent(aodfmult)) return kFALSE;
346 Int_t vtx = fVtxAxis->FindBin(fVtx)-1;
348 // Then we assign a reference to the forward histogram of interest
349 TH2D& forwarddNdedp = ((fFlowFlags & kFMD) ? aodfmult->GetHistogram() : fHistdNdedpV0);
350 TH2D& spddNdedp = aodcmult->GetHistogram();
351 if ((fFlowFlags & kStdQC)) {
352 FillVtxBinList(fBinsForward, forwarddNdedp, vtx);
353 } else if ((fFlowFlags & kEtaGap)) {
354 FillVtxBinListEtaGap(fBinsForward, forwarddNdedp, forwarddNdedp, vtx);
356 // At the moment only clusters are supported for the central region (some day add tracks?)
357 // So no extra checks necessary
359 if ((fFlowFlags & kStdQC)) {
360 FillVtxBinList(fBinsCentral, spddNdedp, vtx);
361 } else if ((fFlowFlags & kEtaGap)) {
362 FillVtxBinListEtaGap(fBinsCentral, forwarddNdedp, spddNdedp, vtx);
363 } else if ((fFlowFlags & k3Cor)) {
364 FillVtxBinList3Cor(fBinsForward, spddNdedp, forwarddNdedp, vtx);
368 Double_t totForward = forwarddNdedp.Integral(1, forwarddNdedp.GetNbinsX(), 1, forwarddNdedp.GetNbinsY());
369 Double_t totSPD = spddNdedp.Integral(1, spddNdedp.GetNbinsX(), 1, spddNdedp.GetNbinsY());
370 fHistFMDSPDCorr->Fill(totForward, totSPD);
376 //_____________________________________________________________________
377 void AliForwardFlowTaskQC::FillVtxBinList(const TList& list, TH2D& h, Int_t vtx, UShort_t flags) const
380 // Loops over list of VtxBins, fills hists of bins for current vertex
381 // and runs analysis on those bins
384 // list: list of VtxBins
385 // h: dN/detadphi histogram
386 // vtx: current vertex bin
387 // flags: extra flags to handle calculations.
389 // Note: The while loop is used in this function and the next 2 for historical reasons,
390 // as originally each moment had it's own VertexBin object.
393 Int_t nVtxBins = fVtxAxis->GetNbins();
395 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
396 // If no tracks do things normally
397 if (!(fFlowFlags & kTPC) && !bin->FillHists(h, fCent, kFillBoth|flags|kReset)) return;
398 // if tracks things are more complicated
399 else if ((fFlowFlags & kTPC)) {
400 TObjArray* trList = GetTracks();
402 Bool_t useEvent = bin->FillTracks(trList, kFillRef|kReset|flags);
403 // If esd input trList is a new object owned by this task and should be cleaned up
404 if (AliForwardUtil::CheckForAOD() == 2) delete trList;
405 if (!useEvent) return;
406 if (!bin->FillHists(h, fCent, kFillDiff|kReset|flags)) return;
408 bin->CumulantsAccumulate(fCent);
414 //_____________________________________________________________________
415 void AliForwardFlowTaskQC::FillVtxBinListEtaGap(const TList& list, TH2D& href,
416 TH2D& hdiff, Int_t vtx, UShort_t flags) const
419 // Loops over list of VtxBins, fills hists of bins for current vertex
420 // and runs analysis on those bins
423 // list: list of VtxBins
424 // href: dN/detadphi histogram for ref. flow
425 // hdiff: dN/detadphi histogram for diff. flow
426 // vBin: current vertex bin
427 // flags: extra flags to handle calculations.
431 Int_t nVtxBins = fVtxAxis->GetNbins();
433 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
434 if (!bin->FillHists(href, fCent, kFillRef|flags|kReset)) return;
435 bin->FillHists(hdiff, fCent, kFillDiff|kReset);
436 bin->CumulantsAccumulate(fCent);
442 //_____________________________________________________________________
443 void AliForwardFlowTaskQC::FillVtxBinList3Cor(const TList& list, TH2D& hcent,
444 TH2D& hfwd, Int_t vtx, UShort_t flags)
447 // Loops over list of VtxBins, fills hists of bins for current vertex
448 // and runs analysis on those bins
451 // list: list of VtxBins
452 // hcent: dN/detadphi histogram for central coverage
453 // hfwd: dN/detadphi histogram for forward coverage
454 // vBin: current vertex bin
455 // flags: extra flags to handle calculations.
459 Int_t nVtxBins = fVtxAxis->GetNbins();
461 TH2D& h = CombineHists(hcent, hfwd);
463 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
464 if (!bin->FillHists(h, fCent, kFillBoth|flags|kReset)) return;
465 bin->CumulantsAccumulate3Cor(fCent);
471 //_____________________________________________________________________
472 TH2D& AliForwardFlowTaskQC::CombineHists(TH2D& hcent, TH2D& hfwd)
475 // Combines a forward and central d^2N/detadphi histogram.
476 // At some point it might need a flag to choose which histogram gets
477 // priority when there is an overlap, at the moment the average is chosen
480 // hcent: Central barrel detector
481 // hfwd: Forward detector
483 // Return: reference to combined hist
486 // If hists are the same (MC input) don't do anything
487 if (&hcent == &hfwd) return hcent;
489 fHistdNdedp3Cor.Reset();
491 if ((fFlowFlags & kFMD)) {
492 for (Int_t e = 1; e <= fHistdNdedp3Cor.GetNbinsX(); e++) {
493 Double_t eta = fHistdNdedp3Cor.GetXaxis()->GetBinCenter(e);
494 Bool_t fwdCov = (hfwd.GetBinContent(e, 0) != 0);
495 Bool_t centCov = (hcent.GetBinContent(e, 0) != 0);
496 if (!fwdCov && !centCov) continue;
497 else fHistdNdedp3Cor.SetBinContent(e, 0, 1);
498 for (Int_t p = 1; p <= fHistdNdedp3Cor.GetNbinsY(); p++) {
499 Double_t phi = fHistdNdedp3Cor.GetYaxis()->GetBinCenter(p);
503 cont += hfwd.GetBinContent(e, p);
507 cont += hcent.GetBinContent(e, p);
510 if (cont == 0 || n == 0) continue;
512 fHistdNdedp3Cor.Fill(eta, phi, cont);
515 // VZERO, SPD input, here we do not average but cut to avoid
516 // (too much) overlap.
517 } else if ((fFlowFlags & kVZERO)) {
519 for (Int_t eV = 1; eV <= hfwd.GetNbinsX(); eV++) {
520 Double_t eta = hfwd.GetXaxis()->GetBinLowEdge(eV)+0.1;
521 if (hfwd.GetBinContent(eV, 0) == 0) continue;
523 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
524 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
526 for (Int_t p = 1; p <= hfwd.GetNbinsY(); p++) {
527 Double_t phi = hfwd.GetYaxis()->GetBinCenter(p);
528 Double_t cont = hfwd.GetBinContent(eV, p);
529 fHistdNdedp3Cor.Fill(eta, phi, cont);
533 Int_t eSs = hcent.GetXaxis()->FindBin(-1.99);
534 Int_t eSe = hcent.GetXaxis()->FindBin(1.99);
535 for (Int_t eS = eSs; eS <= eSe; eS++) {
536 Double_t eta = hcent.GetXaxis()->GetBinCenter(eS);
537 if (hcent.GetBinContent(eS, 0) == 0) continue;
539 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
540 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
542 for (Int_t p = 1; p <= hcent.GetNbinsY(); p++) {
543 Double_t phi = hcent.GetYaxis()->GetBinCenter(p);
544 Double_t cont = hcent.GetBinContent(eS, p);
545 fHistdNdedp3Cor.Fill(eta, phi, cont);
549 return fHistdNdedp3Cor;
551 //_____________________________________________________________________
552 TObjArray* AliForwardFlowTaskQC::GetTracks() const
555 // Get TPC tracks to use for reference flow.
557 // Return: TObjArray with tracks
559 TObjArray* trList = 0;
561 UShort_t input = AliForwardUtil::CheckForAOD();
563 // If AOD input, simply get the track array from the event
564 case 1: trList = static_cast<TObjArray*>(fAOD->GetTracks());
567 // If ESD input get event, apply track cuts
568 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
570 // Warning! trList is now a new array, we need to delete it after use
571 // this is not a very good implementation!
572 trList = fESDTrackCuts->GetAcceptedTracks(esd, kTRUE);
575 default: AliFatal("Neither ESD or AOD input. This should never happen");
580 //_____________________________________________________________________
581 void AliForwardFlowTaskQC::Terminate(Option_t */*option*/)
584 // Calls the finalize function, done at the end of the analysis
590 // Make sure pointers are set to the correct lists
591 fSumList = dynamic_cast<TList*> (GetOutputData(1));
593 AliError("Could not retrieve TList fSumList");
597 fOutputList = new TList();
598 fOutputList->SetName("Results");
599 fOutputList->SetOwner();
601 if ((fFlowFlags & kEtaGap)) {
602 TParameter<Double_t>* etaGap = new TParameter<Double_t>("EtaGap", fEtaGap);
603 fOutputList->Add(etaGap);
605 // We only add axes in terminate, as TAxis object do not merge well,
606 // and so we get a mess when running on the grid if we put them in the sum list...
607 fVtxAxis->SetName("VtxAxis");
608 fOutputList->Add(fVtxAxis);
609 fCentAxis->SetName("CentAxis");
610 fOutputList->Add(fCentAxis);
612 // Run finalize on VertexBins
615 // Loop over output to get dN/deta hists - used for diagnostics
616 TIter next(fOutputList);
621 while ((o = next())) {
623 if (name.Contains("dNdeta")) {
624 dNdeta = dynamic_cast<TH2D*>(o);
625 name.ReplaceAll("dNdeta", "cent");
626 name.ReplaceAll("Ref", "");
627 name.ReplaceAll("Diff", "");
628 cent = dynamic_cast<TH1D*>(fOutputList->FindObject(name.Data()));
629 if (!dNdeta || !cent) continue;
630 for (Int_t cBin = 1; cBin <= dNdeta->GetNbinsY(); cBin++) {
631 Double_t nEvents = cent->GetBinContent(cBin);
632 if (nEvents == 0) continue;
633 for (Int_t eBin = 1; eBin <= dNdeta->GetNbinsX(); eBin++) {
634 dNdeta->SetBinContent(eBin, cBin, dNdeta->GetBinContent(eBin, cBin)/nEvents);
635 dNdeta->SetBinError(eBin, cBin, dNdeta->GetBinError(eBin, cBin)/nEvents);
641 // Loop over output and make 1D projections for fast look at results
642 MakeCentralityHists(fOutputList);
643 TList* vtxList = (TList*)fOutputList->FindObject("vtxList");
644 if (vtxList) MakeCentralityHists(vtxList);
645 TList* nuaList = (TList*)fOutputList->FindObject("NUATerms");
646 TIter nextNua(nuaList);
649 while ((o = nextNua())) {
650 if (!(h = dynamic_cast<TH2D*>(o))) continue;
651 Double_t evts = h->GetBinContent(0, 0);
652 if (evts != 0) h->Scale(1./evts);
654 if (nuaList) MakeCentralityHists(nuaList);
656 PostData(2, fOutputList);
660 //_____________________________________________________________________
661 void AliForwardFlowTaskQC::Finalize()
664 // Finalize command, called by Terminate()
667 // Reinitiate vertex bins if Terminate is called separately!
668 if (fBinsForward.GetEntries() == 0) InitVertexBins();
670 // Iterate over all vertex bins objects and finalize cumulants
672 EndVtxBinList(fBinsForward);
673 EndVtxBinList(fBinsCentral);
677 //_____________________________________________________________________
678 void AliForwardFlowTaskQC::EndVtxBinList(const TList& list) const
681 // Loop over VertexBin list and call terminate on each
684 // list: VertexBin list
688 while ((bin = static_cast<VertexBin*>(next()))) {
689 bin->CumulantsTerminate(fSumList, fOutputList);
693 // _____________________________________________________________________
694 void AliForwardFlowTaskQC::MakeCentralityHists(TList* list) const
697 // Loop over a list containing a TH2D with flow results
698 // and project to TH1's in specific centrality bins
701 // list: Flow results list
707 TIter nextHist(list);
708 while ((helper = dynamic_cast<TObject*>(nextHist()))) {
709 if (!(hist2D = dynamic_cast<TH2D*>(helper))) continue;
710 for (Int_t cBin = 1; cBin <= hist2D->GetNbinsY(); cBin++) {
711 Int_t cMin = Int_t(hist2D->GetYaxis()->GetBinLowEdge(cBin));
712 Int_t cMax = Int_t(hist2D->GetYaxis()->GetBinUpEdge(cBin));
713 TString name = Form("cent_%d-%d", cMin, cMax);
714 centList = (TList*)list->FindObject(name.Data());
716 centList = new TList();
717 centList->SetName(name.Data());
720 hist1D = hist2D->ProjectionX(Form("%s_%s", hist2D->GetName(), name.Data()),
722 hist1D->SetTitle(hist1D->GetName());
723 centList->Add(hist1D);
727 // _____________________________________________________________________
728 Bool_t AliForwardFlowTaskQC::CheckEvent(const AliAODForwardMult* aodfm)
731 // Function to check that an AOD event meets the cuts
734 // AliAODForwardMult: forward mult object with trigger and vertex info
736 // Return: false if there is no trigger or if the centrality or vertex
737 // is out of range. Otherwise true.
740 // First check for trigger
741 if (!CheckTrigger(aodfm)) {
742 fHistEventSel->Fill(kNoTrigger);
746 // Then check for centrality
747 if (!GetCentrality(aodfm)) {
751 // And finally check for vertex
752 if (!GetVertex(aodfm)) {
756 // Ev. accepted - filling diag. hists
757 fHistCent->Fill(fCent);
758 fHistVertexSel->Fill(fVtx);
759 fHistEventSel->Fill(kOK);
763 // _____________________________________________________________________
764 Bool_t AliForwardFlowTaskQC::CheckTrigger(const AliAODForwardMult* aodfm) const
767 // Function to look for a trigger string in the event.
768 // First check for info in forward mult object, if not there, use the AOD header
771 // AliAODForwardMult: forward mult object with trigger and vertex info
773 // Return: true if offline trigger is present
775 if (aodfm) return aodfm->IsTriggerBits(AliAODForwardMult::kOffline);
776 // this may need to be changed for 2011 data to handle kCentral and so on...
777 else return (((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))
778 ->IsEventSelected() & AliVEvent::kMB);
780 // _____________________________________________________________________
781 Bool_t AliForwardFlowTaskQC::GetCentrality(const AliAODForwardMult* aodfm)
784 // Function to look get centrality of the event.
785 // First check for info in forward mult object, if not there, use the AOD header
788 // AliAODForwardMult: forward mult object with trigger and vertex info
790 // Return: true if centrality determination is present
793 if (aodfm->HasCentrality()) {
794 fCent = (Double_t)aodfm->GetCentrality();
795 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
796 fHistEventSel->Fill(kInvCent);
802 fHistEventSel->Fill(kNoCent);
806 AliCentrality* aodCent = fAOD->GetCentrality();
808 fCent = (Double_t)aodCent->GetCentralityPercentile("V0M");
809 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
810 fHistEventSel->Fill(kInvCent);
816 fHistEventSel->Fill(kNoCent);
821 //_____________________________________________________________________
822 Bool_t AliForwardFlowTaskQC::GetVertex(const AliAODForwardMult* aodfm)
825 // Function to look for vertex determination in the event.
826 // First check for info in forward mult object, if not there, use the AOD header
829 // AliAODForwardMult: forward mult object with trigger and vertex info
831 // Return: true if vertex is determined
834 if (aodfm->HasIpZ()) {
835 fVtx = aodfm->GetIpZ();
836 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
837 fHistEventSel->Fill(kInvVtx);
842 fHistEventSel->Fill(kNoVtx);
847 AliAODVertex* aodVtx = fAOD->GetPrimaryVertex();
849 fVtx = aodVtx->GetZ();
850 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
851 fHistEventSel->Fill(kInvVtx);
856 fHistEventSel->Fill(kNoVtx);
862 // _____________________________________________________________________
863 AliVVZERO* AliForwardFlowTaskQC::GetVZERO() const
865 AliVVZERO* vzero = 0;
867 UShort_t input = AliForwardUtil::CheckForAOD();
869 // If AOD input, simply get the track array from the event
870 case 1: vzero = (AliVVZERO*)fAOD->GetVZEROData();
873 // If ESD input get event, apply track cuts
874 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
876 vzero = (AliVVZERO*)esd->GetVZEROData();
879 default: AliFatal("Neither ESD or AOD input. This should never happen");
884 // _____________________________________________________________________
885 void AliForwardFlowTaskQC::FillVZEROHist(AliVVZERO* vzero)
888 // Loops over VZERO data object and fill up d^2N/detadphi histogram for flow analysis
891 // vzero: VZERO AOD data object
896 // Sort of right for 2010 data, do not use for 2011!
897 Double_t eq[64] = { 1.43536, 1.45727, 1.44993, 1.30051, 1.17425, 1.2335, 1.22247, 1.14362,
898 1.14647, 1.25208, 1.17681, 1.21642, 1.16604, 1.05532, 1.03212, 1.1032,
899 1.22941, 1.36986, 1.14652, 1.20056, 0.927086, 1.10809, 1.03343, 1.29472,
900 1.21204, 1.29217, 1.2003, 2.10382, 1.28513, 1.40558, 1.25784, 1.21848,
901 0.475162, 0.50421, 0.503617, 0.512471, 0.515276, 0.39831, 0.415199, 0.444664,
902 0.521922, 0.785915, 0.703658, 0.832479, 0.77461, 0.73129, 0.778697, 0.710265,
903 0.89686, 0.967688, 0.974225, 0.873445, 0.811096, 0.828493, 0.889609, 0.586056,
904 1.15877, 0.954656, 0.914557, 0.979028, 1.04907, 0.748518, 0.928043, 0.98175 };
905 for (Int_t i = 0; i < 64; i++) {
908 bin = (ring < 5 ? ring+1 : 15-ring);
909 eta = fHistdNdedpV0.GetXaxis()->GetBinCenter(bin);
910 fHistdNdedpV0.SetBinContent(bin, 0, 1);
912 Float_t amp = vzero->GetMultiplicity(i);
914 Double_t phi = TMath::Pi()/8.+TMath::TwoPi()*i/8.;
915 while (phi > TMath::TwoPi()) phi -= TMath::TwoPi();
916 fHistdNdedpV0.Fill(eta, phi, amp);
919 //_____________________________________________________________________
920 AliForwardFlowTaskQC::VertexBin::VertexBin()
922 fMaxMoment(0), // Max flow moment for this vertexbin
923 fVzMin(0), // Vertex z-coordinate min [cm]
924 fVzMax(0), // Vertex z-coordinate max [cm]
925 fType(), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
926 fFlags(0), // Flow flags
927 fSigmaCut(-1), // Sigma cut to remove outlier events
928 fEtaGap(-1), // Eta gap value
929 fEtaLims(), // Limits for binning in 3Cor method
930 fCumuRef(), // Histogram for reference flow
931 fCumuDiff(), // Histogram for differential flow
932 fCumuHists(0,0), // CumuHists object for keeping track of results
933 fCumuNUARef(), // Histogram for ref NUA terms
934 fCumuNUADiff(), // Histogram for diff NUA terms
935 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
936 fdNdedpDiffAcc(),// Diagnostics histogram for acc. maps
937 fOutliers(), // Histogram for sigma distribution
938 fDebug() // Debug level
941 // Default constructor
944 //_____________________________________________________________________
945 AliForwardFlowTaskQC::VertexBin::VertexBin(Int_t vLow, Int_t vHigh,
946 UShort_t moment, TString name,
947 UShort_t flags, Double_t cut,
950 fMaxMoment(moment), // Max flow moment for this vertexbin
951 fVzMin(vLow), // Vertex z-coordinate min [cm]
952 fVzMax(vHigh), // Vertex z-coordinate max [cm]
953 fType(name), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
954 fFlags(flags), // Flow flags
955 fSigmaCut(cut), // Sigma cut to remove outlier events
956 fEtaGap(etaGap), // Eta gap value
957 fEtaLims(), // Limits for binning in 3Cor method
958 fCumuRef(), // Histogram for reference flow
959 fCumuDiff(), // Histogram for differential flow
960 fCumuHists(moment,0),// CumuHists object for keeping track of results
961 fCumuNUARef(), // Histogram for ref NUA terms
962 fCumuNUADiff(), // Histogram for diff NUA terms
963 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
964 fdNdedpDiffAcc(), // Diagnostics histogram for acc. maps
965 fOutliers(), // Histogram for sigma distribution
966 fDebug(0) // Debug level
972 // vLow: min z-coordinate
973 // vHigh: max z-coordinate
974 // moment: max flow moment
975 // name: data type name (FMD/SPD/FMDTR/SPDTR/MC)
978 // etaGap: eta-gap value
982 SetName(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
983 SetTitle(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
985 fDebug = AliAnalysisManager::GetAnalysisManager()->GetDebugLevel();
986 if (fDebug > 0) Printf("AliForwardFlowTaskQC::VertexBin()\tDebugMode: %d", fDebug);
988 // Set limits for 3 correlator method
989 if ((fFlags & kFMD)) {
996 } else if ((fFlags & kVZERO)) {
1005 //_____________________________________________________________________
1006 AliForwardFlowTaskQC::VertexBin&
1007 AliForwardFlowTaskQC::VertexBin::operator=(const AliForwardFlowTaskQC::VertexBin& o)
1010 // Assignment operator
1013 // o: AliForwardFlowTaskQC::VertexBin
1015 if (&o == this) return *this;
1016 fMaxMoment = o.fMaxMoment;
1021 fSigmaCut = o.fSigmaCut;
1022 fEtaGap = o.fEtaGap;
1023 fCumuRef = o.fCumuRef;
1024 fCumuDiff = o.fCumuDiff;
1025 fCumuHists = o.fCumuHists;
1026 fCumuNUARef = o.fCumuNUARef;
1027 fCumuNUADiff = o.fCumuNUADiff;
1028 fdNdedpRefAcc = o.fdNdedpRefAcc;
1029 fdNdedpDiffAcc = o.fdNdedpDiffAcc;
1030 fOutliers = o.fOutliers;
1032 for (UInt_t i = 0; i < sizeof(fEtaLims)/sizeof(Double_t); i++) fEtaLims[i] = o.fEtaLims[i];
1036 //_____________________________________________________________________
1037 void AliForwardFlowTaskQC::VertexBin::AddOutput(TList* outputlist, TAxis* centAxis)
1040 // Add histograms to outputlist
1043 // outputlist: list of histograms
1044 // centAxis: centrality axis
1047 // First we try to find an outputlist for this vertexbin
1048 TList* list = (TList*)outputlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1049 // If it doesn't exist we make one
1052 list->SetName(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1053 outputlist->Add(list);
1056 // Get bin numbers and binning defined
1057 Int_t nHBins = GetBinNumberSin();
1058 Int_t nEtaBins = 48;
1059 if ((fFlags & k3Cor)) {
1060 if ((fFlags & kFMD)) nEtaBins = 24;
1061 else if ((fFlags & kVZERO)) nEtaBins = 19;
1063 else if ((fFlags & kVZERO) && (fFlags & kEtaGap)) nEtaBins = 19;
1064 else if ((fFlags & kVZERO)) nEtaBins = 11;
1066 Double_t vzeroBins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
1067 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
1068 Double_t vzeroBins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
1069 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
1070 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
1072 Int_t nRefBins = nEtaBins; // needs to be something as default
1073 if ((fFlags & kStdQC)) {
1074 if ((fFlags & kSymEta) && !((fFlags & kTPC) && (fFlags & kSPD))) nRefBins = 1;
1076 } else if ((fFlags & kEtaGap )) {
1078 } else if ((fFlags & k3Cor)) {
1082 // We initiate the reference histogram
1083 fCumuRef = new TH2D(Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1084 Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1086 nHBins, 0.5, nHBins+0.5);
1087 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuRef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1088 SetupNUALabels(fCumuRef->GetYaxis());
1089 list->Add(fCumuRef);
1090 // We initiate the differential histogram
1091 fCumuDiff = new TH2D(Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1092 Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1093 nEtaBins, -6., 6., nHBins, 0.5, nHBins+0.5);
1094 if ((fFlags & kVZERO)) {
1095 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1096 fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1097 else fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins);
1099 SetupNUALabels(fCumuDiff->GetYaxis());
1100 list->Add(fCumuDiff);
1102 // Cumulants sum hists
1103 Int_t cBins = centAxis->GetNbins();
1104 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1106 Int_t nC2Bins = ((fFlags & kEtaGap) || (fFlags & k3Cor) ? kW2 : k3pWeight);
1107 Int_t nC4Bins = ((fFlags & kEtaGap) ? kW2 : ((fFlags & k3Cor) ? kW4 : kSinphi1phi2phi3p));
1108 for (Int_t n = 2; n <= fMaxMoment; n++) {
1109 // Initiate the ref cumulant sum histogram
1110 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1111 Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1113 cBins, 0., 100., nC2Bins, 0.5, nC2Bins+0.5);
1114 if ((fFlags & kVZERO) && (fFlags & k3Cor)) cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1115 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1116 fCumuHists.Add(cumuHist);
1117 // Initiate the diff cumulant sum histogram
1118 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1119 Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1120 nEtaBins, -6., 6., cBins, 0., 100., nC4Bins, 0.5, nC4Bins+0.5);
1121 if ((fFlags & kVZERO)) {
1122 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1123 cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1124 else cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins);
1126 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1127 fCumuHists.Add(cumuHist);
1130 // Common NUA histograms
1131 fCumuNUARef = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1132 Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1134 cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1135 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuNUARef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1136 fCumuNUARef->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1137 SetupNUALabels(fCumuNUARef->GetZaxis());
1138 fCumuNUARef->Sumw2();
1139 list->Add(fCumuNUARef);
1141 fCumuNUADiff = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1142 Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1143 nEtaBins, -6., 6., cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1144 if ((fFlags & kVZERO)) {
1145 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1146 fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1147 else fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins);
1149 fCumuNUADiff->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1150 SetupNUALabels(fCumuNUADiff->GetZaxis());
1151 fCumuNUADiff->Sumw2();
1152 list->Add(fCumuNUADiff);
1154 // We create diagnostic histograms.
1155 TList* dList = (TList*)outputlist->FindObject("Diagnostics");
1156 if (!dList) AliFatal("No diagnostics list found");
1159 Int_t nPhiBins = ((fFlags & kFMD) ? 20 : 8);
1160 fdNdedpRefAcc = new TH2F(Form("h%sdNdedpRefAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1161 Form("%s reference flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
1162 nEtaBins, -6., 6., nPhiBins, 0, TMath::TwoPi());
1163 if ((fFlags & kVZERO)) {
1164 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1165 fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1166 else fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
1168 dList->Add(fdNdedpRefAcc);
1170 fdNdedpDiffAcc = new TH2F(Form("h%sdNdedpDiffAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1171 Form("%s differential flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
1172 nEtaBins, -6., 6., nPhiBins, 0, TMath::TwoPi());
1173 if ((fFlags & kVZERO)) {
1174 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1175 fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1176 else fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
1178 dList->Add(fdNdedpDiffAcc);
1180 fOutliers = new TH2F(Form("hOutliers_%s_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1181 Form("Maximum #sigma from mean N_{ch} pr. bin - %s, %d < v_{z} < %d",
1182 fType.Data(), fVzMin, fVzMax),
1183 20, 0., 100., 500, 0., ((fFlags & kMC) ? 15. : 5.));
1184 dList->Add(fOutliers);
1188 //_____________________________________________________________________
1189 Bool_t AliForwardFlowTaskQC::VertexBin::FillHists(TH2D& dNdetadphi, Double_t cent, UShort_t mode)
1192 // Fill reference and differential eta-histograms
1195 // dNdetadphi: 2D histogram with input data
1197 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
1199 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1200 Bool_t useEvent = kTRUE;
1202 // Fist we reset histograms
1203 if ((mode & kReset)) {
1204 if ((mode & kFillRef)) fCumuRef->Reset();
1205 if ((mode & kFillDiff)) fCumuDiff->Reset();
1208 // Then we loop over the input and calculate sum cos(k*n*phi)
1209 // and fill it in the reference and differential histograms
1211 Double_t limit = 9999.;
1212 for (Int_t etaBin = 1; etaBin <= dNdetadphi.GetNbinsX(); etaBin++) {
1213 Double_t eta = dNdetadphi.GetXaxis()->GetBinCenter(etaBin);
1214 // Numbers to cut away bad events
1215 Double_t runAvg = 0;
1218 Double_t avgSqr = 0;
1219 for (Int_t phiBin = 0; phiBin <= dNdetadphi.GetNbinsY(); phiBin++) {
1220 // Check for acceptance
1222 if (dNdetadphi.GetBinContent(etaBin, 0) == 0) break;
1223 // Central limit for eta gap break for reference flow
1224 if ((fFlags & kEtaGap) && (mode & kFillRef) &&
1225 TMath::Abs(eta) < fEtaGap) break;
1226 // Backward and forward eta gap break for reference flow
1227 if ((fFlags & kEtaGap) && (mode & kFillRef) && TMath::Abs(eta) > TMath::Abs(limit)) break;
1228 if ((fFlags & kStdQC) && (fFlags & kMC)) {
1229 if (!(fFlags & kSPD) && TMath::Abs(eta) < 1.75) break;
1230 if ((fFlags & kSPD) && TMath::Abs(eta) > 2.00) break;
1232 if (limit > 1e3) limit = dNdetadphi.GetXaxis()->GetBinLowEdge(etaBin);
1234 } // End of phiBin == 0
1235 Double_t phi = dNdetadphi.GetYaxis()->GetBinCenter(phiBin);
1236 Double_t weight = dNdetadphi.GetBinContent(etaBin, phiBin);
1238 // We calculate the average Nch per. bin
1239 avgSqr += weight*weight;
1242 if (weight == 0) continue;
1243 if (weight > max) max = weight;
1245 // Fill into Cos() and Sin() hists
1246 if ((mode & kFillRef)) {
1247 fCumuRef->Fill(eta, 0., weight);// mult goes in underflowbin - no visual, but not needed?
1248 fdNdedpRefAcc->Fill(eta, phi, weight);
1250 if ((mode & kFillDiff)) {
1251 fCumuDiff->Fill(eta, 0., weight);
1252 fdNdedpDiffAcc->Fill(eta, phi, weight);
1254 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1255 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1256 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1257 Double_t cosnPhi = weight*TMath::Cos(n*phi);
1258 Double_t sinnPhi = weight*TMath::Sin(n*phi);
1260 if ((mode & kFillRef)) {
1261 fCumuRef->Fill(eta, cosBin, cosnPhi);
1262 fCumuRef->Fill(eta, sinBin, sinnPhi);
1265 if ((mode & kFillDiff)) {
1266 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1267 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1269 } // End of NUA loop
1270 } // End of phi loop
1271 // Outlier cut calculations
1275 Double_t stdev = (nInAvg > 1 ? TMath::Sqrt(nInAvg/(nInAvg-1))*TMath::Sqrt(avgSqr - runAvg*runAvg) : 0);
1276 Double_t nSigma = (stdev == 0 ? 0 : (max-runAvg)/stdev);
1277 if (fSigmaCut > 0. && nSigma >= fSigmaCut && cent < 60) nBadBins++;
1279 fOutliers->Fill(cent, nSigma);
1280 // We still finish the loop, for fOutliers to make sense,
1281 // but we do no keep the event for analysis
1282 if (nBadBins > 3) useEvent = kFALSE;
1288 //_____________________________________________________________________
1289 Bool_t AliForwardFlowTaskQC::VertexBin::FillTracks(TObjArray* trList, UShort_t mode)
1292 // Fill reference and differential eta-histograms
1295 // trList: list of tracks
1296 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
1298 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1300 // Fist we reset histograms
1301 if ((mode & kReset)) {
1302 if ((mode & kFillRef)) fCumuRef->Reset();
1303 if ((mode & kFillDiff)) fCumuDiff->Reset();
1306 UShort_t input = AliForwardUtil::CheckForAOD();
1307 // Then we loop over the input and calculate sum cos(k*n*phi)
1308 // and fill it in the reference and differential histograms
1309 Int_t nTr = trList->GetEntries();
1310 if (nTr == 0) return kFALSE;
1312 AliAODTrack* aodTr = 0;
1313 // Cuts for AOD tracks (have already been applied to ESD tracks)
1314 const Double_t pTMin = 0.5, pTMax = 20., etaMin = -0.8, etaMax = 0.8, minNCl = 50;
1315 for (Int_t i = 0; i < nTr; i++) { // track loop
1316 tr = (AliVTrack*)trList->At(i);
1318 if (input == 1) { // If AOD input
1319 // A dynamic cast would be more safe here, but this is faster...
1320 aodTr = (AliAODTrack*)tr;
1321 if (aodTr->GetID() > -1) continue;
1322 if (!aodTr->TestFilterBit(128) || !aodTr->Pt() > pTMax || aodTr->Pt() < pTMin ||
1323 aodTr->Eta() > etaMax || aodTr->Eta() < etaMin || aodTr->GetTPCNcls() < minNCl) continue;
1326 Double_t eta = tr->Eta();
1327 // if ((fFlags & kSPD) && TMath::Abs(eta) < 0.4) continue;
1328 Double_t phi = tr->Phi();
1329 if ((mode & kFillRef)) {
1330 fCumuRef->Fill(eta, 0.);// mult goes in underflowbin - no visual, but not needed?
1331 fdNdedpRefAcc->Fill(eta, phi);
1333 if ((mode & kFillDiff)) {
1334 fCumuDiff->Fill(eta, 0);
1335 fdNdedpDiffAcc->Fill(eta, phi);
1337 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1338 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1339 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1340 Double_t cosnPhi = TMath::Cos(n*phi);
1341 Double_t sinnPhi = TMath::Sin(n*phi);
1343 if ((mode & kFillRef)) {
1344 fCumuRef->Fill(eta, cosBin, cosnPhi);
1345 fCumuRef->Fill(eta, sinBin, sinnPhi);
1348 if ((mode & kFillDiff)) {
1349 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1350 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1352 } // End of NUA loop
1353 } // End of track loop
1356 //_____________________________________________________________________
1357 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate(Double_t cent)
1360 // Calculate the Q cumulant up to order fMaxMoment
1363 // cent: centrality of event
1365 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1367 // Fill out NUA hists
1368 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1369 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1370 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1371 if ((fFlags & kTPC) && (fFlags && kSPD)) eta = -eta;
1372 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1373 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1376 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1377 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1378 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1379 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1380 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1384 // We create the objects needed for the analysis
1387 // For each n we loop over the hists
1388 for (Int_t n = 2; n <= fMaxMoment; n++) {
1389 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1390 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1391 Int_t prevRefEtaBin = 0;
1393 // Per mom. quantities
1394 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1395 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1396 Double_t dQ2nReA = 0, dQ2nImA = 0;
1397 Double_t two = 0, w2 = 0, four = 0, w4 = 0;
1398 Double_t cosPhi1Phi2 = 0, cosPhi1Phi2Phi3m = 0;
1399 Double_t sinPhi1Phi2 = 0, sinPhi1Phi2Phi3m = 0;
1400 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1401 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1402 Double_t refEta = eta;
1403 if ((fFlags & kTPC) && (fFlags && kSPD)) refEta = -eta;
1404 Int_t refEtaBinA = fCumuRef->GetXaxis()->FindBin(refEta);
1405 if ((fFlags & kEtaGap)) refEta = -eta;
1406 Int_t refEtaBinB = fCumuRef->GetXaxis()->FindBin(refEta);
1407 if (refEtaBinA != prevRefEtaBin) {
1408 prevRefEtaBin = refEtaBinA;
1410 multA = fCumuRef->GetBinContent(refEtaBinA, 0);
1411 dQnReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n));
1412 dQnImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n));
1413 dQ2nReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n*2));
1414 dQ2nImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n*2));
1416 multB = fCumuRef->GetBinContent(refEtaBinB, 0);
1417 dQnReB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberCos(n));
1418 dQnImB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberSin(n));
1420 if (multA <= 3 || multB <= 3) return;
1421 // The reference flow is calculated
1423 if ((fFlags & kStdQC)) {
1424 w2 = multA * (multA - 1.);
1425 two = dQnReA*dQnReA + dQnImA*dQnImA - multA;
1428 two = dQnReA*dQnReB + dQnImA*dQnImB;
1430 cumuRef->Fill(eta, cent, kW2Two, two);
1431 cumuRef->Fill(eta, cent, kW2, w2);
1433 // The reference flow is calculated
1435 if ((fFlags & kStdQC)) {
1436 w4 = multA * (multA - 1.) * (multA - 2.) * (multA - 3.);
1438 four = 2.*multA*(multA-3.) + TMath::Power((TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.)),2.)
1439 -4.*(multA-2.)*(TMath::Power(dQnReA,2.) + TMath::Power(dQnImA,2.))
1440 -2.*(TMath::Power(dQnReA,2.)*dQ2nReA+2.*dQnReA*dQnImA*dQ2nImA-TMath::Power(dQnImA,2.)*dQ2nReA)
1441 +(TMath::Power(dQ2nReA,2.)+TMath::Power(dQ2nImA,2.));
1443 cumuRef->Fill(eta, cent, kW4Four, four);
1444 cumuRef->Fill(eta, cent, kW4, w4);
1447 cosPhi1Phi2 = dQnReA*dQnReA - dQnImA*dQnImA - dQ2nReA;
1448 sinPhi1Phi2 = 2.*dQnReA*dQnImA - dQ2nImA;
1450 cosPhi1Phi2Phi3m = dQnReA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1451 -dQnReA*dQ2nReA-dQnImA*dQ2nImA-2.*(multA-1)*dQnReA;
1453 sinPhi1Phi2Phi3m = -dQnImA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1454 +dQnReA*dQ2nImA-dQnImA*dQ2nReA+2.*(multA-1)*dQnImA;
1456 cumuRef->Fill(eta, cent, kCosphi1phi2, cosPhi1Phi2);
1457 cumuRef->Fill(eta, cent, kSinphi1phi2, sinPhi1Phi2);
1458 cumuRef->Fill(eta, cent, kCosphi1phi2phi3m, cosPhi1Phi2Phi3m);
1459 cumuRef->Fill(eta, cent, kSinphi1phi2phi3m, sinPhi1Phi2Phi3m);
1460 cumuRef->Fill(eta, cent, k3pWeight, multA*(multA-1.)*(multA-2.));
1462 } // End of reference flow
1463 // For each etaBin bin the necessary values for differential flow is calculated
1464 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1465 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1466 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1467 Double_t p2nRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n*2));
1468 Double_t p2nIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n*2));
1469 if (mp == 0) continue;
1476 // Differential flow calculations for each eta bin is done:
1477 // 2-particle differential flow
1478 if ((fFlags & kStdQC) && !(fFlags & kTPC)) {
1486 Double_t w2p = mp * multB - mq;
1487 Double_t twoPrime = pnRe*dQnReB + pnIm*dQnImB - mq;
1489 cumuDiff->Fill(eta, cent, kW2Two, twoPrime);
1490 cumuDiff->Fill(eta, cent, kW2, w2p);
1492 if ((fFlags & kEtaGap)) continue;
1493 // Differential flow calculations for each eta bin bin is done:
1494 // 4-particle differential flow
1495 Double_t w4p = (mp * multA - 3.*mq)*(multA - 1.)*(multA - 2.);
1497 Double_t fourPrime = (TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*(pnRe*dQnReA+pnIm*dQnImA)
1498 - q2nRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))
1499 - 2.*q2nIm*dQnReA*dQnImA
1500 - pnRe*(dQnReA*dQ2nReA+dQnImA*dQ2nImA)
1501 + pnIm*(dQnImA*dQ2nReA-dQnReA*dQ2nImA)
1502 - 2.*multA*(pnRe*dQnReA+pnIm*dQnImA)
1503 - 2.*(TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*mq
1504 + 6.*(qnRe*dQnReA+qnIm*dQnImA)
1505 + 1.*(q2nRe*dQ2nReA+q2nIm*dQ2nImA)
1506 + 2.*(pnRe*dQnReA+pnIm*dQnImA)
1510 cumuDiff->Fill(eta, cent, kW4Four, fourPrime);
1511 cumuDiff->Fill(eta, cent, kW4, w4p);
1514 Double_t cosPsi1Phi2 = pnRe*dQnReA - pnIm*dQnImA - q2nRe;
1515 Double_t sinPsi1Phi2 = pnRe*dQnImA + pnIm*dQnReA - q2nIm;
1517 Double_t cosPsi1Phi2Phi3p = pnRe*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1518 - 1.*(q2nRe*dQnReA+q2nIm*dQnImA)
1519 - mq*dQnReA+2.*qnRe;
1521 Double_t sinPsi1Phi2Phi3p = pnIm*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1522 - 1.*(q2nIm*dQnReA-q2nRe*dQnImA)
1523 - mq*dQnImA+2.*qnIm;
1525 Double_t cosPsi1Phi2Phi3m = pnRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))+2.*pnIm*dQnReA*dQnImA
1526 - 1.*(pnRe*dQ2nReA+pnIm*dQ2nImA)
1527 - 2.*mq*dQnReA+2.*qnRe;
1529 Double_t sinPsi1Phi2Phi3m = pnIm*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))-2.*pnRe*dQnReA*dQnImA
1530 - 1.*(pnIm*dQ2nReA-pnRe*dQ2nImA)
1531 + 2.*mq*dQnImA-2.*qnIm;
1533 cumuDiff->Fill(eta, cent, kCosphi1phi2, cosPsi1Phi2);
1534 cumuDiff->Fill(eta, cent, kSinphi1phi2, sinPsi1Phi2);
1535 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3m, cosPsi1Phi2Phi3m);
1536 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3m, sinPsi1Phi2Phi3m);
1537 cumuDiff->Fill(eta, cent, k3pWeight, (mp*multA-2.*mq)*(multA-1.));
1538 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3p, cosPsi1Phi2Phi3p);
1539 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3p, sinPsi1Phi2Phi3p);
1540 } // End of eta loop
1542 cumuRef->Fill(-7., cent, -0.5, 1.);
1543 } // End of moment loop
1546 //_____________________________________________________________________
1547 void AliForwardFlowTaskQC::VertexBin::GetLimits(Int_t bin, Int_t& aLow, Int_t& aHigh,
1548 Int_t& bLow, Int_t& bHigh) const
1551 // Get the limits for the 3 correlator method
1554 // bin : reference bin #
1555 // aLow : Lowest bin to be included in v_A calculations
1556 // aHigh: Highest bin to be included in v_A calculations
1557 // bLow : Lowest bin to be included in v_B calculations
1558 // bHigh: Highest bin to be included in v_B calculations
1560 if ((fFlags & kFMD)) {
1563 aLow = 14; aHigh = 15;
1564 bLow = 20; bHigh = 22;
1567 aLow = 16; aHigh = 16;
1568 bLow = 21; bHigh = 22;
1571 aLow = 6; aHigh = 7;
1572 bLow = 21; bHigh = 22;
1575 aLow = 6; aHigh = 7;
1576 bLow = 12; bHigh = 12;
1579 aLow = 6; aHigh = 8;
1580 bLow = 13; bHigh = 14;
1583 AliFatal(Form("No limits for this eta region! (%d)", bin));
1586 else if ((fFlags & kVZERO)) {
1589 aLow = 6; aHigh = 13;
1590 bLow = 17; bHigh = 18;
1593 aLow = 6; aHigh = 9;
1594 bLow = 17; bHigh = 18;
1597 aLow = 2; aHigh = 3;
1598 bLow = 17; bHigh = 18;
1601 aLow = 2; aHigh = 3;
1602 bLow = 6; bHigh = 9;
1605 aLow = 2; aHigh = 3;
1606 bLow = 6; bHigh = 13;
1609 AliFatal(Form("No limits for this eta region! (%d)", bin));
1612 // Try to catch cases where fEtaLimits and these values do not correspond to each other
1613 if (aHigh > fCumuNUARef->GetNbinsX() || bHigh > fCumuNUARef->GetNbinsX())
1614 AliFatal(Form("Limits outside vtx range! (%d) - aHigh = %d, bHigh = %d, Nbins = %d",
1615 bin, aHigh, bHigh, fCumuNUARef->GetNbinsX()));
1617 //_____________________________________________________________________
1618 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate3Cor(Double_t cent)
1621 // Calculate the Q cumulant up to order fMaxMoment
1624 // cent: centrality of event
1626 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1628 // Fill out NUA hists
1629 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1630 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1631 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1632 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1633 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1636 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1637 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1638 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1639 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1640 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1644 // We create the objects needed for the analysis
1647 // For each n we loop over the hists
1648 for (Int_t n = 2; n <= fMaxMoment; n++) {
1649 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1650 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1652 // Per mom. quantities
1654 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
1655 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1656 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1657 Double_t two = 0, w2 = 0;
1658 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1659 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1660 if (fEtaLims[prevLim] < eta) {
1661 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
1663 multA = 0; dQnReA = 0; dQnImA = 0;
1664 multB = 0; dQnReB = 0; dQnImB = 0;
1666 for (Int_t a = aLow; a <= aHigh; a++) {
1667 multA += fCumuRef->GetBinContent(a, 0);
1668 dQnReA += fCumuRef->GetBinContent(a, GetBinNumberCos(n));
1669 dQnImA += fCumuRef->GetBinContent(a, GetBinNumberSin(n));
1671 for (Int_t b = bLow; b <= bHigh; b++) {
1672 multB += fCumuRef->GetBinContent(b, 0);
1673 dQnReB += fCumuRef->GetBinContent(b, GetBinNumberCos(n));
1674 dQnImB += fCumuRef->GetBinContent(b, GetBinNumberSin(n));
1676 // The reference flow is calculated
1679 two = dQnReA*dQnReB + dQnImA*dQnImB;
1680 } // End of reference flow
1681 cumuRef->Fill(eta, cent, kW2Two, two);
1682 cumuRef->Fill(eta, cent, kW2, w2);
1684 // For each etaBin bin the necessary values for differential flow is calculated
1685 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1686 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1687 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1688 if (mp == 0) continue;
1690 // Differential flow calculations for each eta bin is done:
1691 // 2-particle differential flow
1692 Double_t w2pA = mp * multA;
1693 Double_t twoPrimeA = pnRe*dQnReA + pnIm*dQnImA;
1694 cumuDiff->Fill(eta, cent, kW2Two, twoPrimeA);
1695 cumuDiff->Fill(eta, cent, kW2, w2pA);
1697 Double_t w2pB = mp * multB;
1698 Double_t twoPrimeB = pnRe*dQnReB + pnIm*dQnImB;
1699 cumuDiff->Fill(eta, cent, kW4Four, twoPrimeB);
1700 cumuDiff->Fill(eta, cent, kW4, w2pB);
1701 } // End of eta loop
1703 cumuRef->Fill(-7., cent, -0.5, 1.);
1704 } // End of moment loop
1708 //_____________________________________________________________________
1709 void AliForwardFlowTaskQC::VertexBin::CumulantsTerminate(TList* inlist, TList* outlist)
1712 // Finalizes the Q cumulant calculations
1715 // inlist: input sumlist
1716 // outlist: output result list
1719 // Re-find cumulants hist if Terminate is called separately
1720 if (!fCumuHists.IsConnected()) {
1721 TList* list = (TList*)inlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1722 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1725 fCumuNUARef = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1727 fCumuNUADiff = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1729 // Clone to avoid normalization problems when redoing terminate locally
1730 fCumuNUARef = (TH3D*)fCumuNUARef->Clone(Form("%s_vertex_%d_%d%s_cumuNUARefNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1731 fCumuNUADiff = (TH3D*)fCumuNUADiff->Clone(Form("%s_vertex_%d_%d%s_cumuNUADiffNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1733 // Diagnostics histograms
1734 TH2I* quality = (TH2I*)outlist->FindObject(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1736 quality = MakeQualityHist(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1737 outlist->Add(quality);
1739 TH1D* cent = (TH1D*)outlist->FindObject(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)));
1741 cent = new TH1D(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1742 Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1743 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1744 cent->GetXaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1747 TH2D* dNdetaRef = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)));
1749 dNdetaRef = new TH2D(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1750 Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1751 fCumuNUARef->GetNbinsX(), fCumuNUARef->GetXaxis()->GetXmin(), fCumuNUARef->GetXaxis()->GetXmax(),
1752 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1753 dNdetaRef->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1755 outlist->Add(dNdetaRef);
1757 TH2D* dNdetaDiff = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)));
1759 dNdetaDiff = new TH2D(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1760 Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1761 fCumuNUADiff->GetNbinsX(), fCumuNUADiff->GetXaxis()->GetXmin(), fCumuNUADiff->GetXaxis()->GetXmax(),
1762 fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXmin(), fCumuNUADiff->GetYaxis()->GetXmax());
1763 dNdetaDiff->GetYaxis()->Set(fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXbins()->GetArray());
1764 dNdetaDiff->Sumw2();
1765 outlist->Add(dNdetaDiff);
1768 // Setting up outputs
1769 // Create output lists and diagnostics
1770 TList* vtxList = (TList*)outlist->FindObject("vtxList");
1772 vtxList = new TList();
1773 vtxList->SetName("vtxList");
1774 outlist->Add(vtxList);
1776 vtxList->Add(fCumuNUARef);
1777 vtxList->Add(fCumuNUADiff);
1779 // Setup output profiles
1780 CumuHistos cumu2(fMaxMoment, ((fFlags & kNUAcorr) ? 2 : 0));
1781 CumuHistos cumu4(fMaxMoment, ((fFlags & kNUAcorr) ? 1 : 0));
1783 cumu2.ConnectList(Form("%sQC2_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1784 if ((fFlags & kStdQC))
1785 cumu4.ConnectList(Form("%sQC4_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1787 for (Int_t n = 2; n <= fMaxMoment; n++) {
1789 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNoNUA));
1790 if ((fFlags & k3Cor)){
1791 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNoNUA));
1792 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNoNUA));
1794 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNoNUA));
1797 if ((fFlags & kStdQC)) {
1798 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNoNUA));
1799 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNoNUA));
1801 } // End of v_n result loop
1803 if ((fFlags & kNUAcorr)) {
1804 for (Int_t n = 2; n <= fMaxMoment; n++) {
1806 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUAOld));
1807 if ((fFlags & k3Cor)) {
1808 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUAOld));
1809 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUAOld));
1811 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUAOld));
1814 if ((fFlags & kStdQC)) {
1815 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNUAOld));
1816 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNUAOld));
1819 for (Int_t n = 2; n <= fMaxMoment; n++) {
1821 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUA));
1822 if ((fFlags & k3Cor)) {
1823 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUA));
1824 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUA));
1826 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUA));
1831 // Calculating the cumulants
1832 if ((fFlags & k3Cor)) {
1833 Calculate3CorFlow(cumu2, quality, cent, dNdetaRef, dNdetaDiff);
1835 CalculateReferenceFlow(cumu2, cumu4, quality, cent, dNdetaRef);
1836 CalculateDifferentialFlow(cumu2, cumu4, quality, dNdetaDiff);
1838 if ((fFlags & kNUAcorr)) {
1839 SolveCoupledFlowEquations(cumu2, 'r');
1840 if ((fFlags & k3Cor)) {
1841 SolveCoupledFlowEquations(cumu2, 'a');
1842 SolveCoupledFlowEquations(cumu2, 'b');
1844 SolveCoupledFlowEquations(cumu2, 'd');
1848 // Add to output for immediate viewing - individual vtx bins are used for final results
1849 AddVertexBins(cumu2, outlist, ((fFlags & kNUAcorr) ? 2 : 0));
1850 if ((fFlags & kStdQC)) AddVertexBins(cumu4, outlist, ((fFlags & kNUAcorr) ? 1 : 0));
1852 // Setup NUA diagnoastics histograms
1853 TList* nualist = (TList*)outlist->FindObject("NUATerms");
1855 nualist = new TList();
1856 nualist->SetName("NUATerms");
1857 outlist->Add(nualist);
1860 TH2D* nuaRef = (TH2D*)nualist->FindObject(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1863 nuaRef = (TH2D*)fCumuNUARef->Project3D("yz");
1864 nuaRef->Scale(1./fCumuNUARef->GetNbinsX());
1865 nuaRef->SetName(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1866 nuaRef->SetTitle(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1867 nualist->Add(nuaRef);
1869 temp = (TH2D*)fCumuNUARef->Project3D("yz");
1870 temp->Scale(1./fCumuNUARef->GetNbinsX());
1874 // Filling in underflow to make scaling possible in Terminate()
1875 nuaRef->Fill(0., -1., 1.);
1877 TH2D* nuaDiff = (TH2D*)nualist->FindObject(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1879 nuaDiff = (TH2D*)fCumuNUADiff->Project3D("yz");
1880 nuaDiff->SetName(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1881 nuaDiff->SetTitle(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1882 nualist->Add(nuaDiff);
1884 temp = (TH2D*)fCumuNUADiff->Project3D("yz");
1888 // Filling in underflow to make scaling possible in Terminate()
1889 nuaDiff->Fill(0., -1., 1.);
1893 //_____________________________________________________________________
1894 void AliForwardFlowTaskQC::VertexBin::CalculateReferenceFlow(CumuHistos& cumu2h, CumuHistos& cumu4h, TH2I* quality,
1895 TH1D* chist, TH2D* dNdetaRef) const
1898 // Calculates the reference flow
1901 // cumu2h: CumuHistos object with QC{2} cumulants
1902 // cumu4h: CumuHistos object with QC{4} cumulants
1903 // quality: Histogram for success rate of cumulants
1904 // chist: Centrality histogram
1905 // dNdetaRef: dN/deta histogram for estimating multiplicity used for ref calculations
1908 // Normalizing common NUA hists
1909 for (Int_t cBin = 1; cBin <= fCumuNUARef->GetNbinsY(); cBin++) {
1910 Double_t cent = fCumuNUARef->GetYaxis()->GetBinCenter(cBin);
1911 for (Int_t eBin = 1; eBin <= fCumuNUARef->GetNbinsX(); eBin++) {
1912 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(eBin);
1913 Double_t mult = fCumuNUARef->GetBinContent(eBin, cBin, 0);
1914 if (mult == 0) continue;
1915 for (Int_t qBin = 1; qBin <= fCumuNUARef->GetNbinsZ(); qBin++) {
1916 fCumuNUARef->SetBinContent(eBin, cBin, qBin, fCumuNUARef->GetBinContent(eBin, cBin, qBin)/mult);
1917 fCumuNUARef->SetBinError(eBin, cBin, qBin, fCumuNUARef->GetBinError(eBin, cBin, qBin)/mult);
1919 // Fill dN/deta diagnostics
1920 dNdetaRef->Fill(eta, cent, mult);
1924 // For flow calculations
1927 TH2D* cumu2NUAold = 0;
1930 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
1931 // Loop over cumulant histogram for final calculations
1932 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
1933 cumu2 = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
1934 if ((fFlags & kNUAcorr)) {
1935 cumu2NUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
1937 if ((fFlags & kStdQC)) {
1938 cumu4 = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNoNUA);
1939 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNUAOld);
1941 cumuRef = (TH3D*)fCumuHists.Get('r', n);
1943 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
1944 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
1945 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
1946 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
1947 for (Int_t etaBin = 1; etaBin <= cumuRef->GetNbinsX(); etaBin++) { // Eta loop begins
1948 Double_t eta = cumuRef->GetXaxis()->GetBinCenter(etaBin);
1949 Double_t refEta = eta;
1950 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(refEta);
1951 if ((fFlags & kEtaGap)) refEta = -eta;
1952 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(refEta);
1953 // 2-particle reference flow
1954 Double_t w2Two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
1955 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
1956 if (w2 == 0) continue;
1957 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
1958 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
1959 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
1960 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
1961 Double_t cos2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(2*n));
1962 Double_t sin2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(2*n));
1963 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
1964 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
1965 Double_t two = w2Two / w2;
1967 if (qc2 >= 0) cumu2->Fill(eta, cent, TMath::Sqrt(qc2));
1969 if ((fFlags & kNUAcorr)) {
1971 // With no eta gap the last two terms are <<cos(phi)>>^2 and <<sin(phi)>>^2,
1972 // with eta gap the different coverage is taken into account.
1973 // The next line covers both cases.
1974 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
1975 // Extra NUA term from 2n cosines and sines
1976 Double_t den = 1-(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB);
1977 if (den != 0) qc2 /= den;
1982 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
1983 fType.Data(), n, qc2, eta, cent));
1984 quality->Fill((n-2)*qualityFactor+2, Int_t(cent));
1987 Double_t vnTwo = TMath::Sqrt(qc2);
1988 if (!TMath::IsNaN(vnTwo)) {
1989 quality->Fill((n-2)*qualityFactor+1, Int_t(cent));
1990 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, vnTwo);
1993 if (!(fFlags & kStdQC)) continue;
1994 // 4-particle reference flow
1995 Double_t w4Four = cumuRef->GetBinContent(refEtaBinA, cBin, kW4Four);
1996 Double_t w4 = cumuRef->GetBinContent(refEtaBinA, cBin, kW4);
1997 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
1998 if (w4 == 0 || multm1m2 == 0) continue;
1999 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2000 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2001 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2002 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2004 cosP1nPhi1P1nPhi2 /= w2;
2005 sinP1nPhi1P1nPhi2 /= w2;
2006 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2007 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2008 Double_t four = w4Four / w4;
2009 Double_t qc4 = four-2.*TMath::Power(two,2.);
2010 if (qc4 < 0) cumu4->Fill(eta, cent, TMath::Power(-qc4, 0.25));
2012 if ((fFlags & kNUAcorr)) {
2013 qc4 += - 4.*cosP1nPhiA*cosP1nPhi1M1nPhi2M1nPhi3
2014 + 4.*sinP1nPhiA*sinP1nPhi1M1nPhi2M1nPhi3-TMath::Power(cosP1nPhi1P1nPhi2,2.)-TMath::Power(sinP1nPhi1P1nPhi2,2.)
2015 + 4.*cosP1nPhi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2016 + 8.*sinP1nPhi1P1nPhi2*sinP1nPhiA*cosP1nPhiA
2017 + 8.*two*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2018 - 6.*TMath::Power((TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.)),2.);
2022 AliInfo(Form("%s: QC_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2023 fType.Data(), n, qc2, eta, cent));
2024 quality->Fill((n-2)*qualityFactor+6, Int_t(cent));
2027 Double_t vnFour = TMath::Power(-qc4, 0.25);
2028 if (!TMath::IsNaN(vnFour*multm1m2)) {
2029 quality->Fill((n-2)*qualityFactor+5, Int_t(cent));
2030 if ((fFlags & kNUAcorr)) cumu4NUA->Fill(eta, cent, vnFour);
2038 //_____________________________________________________________________
2039 void AliForwardFlowTaskQC::VertexBin::CalculateDifferentialFlow(CumuHistos& cumu2h, CumuHistos& cumu4h,
2040 TH2I* quality, TH2D* dNdetaDiff) const
2043 // Calculates the differential flow
2046 // cumu2h: CumuHistos object with QC{2} cumulants
2047 // cumu4h: CumuHistos object with QC{4} cumulants
2048 // quality: Histogram for success rate of cumulants
2049 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2052 for (Int_t cBin = 1; cBin <= fCumuNUADiff->GetNbinsY(); cBin++) {
2053 Double_t cent = fCumuNUADiff->GetYaxis()->GetBinCenter(cBin);
2054 for (Int_t eBin = 1; eBin <= fCumuNUADiff->GetNbinsX(); eBin++) {
2055 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(eBin);
2056 Double_t mult = fCumuNUADiff->GetBinContent(eBin, cBin, 0);
2057 if (mult == 0) continue;
2058 for (Int_t qBin = 1; qBin <= fCumuNUADiff->GetNbinsZ(); qBin++) {
2059 fCumuNUADiff->SetBinContent(eBin, cBin, qBin, fCumuNUADiff->GetBinContent(eBin, cBin, qBin)/mult);
2060 fCumuNUADiff->SetBinError(eBin, cBin, qBin, fCumuNUADiff->GetBinError(eBin, cBin, qBin)/mult);
2062 dNdetaDiff->Fill(eta, cent, mult);
2066 // For flow calculations
2070 TH2D* cumu2NUAold = 0;
2073 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
2074 // Loop over cumulant histogram for final calculations
2075 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2076 cumu2 = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNoNUA);
2077 if ((fFlags & kNUAcorr)) {
2078 cumu2NUAold = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNUAOld);
2080 if ((fFlags & kStdQC)) {
2081 cumu4 = (TH2D*)cumu4h.Get('d',n);
2082 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('d', n, CumuHistos::kNUAOld);
2084 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2085 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2086 for (Int_t cBin = 1; cBin <= cumuDiff->GetNbinsY(); cBin++) { // Centrality loop begins
2087 Double_t cent = cumuDiff->GetYaxis()->GetBinCenter(cBin);
2088 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2089 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2090 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2091 Double_t refEta = eta;
2092 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(refEta);
2093 if ((fFlags & kEtaGap)) refEta = -eta;
2094 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(refEta);
2096 // Reference objects
2097 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
2098 if (w2 == 0) continue;
2099 Double_t two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
2101 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
2102 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
2103 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
2104 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
2105 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
2106 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
2108 // 2-particle differential flow
2109 Double_t w2pTwoPrime = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2110 Double_t w2p = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2111 if (w2p == 0) continue;
2112 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2113 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2114 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2115 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2116 Double_t twoPrime = w2pTwoPrime / w2p;
2118 Double_t qc2Prime = twoPrime;
2119 cumu2->Fill(eta, cent, qc2Prime);
2120 if ((fFlags & kNUAcorr)) {
2122 qc2Prime -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB;
2123 // Extra NUA term from 2n cosines and sines
2124 qc2Prime /= (1.-(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
2126 if (!TMath::IsNaN(qc2Prime)) {
2127 quality->Fill((n-2)*qualityFactor+3, Int_t(cent));
2128 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, qc2Prime);
2131 quality->Fill((n-2)*qualityFactor+4, Int_t(cent));
2133 AliInfo(Form("%s: QC'_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2134 fType.Data(), n, qc2Prime, eta, cent));
2136 if (!(fFlags & kStdQC)) continue;
2137 // Reference objects
2138 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2139 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2140 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2141 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2142 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
2143 cosP1nPhi1P1nPhi2 /= w2;
2144 sinP1nPhi1P1nPhi2 /= w2;
2145 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2146 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2148 // 4-particle differential flow
2149 Double_t w4pFourPrime = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2150 Double_t w4p = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2151 Double_t mpqMult = cumuDiff->GetBinContent(etaBin, cBin, k3pWeight);
2152 if (w4p == 0 || mpqMult == 0) continue;
2153 Double_t cosP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2);
2154 Double_t sinP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2);
2155 Double_t cosP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3m);
2156 Double_t sinP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3m);
2157 Double_t cosP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3p);
2158 Double_t sinP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3p);
2160 cosP1nPsi1P1nPhi2 /= w2p;
2161 sinP1nPsi1P1nPhi2 /= w2p;
2162 cosP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2163 sinP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2164 cosP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2165 sinP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2167 Double_t fourPrime = w4pFourPrime / w4p;
2168 Double_t qc4Prime = fourPrime-2.*twoPrime*two;
2169 if (cumu4) cumu4->Fill(eta, cent, qc4Prime);
2171 if ((fFlags & kNUAcorr)) {
2172 qc4Prime += - cosP1nPsi*cosP1nPhi1M1nPhi2M1nPhi3
2173 + sinP1nPsi*sinP1nPhi1M1nPhi2M1nPhi3
2174 - cosP1nPhiA*cosP1nPsi1M1nPhi2M1nPhi3
2175 + sinP1nPhiA*sinP1nPsi1M1nPhi2M1nPhi3
2176 - 2.*cosP1nPhiA*cosP1nPsi1P1nPhi2M1nPhi3
2177 - 2.*sinP1nPhiA*sinP1nPsi1P1nPhi2M1nPhi3
2178 - cosP1nPsi1P1nPhi2*cosP1nPhi1P1nPhi2
2179 - sinP1nPsi1P1nPhi2*sinP1nPhi1P1nPhi2
2180 + 2.*cosP1nPhi1P1nPhi2*(cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2181 + 2.*sinP1nPhi1P1nPhi2*(cosP1nPsi*sinP1nPhiA+sinP1nPsi*cosP1nPhiA)
2182 + 4.*two*(cosP1nPsi*cosP1nPhiA+sinP1nPsi*sinP1nPhiA)
2183 + 2.*cosP1nPsi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2184 + 4.*sinP1nPsi1P1nPhi2*cosP1nPhiA*sinP1nPhiA
2185 + 4.*twoPrime*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2186 - 6.*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2187 * (cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2188 - 12.*cosP1nPhiA*sinP1nPhiA
2189 * (sinP1nPsi*cosP1nPhiA+cosP1nPsi*sinP1nPhiA);
2191 // Double_t vnFourDiff = - qc4Prime / TMath::Power(-qc4, 0.75);
2192 if (!TMath::IsNaN(qc4Prime*mpqMult)) {
2193 quality->Fill((n-2)*qualityFactor+7, Int_t(cent));
2194 if (cumu4NUA) cumu4NUA->Fill(eta, cent, qc4Prime);
2197 quality->Fill((n-2)*qualityFactor+8, Int_t(cent));
2199 AliInfo(Form("%s: v_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f",
2200 fType.Data(), n, qc4Prime, eta, cent));
2201 } // End of eta loop
2202 } // End of centrality loop
2207 //_____________________________________________________________________
2208 void AliForwardFlowTaskQC::VertexBin::Calculate3CorFlow(CumuHistos& cumu2h, TH2I* quality, TH1D* chist,
2209 TH2D* dNdetaRef, TH2D* dNdetaDiff) const
2212 // Calculates the 3 sub flow
2215 // cumu2h: CumuHistos object with QC{2} cumulants
2216 // quality: Histogram for success rate of cumulants
2217 // chist: Centrality histogram
2218 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2221 // For flow calculations
2225 TH2D* cumu2rNUAold = 0;
2227 TH2D* cumu2aNUAold = 0;
2229 TH2D* cumu2bNUAold = 0;
2230 // Loop over cumulant histogram for final calculations
2231 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2232 cumu2r = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
2233 cumu2a = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNoNUA);
2234 cumu2b = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNoNUA);
2235 if ((fFlags & kNUAcorr)) {
2236 cumu2rNUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
2237 cumu2aNUAold = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNUAOld);
2238 cumu2bNUAold = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNUAOld);
2240 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2241 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2242 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
2243 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
2244 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
2245 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2248 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2249 Double_t cosP1nPhiA = 0;
2250 Double_t sinP1nPhiA = 0;
2251 Double_t cos2nPhiA = 0;
2252 Double_t sin2nPhiA = 0;
2253 Double_t cosP1nPhiB = 0;
2254 Double_t sinP1nPhiB = 0;
2255 Double_t cos2nPhiB = 0;
2256 Double_t sin2nPhiB = 0;
2260 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2261 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2262 // 2-particle reference flow
2263 Double_t w2Two = cumuRef->GetBinContent(etaBin, cBin, kW2Two);
2264 Double_t w2 = cumuRef->GetBinContent(etaBin, cBin, kW2);
2265 if (w2 == 0) continue;
2267 // Update NUA for new range!
2268 if (fEtaLims[prevLim] < eta) {
2269 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
2271 cosP1nPhiA = 0; sinP1nPhiA = 0; cos2nPhiA = 0; sin2nPhiA = 0; multA = 0;
2272 cosP1nPhiB = 0; sinP1nPhiB = 0; cos2nPhiB = 0; sin2nPhiB = 0; multB = 0;
2273 for (Int_t a = aLow; a <= aHigh; a++) {
2274 cosP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n));
2275 sinP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n));
2276 cos2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2277 sin2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2278 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2280 for (Int_t b = bLow; b <= bHigh; b++) {
2281 cosP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n));
2282 sinP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n));
2283 cos2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2284 sin2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2285 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2287 if (multA == 0 || multB == 0) AliFatal("Empty NUA values for 3Cor!");
2288 cosP1nPhiA /= multA;
2289 sinP1nPhiA /= multA;
2292 cosP1nPhiB /= multB;
2293 sinP1nPhiB /= multB;
2297 dNdetaRef->Fill(eta, cent, multA+multB);
2299 Double_t two = w2Two / w2;
2302 if (qc2 >= 0) cumu2r->Fill(eta, cent, TMath::Sqrt(qc2));
2304 if ((fFlags & kNUAcorr)) {
2306 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
2307 // Extra NUA term from 2n cosines and sines
2308 qc2 /= (1-(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB));
2312 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2313 fType.Data(), n, qc2, eta, cent));
2314 quality->Fill((n-2)*4+2, Int_t(cent));
2317 Double_t vnTwo = TMath::Sqrt(qc2);
2318 if (!TMath::IsNaN(vnTwo)) {
2319 quality->Fill((n-2)*4+1, Int_t(cent));
2320 if ((fFlags & kNUAcorr)) cumu2rNUAold->Fill(eta, cent, vnTwo);
2323 // 2-particle differential flow
2324 Double_t w2pTwoPrimeA = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2325 Double_t w2pA = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2326 Double_t w2pTwoPrimeB = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2327 Double_t w2pB = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2328 if (w2pA == 0 || w2pB == 0) continue;
2329 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2330 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2331 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2332 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2333 Double_t mult = fCumuNUADiff->GetBinContent(etaBin, cBin, 0);
2334 if (mult == 0) continue;
2339 Double_t twoPrimeA = w2pTwoPrimeA / w2pA;
2340 Double_t twoPrimeB = w2pTwoPrimeB / w2pB;
2341 dNdetaDiff->Fill(eta, cent, mult);
2343 Double_t qc2PrimeA = twoPrimeA;
2344 Double_t qc2PrimeB = twoPrimeB;
2345 if (qc2PrimeA*qc2PrimeB >= 0) {
2346 cumu2a->Fill(eta, cent, qc2PrimeA);
2347 cumu2b->Fill(eta, cent, qc2PrimeB);
2349 if ((fFlags & kNUAcorr)) {
2351 qc2PrimeA -= cosP1nPsi*cosP1nPhiA + sinP1nPsi*sinP1nPhiA;
2352 qc2PrimeB -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB; // Is this OK?
2353 // Extra NUA term from 2n cosines and sines
2354 qc2PrimeA /= (1.-(cos2nPsi*cos2nPhiA + sin2nPsi*sin2nPhiA));
2355 qc2PrimeB /= (1.-(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
2357 if (!TMath::IsNaN(qc2PrimeA) && !TMath::IsNaN(qc2PrimeB) && qc2 != 0) {
2358 if (qc2PrimeA*qc2PrimeB >= 0) {
2359 quality->Fill((n-2)*4+3, Int_t(cent));
2360 if ((fFlags & kNUAcorr)) cumu2aNUAold->Fill(eta, cent, qc2PrimeA);
2361 if ((fFlags & kNUAcorr)) cumu2bNUAold->Fill(eta, cent, qc2PrimeB);
2365 quality->Fill((n-2)*4+4, Int_t(cent));
2367 AliInfo(Form("%s: QC'a_%d{2} = %1.3f, QC'b_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2368 fType.Data(), n, qc2PrimeA, n, qc2PrimeB, eta, cent));
2369 } // End of eta loop
2370 } // End of centrality loop
2375 //_____________________________________________________________________
2376 void AliForwardFlowTaskQC::VertexBin::SolveCoupledFlowEquations(CumuHistos& cumu, const Char_t type) const
2379 // Function to solve the coupled flow equations
2380 // We solve it by using matrix calculations:
2381 // A*v_n = V => v_n = A^-1*V
2382 // First we set up a TMatrixD container to make ROOT
2383 // do the inversions in an efficient way, we multiply the current <<2>> estimates.
2384 // Then we fill new TH2D's if the corrected <<2>>'s (cumuNUA object).
2387 // cumu: CumuHistos object - uncorrected
2388 // type: Reference ('r') or differential ('d') or ('a' or 'b') for 3 correlator
2391 // We start by declaring Matrix and vector objects, as their constructors are quite heavy
2392 TMatrixD mNUA(fMaxMoment-1, fMaxMoment-1);
2393 TVectorD vQC2(fMaxMoment-1);
2395 for (Int_t cBin = 1; cBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsY(); cBin++) { // cent loop
2396 Double_t cent = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinCenter(cBin);
2397 for (Int_t eBin = 1; eBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsX(); eBin++) { // eta loop
2398 Double_t eta = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin);
2399 mNUA.Zero(); // reset matrix
2400 vQC2.Zero(); // reset vector
2401 for (Int_t n = 0; n < fMaxMoment-1; n++) { // moment loop
2402 vQC2(n) = static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUAOld))->GetBinContent(eBin, cBin);
2403 if (type == 'r' || type == 'R') vQC2(n) *= vQC2(n); // going back to <<2>>
2404 for (Int_t m = 0; m < fMaxMoment-1; m++) { // cross moment
2405 mNUA(n,m) = CalculateNUAMatrixElement(n, m, type, eBin, cBin);
2406 } // End of cross moment loop
2407 } // End of moment loop
2411 // If determinant is non-zero we go with corrected results
2412 if (det != 0 ) vQC2 = mNUA*vQC2;
2413 else AliWarning(Form("Determinant == 0 - cent: %d-%d, eta: %f, type: '%c', data: %s, vtx: %d-%d%s",
2414 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinLowEdge(cBin)),
2415 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinUpEdge(cBin)),
2416 cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin),
2417 type, fType.Data(), fVzMin, fVzMax,
2418 GetQCType(fFlags, kTRUE)));
2419 // Go back to v_n for ref. keep <<2'>> for diff. flow).
2420 for (Int_t n = 0; n < fMaxMoment-1; n++) {
2422 if (type == 'r' || type == 'R')
2423 vnTwo = (vQC2(n) > 0. ? TMath::Sqrt(vQC2(n)) : 0.);
2425 // is really more <<2'>> in this case
2428 // Fill in corrected v_n
2429 if (vnTwo != 0) static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUA))->Fill(eta, cent, vnTwo);
2430 } // End of moment loop
2431 } // End of eta loop
2432 } // End of centrality loop
2435 //_____________________________________________________________________
2436 Double_t AliForwardFlowTaskQC::VertexBin::CalculateNUAMatrixElement(Int_t n, Int_t m, Char_t type, Int_t binA, Int_t cBin) const
2439 // Calculates the (n,m)-th element in the NUA matrix: 1 if n == m, otherwise:
2440 // <<cos[(n-m)phi1]>>*<<cos[(n-m)phi2]>> + <<sin[(n-m)phi1]>>*<<sin[(n-m)phi2]>>
2441 // NUA(n,m) = -----------------------------------------------------------------------------
2442 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
2444 // <<cos[(n+m)phi1]>>*<<cos[(n+m)phi2]>> + <<sin[(n+m)phi1]>>*<<sin[(n+m)phi2]>>
2445 // + -----------------------------------------------------------------------------
2446 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
2451 // type: Reference ('r') or differential ('d') or ('a' or 'b')
2452 // binA: eta bin of phi1
2453 // cBin: centrality bin
2457 if (n == m) return 1.;
2461 Double_t cosnMmPhi1 = 0, cosnMmPhi2 = 0, sinnMmPhi1 = 0, sinnMmPhi2 = 0;
2462 Double_t cosnPmPhi1 = 0, cosnPmPhi2 = 0, sinnPmPhi1 = 0, sinnPmPhi2 = 0;
2463 Double_t cos2nPhi1 = 0, cos2nPhi2 = 0, sin2nPhi1 = 0, sin2nPhi2 = 0;
2466 if (type == 'r' || type == 'R') {
2467 if ((fFlags & k3Cor)) {
2468 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(binA);
2470 while (fEtaLims[i] < eta) i++;
2471 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2472 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2473 Double_t multA = 0, multB = 0;
2474 for (Int_t a = aLow; a <= aHigh; a++) {
2475 cosnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n-m));
2476 sinnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n-m));
2477 cosnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n+m));
2478 sinnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n+m));
2479 cos2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2480 sin2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2481 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2483 for (Int_t b = bLow; b <= bHigh; b++) {
2484 cosnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n-m));
2485 sinnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n-m));
2486 cosnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n+m));
2487 sinnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n+m));
2488 cos2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2489 sin2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2490 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2492 if (multA == 0 || multB == 0) {
2493 if (fDebug > 0) AliWarning("multA or multB == 0 in matrix elements, aborting NUA");
2496 cosnMmPhi1 /= multA;
2497 sinnMmPhi1 /= multA;
2498 cosnPmPhi1 /= multA;
2499 sinnPmPhi1 /= multA;
2502 cosnMmPhi2 /= multB;
2503 sinnMmPhi2 /= multB;
2504 cosnPmPhi2 /= multB;
2505 sinnPmPhi2 /= multB;
2509 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUARef->GetXaxis()->GetBinCenter(binA));
2510 cosnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2511 sinnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2512 cosnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2513 sinnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2514 cos2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2515 sin2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2516 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2517 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2518 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2519 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2520 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2521 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2523 } // differential flow
2524 else if (type == 'd' || type == 'D') {
2525 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUADiff->GetXaxis()->GetBinCenter(binA));
2526 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2527 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2528 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2529 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2530 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2531 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2532 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2533 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2534 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2535 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2536 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2537 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2538 } // 3 correlator part a or b
2539 else if (type == 'a' || type == 'A' || type == 'b' || type == 'B') {
2540 Double_t mult1 = 0, mult2 = 0;
2542 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2543 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2544 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2545 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2546 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2547 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2548 mult1 = fCumuNUADiff->GetBinContent(binA, cBin, 0);
2550 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(binA);
2552 while (fEtaLims[i] < eta) i++;
2553 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2554 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2555 Int_t lLow = ((type == 'a' || type == 'A') ? aLow : bLow);
2556 Int_t lHigh = ((type == 'a' || type == 'A') ? aHigh : bHigh);
2557 for (Int_t l = lLow; l <= lHigh; l++) {
2558 cosnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n-m));
2559 sinnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n-m));
2560 cosnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n+m));
2561 sinnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n+m));
2562 cos2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(2*n));
2563 sin2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(2*n));
2564 mult2 += fCumuNUARef->GetBinContent(l, cBin, 0);
2566 if (mult1 == 0 || mult2 == 0) {
2567 if (fDebug > 0) AliWarning("mult1 or mult2 == 0 in matrix elements, aborting NUA");
2570 cosnMmPhi1 /= mult1;
2571 sinnMmPhi1 /= mult1;
2572 cosnPmPhi1 /= mult1;
2573 sinnPmPhi1 /= mult1;
2576 cosnMmPhi2 /= mult2;
2577 sinnMmPhi2 /= mult2;
2578 cosnPmPhi2 /= mult2;
2579 sinnPmPhi2 /= mult2;
2584 // Actual calculation
2585 Double_t e = cosnMmPhi1*cosnMmPhi2 + sinnMmPhi1*sinnMmPhi2 + cosnPmPhi1*cosnPmPhi2 + sinnPmPhi1*sinnPmPhi2;
2586 Double_t den = 1 + cos2nPhi1*cos2nPhi2 + sin2nPhi1*sin2nPhi2;
2587 if (den != 0) e /= den;
2592 //_____________________________________________________________________
2593 void AliForwardFlowTaskQC::VertexBin::AddVertexBins(CumuHistos& cumu, TList* list, UInt_t nNUA) const
2596 // Add up vertex bins with flow results
2599 // cumu: CumuHistos object with vtxbin results
2600 // list: Outout list with added results
2601 // nNUA: # of NUA histograms to loop over
2604 TProfile2D* avgProf = 0;
2606 Int_t nT = ((fFlags & k3Cor) ? 3 : 2);
2608 for (UInt_t nua = 0; nua <= nNUA; nua++) { // NUA loop
2609 for (Int_t n = 2; n <= fMaxMoment; n++) { // moment loop
2610 for (Int_t t = 0; t < nT; t++) { // type loop (r/d/a/b)
2613 case 0: ct = 'r'; break;
2614 case 1: ct = ((fFlags & k3Cor) ? 'a' : 'd'); break;
2615 case 2: ct = 'b'; break;
2616 default: ct = '\0'; break;
2618 vtxHist = static_cast<TH2D*>(cumu.Get(ct,n,nua));
2620 AliWarning("VertexBin::AddVertexBins: vtxHist not found!");
2623 name = vtxHist->GetName();
2624 // Strip name of vtx info
2625 Ssiz_t l = name.Last('x')-3;
2627 avgProf = (TProfile2D*)list->FindObject(name.Data());
2628 // if no output profile yet, make one
2630 avgProf = new TProfile2D(name.Data(), name.Data(),
2631 vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXmin(), vtxHist->GetXaxis()->GetXmax(),
2632 vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXmin(), vtxHist->GetYaxis()->GetXmax());
2633 if (vtxHist->GetXaxis()->IsVariableBinSize())
2634 avgProf->GetXaxis()->Set(vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXbins()->GetArray());
2635 if (vtxHist->GetYaxis()->IsVariableBinSize())
2636 avgProf->GetYaxis()->Set(vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXbins()->GetArray());
2639 // Fill in, cannot be done with Add function.
2640 for (Int_t e = 1; e <= vtxHist->GetNbinsX(); e++) { // eta loop
2641 Double_t eta = vtxHist->GetXaxis()->GetBinCenter(e);
2642 for (Int_t c = 1; c <= vtxHist->GetNbinsY(); c++) { // cent loop
2643 Double_t cent = vtxHist->GetYaxis()->GetBinCenter(c);
2644 Double_t cont = vtxHist->GetBinContent(e, c);
2645 if (cont == 0) continue;
2646 avgProf->Fill(eta, cent, cont);
2647 } // End of cent loop
2648 } // End of eta loop
2649 } // End of type loop
2650 } // End of moment loop
2651 } // End of nua loop
2653 //_____________________________________________________________________
2654 Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberCos(Int_t n) const
2657 // Get the bin number of <<cos(nphi)>>
2662 // Return: bin number
2667 if (n == 0) bin = fMaxMoment*4-1;
2672 //_____________________________________________________________________
2673 Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberSin(Int_t n) const
2676 // Get the bin number of <<sin(nphi)>>
2681 // Return: bin number
2686 if (n == 0) bin = fMaxMoment*4;
2691 //_____________________________________________________________________
2692 void AliForwardFlowTaskQC::VertexBin::SetupNUALabels(TAxis* a) const
2695 // Setup NUA labels on axis
2698 // a: Axis to set up
2700 if (a->GetNbins() != GetBinNumberSin()) AliFatal("SetupNUALabels: Wrong number of bins on axis");
2703 while (i <= a->GetNbins()) {
2704 a->SetBinLabel(i++, Form("<<cos(%d#varphi)>>", j));
2705 a->SetBinLabel(i++, Form("<<sin(%d#varphi)>>", j++));
2710 //_____________________________________________________________________
2711 TH2I* AliForwardFlowTaskQC::VertexBin::MakeQualityHist(const Char_t* name) const
2714 // Add a histogram for checking the analysis quality
2717 // const char*: name of data type
2719 // Return: histogram for tracking successful calculations
2721 Int_t nBins = ((fFlags & kStdQC) ? 8 : 4);
2722 TH2I* quality = new TH2I(name, name, (fMaxMoment-1)*nBins, 1, (fMaxMoment-1)*nBins+1, fCumuNUARef->GetNbinsY(),
2723 fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
2724 quality->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
2725 for (Int_t i = 2, j = 1; i <= fMaxMoment; i++) {
2726 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} > 0", i));
2727 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} <= 0", i));
2728 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} > 0", i));
2729 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} <= 0", i));
2730 if ((fFlags & kStdQC)) {
2731 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} < 0", i));
2732 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} >= 0", i));
2733 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} < 0", i));
2734 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} >= 0", i));
2740 //_____________________________________________________________________
2741 TH2D* AliForwardFlowTaskQC::VertexBin::MakeOutputHist(Int_t qc, Int_t n, const Char_t* ctype, UInt_t nua) const
2744 // Setup a TH2D for the output
2747 // qc # of particle correlations
2749 // ref Type: r/d/a/b
2750 // nua For nua corrected hists?
2752 // Return: 2D hist for results
2754 Bool_t ref = ((ctype[0] == 'R') || (ctype[0] == 'r'));
2755 TAxis* xAxis = (ref ? fCumuNUARef->GetXaxis() : fCumuNUADiff->GetXaxis());
2756 TAxis* yAxis = (ref ? fCumuNUARef->GetYaxis() : fCumuNUADiff->GetYaxis());
2759 case CumuHistos::kNoNUA: ntype = "Un"; break;
2760 case CumuHistos::kNUAOld: ntype = "NUAOld"; break;
2761 case CumuHistos::kNUA: ntype = "NUA"; break;
2764 TH2D* h = new TH2D(Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2765 fType.Data(), qc, n, ctype, ntype.Data(),
2766 GetQCType(fFlags), fVzMin, fVzMax),
2767 Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2768 fType.Data(), qc, n, ctype, ntype.Data(),
2769 GetQCType(fFlags), fVzMin, fVzMax),
2770 xAxis->GetNbins(), xAxis->GetXmin(), xAxis->GetXmax(),
2771 yAxis->GetNbins(), yAxis->GetXmin(), yAxis->GetXmax());
2772 if (xAxis->IsVariableBinSize()) h->GetXaxis()->Set(xAxis->GetNbins(), xAxis->GetXbins()->GetArray());
2773 h->GetYaxis()->Set(yAxis->GetNbins(), yAxis->GetXbins()->GetArray());
2777 //_____________________________________________________________________
2778 void AliForwardFlowTaskQC::PrintFlowSetup() const
2781 // Print the setup of the flow task
2783 Printf("=======================================================");
2784 Printf("%s::Print", this->IsA()->GetName());
2785 Printf("Forward detector: :\t%s", ((fFlowFlags & kFMD) ? "FMD" : "VZERO"));
2786 Printf("Number of bins in vertex axis :\t%d", fVtxAxis->GetNbins());
2787 Printf("Range of vertex axis :\t[%3.1f,%3.1f]",
2788 fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
2789 Printf("Number of bins in centrality axis :\t%d", fCentAxis->GetNbins());
2790 printf("Centrality binning :\t");
2791 for (Int_t cBin = 1; cBin <= fCentAxis->GetNbins(); cBin++) {
2792 printf("%02d-%02d%% ", Int_t(fCentAxis->GetBinLowEdge(cBin)), Int_t(fCentAxis->GetBinUpEdge(cBin)));
2793 if (cBin == fCentAxis->GetNbins()) printf("\n");
2794 else if (cBin % 4 == 0) printf("\n\t\t\t\t\t");
2796 printf("Doing flow analysis for :\t");
2797 for (Int_t n = 2; n <= fMaxMoment; n++) printf("v%d ", n);
2799 TString type = "Standard QC{2} and QC{4} calculations.";
2800 if ((fFlowFlags & kTPC)) type.ReplaceAll(".", " with TPC tracks for reference.");
2801 if ((fFlowFlags & kEtaGap)) type = "QC{2} with a rapidity gap.";
2802 if ((fFlowFlags & k3Cor)) type = "QC{2} with 3 correlators.";
2803 Printf("QC calculation type :\t%s", type.Data());
2804 Printf("Symmetrize ref. flow wrt. eta = 0 :\t%s", ((fFlowFlags & kSymEta) ? "true" : "false"));
2805 Printf("Apply NUA correction terms :\t%s", ((fFlowFlags & kNUAcorr) ? "true" : "false"));
2806 Printf("Satellite vertex flag :\t%s", ((fFlowFlags & kSatVtx) ? "true" : "false"));
2807 Printf("FMD sigma cut: :\t%f", fFMDCut);
2808 Printf("SPD sigma cut: :\t%f", fSPDCut);
2809 if ((fFlowFlags & kEtaGap))
2810 Printf("Eta gap: :\t%f", fEtaGap);
2811 Printf("=======================================================");
2813 //_____________________________________________________________________
2814 const Char_t* AliForwardFlowTaskQC::GetQCType(UShort_t flags, Bool_t prependUS)
2817 // Get the type of the QC calculations
2818 // Used for naming of objects in the VertexBin class,
2819 // important to avoid memory problems when running multiple
2820 // initializations of the class with different setups
2823 // flags: Flow flags for type determination
2824 // prependUS: Prepend an underscore (_) to the name
2826 // Return: QC calculation type
2829 if ((flags & kStdQC)) type = "StdQC";
2830 else if ((flags & kEtaGap)) type = "EtaGap";
2831 else if ((flags & k3Cor)) type = "3Cor";
2832 else type = "UNKNOWN";
2833 if (prependUS) type.Prepend("_");
2834 if ((flags & kTPC)) type.Append("TPCTr");
2837 //_____________________________________________________________________
2838 TH1* AliForwardFlowTaskQC::CumuHistos::Get(Char_t t, Int_t n, UInt_t nua) const
2841 // Get histogram/profile for type t and moment n
2844 // t: type = 'r'/'d'
2849 if (n < 0) AliFatal(Form("CumuHistos out of range: (%c,%d)", t, n));
2853 if (t == 'r' || t == 'R') pos = n;
2854 else if (t == 'd' || t == 'D') pos = n;
2855 else if (t == 'a' || t == 'A') pos = 2*n;
2856 else if (t == 'b' || t == 'B') pos = 2*n+1;
2857 else AliFatal(Form("CumuHistos wrong type: %c", t));
2859 if (t == 'r' || t == 'R') {
2860 if (pos < fRefHists->GetEntries()) {
2861 h = (TH1*)fRefHists->At(pos);
2863 } else if (pos < fDiffHists->GetEntries()) {
2864 h = (TH1*)fDiffHists->At(pos);
2866 if (!h) AliFatal(Form("No hist found in list %c at pos %d", t, pos));
2870 //_____________________________________________________________________
2871 void AliForwardFlowTaskQC::CumuHistos::ConnectList(TString name, TList* l)
2874 // Connect an output list with this object
2878 // l: list to keep outputs in
2881 ref.ReplaceAll("Cumu","CumuRef");
2882 fRefHists = (TList*)l->FindObject(ref.Data());
2884 fRefHists = new TList();
2885 fRefHists->SetName(ref.Data());
2888 // Check that the list correspond to fMaxMoments
2889 if (fRefHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1))
2890 AliError("CumuHistos::ConnectList Wrong number of hists in ref list,"
2891 "you are doing something wrong!");
2893 TString diff = name;
2894 diff.ReplaceAll("Cumu","CumuDiff");
2895 fDiffHists = (TList*)l->FindObject(diff.Data());
2897 fDiffHists = new TList();
2898 fDiffHists->SetName(diff.Data());
2901 // Check that the list correspond to fMaxMoment
2902 if ((fDiffHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1)) &&
2903 (fDiffHists->GetEntries() != 2*(fMaxMoment-1.)*(fNUA+1)))
2904 AliError(Form("CumuHistos::ConnectList Wrong number of hists in diff list,"
2905 "you are doing something wrong! (%s)",name.Data()));
2909 //_____________________________________________________________________
2910 void AliForwardFlowTaskQC::CumuHistos::Add(TH1* h) const
2913 // Add a histogram to this objects lists
2916 // h: histogram/profile to add
2918 TString name = h->GetName();
2919 if (name.Contains("Ref")) {
2920 if (fRefHists) fRefHists->Add(h);
2921 else AliFatal("CumuHistos::Add() - fRefHists does not exist");
2922 // Check that the list correspond to fMaxMoments
2923 if (fRefHists->GetEntries() > (fNUA+1)*(fMaxMoment-1.))
2924 AliError("CumuHistos::Add wrong number of hists in ref list, "
2925 "you are doing something wrong!");
2927 else if (name.Contains("Diff")) {
2928 if (fDiffHists) fDiffHists->Add(h);
2929 else AliFatal("CumuHistos::Add() - fDiffHists does not exist");
2930 // Check that the list correspond to fMaxMoment
2931 if (fDiffHists->GetEntries() > 2*(fNUA+1)*(fMaxMoment-1.))
2932 AliError("CumuHistos::Add wrong number of hists in diff list, "
2933 "you are doing something wrong!");
2937 //_____________________________________________________________________
2938 Int_t AliForwardFlowTaskQC::CumuHistos::GetPos(Int_t n, UInt_t nua) const
2941 // Get position in list of moment n objects
2942 // To take care of different numbering schemes
2946 // nua: # of nua corrections applied
2948 // Return: position #
2950 if (n > fMaxMoment) return -1;
2951 else return (n-2)+nua*(fMaxMoment-1);
2953 //_____________________________________________________________________