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(0.), // 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(0.), // 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();
195 fESDTrackCuts->SetPtRange(0.2, 5.0);
196 fESDTrackCuts->SetEtaRange(-0.8, 0.8);
197 fESDTrackCuts->SetMinNClustersTPC(70);
201 PostData(1, fSumList);
203 //_____________________________________________________________________
204 void AliForwardFlowTaskQC::InitVertexBins()
207 // Init vertexbin objects for forward and central detectors, and add them to the lists
209 for (Int_t v = 1; v <= fVtxAxis->GetNbins(); v++) {
210 Int_t vL = Int_t(fVtxAxis->GetBinLowEdge(v));
211 Int_t vH = Int_t(fVtxAxis->GetBinUpEdge(v));
212 if ((fFlowFlags & kFMD)) {
213 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "FMD", fFlowFlags, fFMDCut, fEtaGap));
214 if (!(fFlowFlags & k3Cor)) fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-FMD", fFlowFlags|kNUAcorr|kSPD, fSPDCut, fEtaGap));
216 else if ((fFlowFlags & kVZERO)) {
217 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "VZERO", fFlowFlags, 0, fEtaGap));
218 if ((fFlowFlags & kEtaGap)) fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-VZERO", fFlowFlags|kNUAcorr|kSPD, fSPDCut, fEtaGap));
222 //_____________________________________________________________________
223 void AliForwardFlowTaskQC::InitHists()
226 // Init histograms and add vertex bin histograms to the sum list
229 fSumList = new TList();
230 fSumList->SetName("Sums");
231 fSumList->SetOwner();
233 if (!fVtxAxis) fVtxAxis = new TAxis(20, -10, 10);
234 fVtxAxis->SetName("VtxAxis");
235 if (!fCentAxis) fCentAxis = new TAxis(20, 0, 100);
236 fVtxAxis->SetName("CentAxis");
238 fHistCent = new TH1D("hCent", "Centralities", 100, 0, 100);
239 fHistVertexSel = new TH1D("hVertexSel", "Selected vertices", fVtxAxis->GetNbins(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
240 fHistEventSel = new TH1I("hEventSel", "Event Selection", kOK, 0.5, kOK+0.5);
241 fHistEventSel->GetXaxis()->SetBinLabel(kNoEvent, "No AOD event");
242 fHistEventSel->GetXaxis()->SetBinLabel(kNoForward, "No forward det");
243 fHistEventSel->GetXaxis()->SetBinLabel(kNoCentral, "No central det");
244 fHistEventSel->GetXaxis()->SetBinLabel(kNoTrigger, "Not triggered");
245 fHistEventSel->GetXaxis()->SetBinLabel(kNoCent, "No centrality");
246 fHistEventSel->GetXaxis()->SetBinLabel(kInvCent, "Centrality outside range");
247 fHistEventSel->GetXaxis()->SetBinLabel(kNoVtx, "No vertex");
248 fHistEventSel->GetXaxis()->SetBinLabel(kInvVtx, "Vtx outside range");
249 fHistEventSel->GetXaxis()->SetBinLabel(kOK, "OK!");
251 fHistFMDSPDCorr = new TH2D("hFMDSPDCorr", "hFMDSPCCorr", 200, 0., 20000., 200, 0, 7500);
253 TList* dList = new TList();
254 dList->SetName("Diagnostics");
255 dList->Add(fHistCent);
256 dList->Add(fHistVertexSel);
257 dList->Add(fHistEventSel);
258 dList->Add(fHistFMDSPDCorr);
259 fSumList->Add(dList);
261 fHistdNdedp3Cor = TH2D(Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)), Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)),
262 200, -4., 6., 20, 0., TMath::TwoPi());
263 if ((fFlowFlags & kVZERO)) {
264 Double_t bins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
265 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
266 fHistdNdedpV0 = TH2D(Form("hdNdedpv0%s", GetQCType(fFlowFlags)), Form("hdNdedpv0%s", GetQCType(fFlowFlags)),
267 11, -6, 6, 8, 0, TMath::TwoPi());
268 fHistdNdedpV0.GetXaxis()->Set(11, bins);
269 if ((fFlowFlags & k3Cor)) {
270 Double_t bins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
271 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
272 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
273 fHistdNdedp3Cor.GetXaxis()->Set(19, bins2);
274 fHistdNdedp3Cor.GetYaxis()->Set(8, 0., TMath::TwoPi());
278 TIter nextForward(&fBinsForward);
280 while ((bin = static_cast<VertexBin*>(nextForward()))) {
281 bin->AddOutput(fSumList, fCentAxis);
283 TIter nextCentral(&fBinsCentral);
284 while ((bin = static_cast<VertexBin*>(nextCentral()))) {
285 bin->AddOutput(fSumList, fCentAxis);
288 //_____________________________________________________________________
289 void AliForwardFlowTaskQC::UserExec(Option_t */*option*/)
292 // Calls the analyze function - called every event
298 // Reset data members
304 PostData(1, fSumList);
308 //_____________________________________________________________________
309 Bool_t AliForwardFlowTaskQC::Analyze()
312 // Load forward and central detector objects from aod tree and call the
313 // cumulants calculation for the correct vertex bin
315 // Return: true on success
319 fAOD = dynamic_cast<AliAODEvent*>(AliForwardUtil::GetAODEvent(this));
321 fHistEventSel->Fill(kNoEvent);
325 // Get detector objects
326 AliAODForwardMult* aodfmult = static_cast<AliAODForwardMult*>(fAOD->FindListObject("Forward"));
327 AliAODCentralMult* aodcmult = static_cast<AliAODCentralMult*>(fAOD->FindListObject("CentralClusters"));
328 AliVVZERO* vzero = GetVZERO();
329 if ((fFlowFlags & kVZERO)) {
331 fHistdNdedpV0.Reset();
332 FillVZEROHist(vzero);
336 // We make sure that the necessary forward object is there
337 if ((fFlowFlags & kFMD) && !aodfmult) {
338 fHistEventSel->Fill(kNoForward);
341 else if ((fFlowFlags & kVZERO) && !vzero) {
342 fHistEventSel->Fill(kNoForward);
345 if (!aodcmult) fHistEventSel->Fill(kNoCentral);
347 // Check event for triggers, get centrality, vtx etc.
348 if (!CheckEvent(aodfmult)) return kFALSE;
349 Int_t vtx = fVtxAxis->FindBin(fVtx)-1;
351 // Then we assign a reference to the forward histogram of interest
352 TH2D& forwarddNdedp = ((fFlowFlags & kFMD) ? aodfmult->GetHistogram() : fHistdNdedpV0);
353 TH2D& spddNdedp = aodcmult->GetHistogram();
354 if ((fFlowFlags & kStdQC)) {
355 FillVtxBinList(fBinsForward, forwarddNdedp, vtx);
356 } else if ((fFlowFlags & kEtaGap)) {
357 FillVtxBinListEtaGap(fBinsForward, forwarddNdedp, forwarddNdedp, vtx);
359 // At the moment only clusters are supported for the central region (some day add tracks?)
360 // So no extra checks necessary
362 if ((fFlowFlags & kStdQC)) {
363 FillVtxBinList(fBinsCentral, spddNdedp, vtx);
364 } else if ((fFlowFlags & kEtaGap)) {
365 FillVtxBinListEtaGap(fBinsCentral, forwarddNdedp, spddNdedp, vtx);
366 } else if ((fFlowFlags & k3Cor)) {
367 FillVtxBinList3Cor(fBinsForward, spddNdedp, forwarddNdedp, vtx);
371 Double_t totForward = forwarddNdedp.Integral(1, forwarddNdedp.GetNbinsX(), 1, forwarddNdedp.GetNbinsY());
372 Double_t totSPD = spddNdedp.Integral(1, spddNdedp.GetNbinsX(), 1, spddNdedp.GetNbinsY());
373 fHistFMDSPDCorr->Fill(totForward, totSPD);
379 //_____________________________________________________________________
380 void AliForwardFlowTaskQC::FillVtxBinList(const TList& list, TH2D& h, Int_t vtx, UShort_t flags) const
383 // Loops over list of VtxBins, fills hists of bins for current vertex
384 // and runs analysis on those bins
387 // list: list of VtxBins
388 // h: dN/detadphi histogram
389 // vtx: current vertex bin
390 // flags: extra flags to handle calculations.
392 // Note: The while loop is used in this function and the next 2 for historical reasons,
393 // as originally each moment had it's own VertexBin object.
396 Int_t nVtxBins = fVtxAxis->GetNbins();
398 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
399 // If no tracks do things normally
400 if (!(fFlowFlags & kTPC) && !bin->FillHists(h, fCent, kFillBoth|flags|kReset)) return;
401 // if tracks things are more complicated
402 else if ((fFlowFlags & kTPC)) {
403 TObjArray* trList = GetTracks();
405 Bool_t useEvent = bin->FillTracks(trList, kFillRef|kReset|flags);
406 // If esd input trList is a new object owned by this task and should be cleaned up
407 if (AliForwardUtil::CheckForAOD() == 2) delete trList;
408 if (!useEvent) return;
409 if (!bin->FillHists(h, fCent, kFillDiff|kReset|flags)) return;
411 bin->CumulantsAccumulate(fCent);
417 //_____________________________________________________________________
418 void AliForwardFlowTaskQC::FillVtxBinListEtaGap(const TList& list, TH2D& href,
419 TH2D& hdiff, Int_t vtx, UShort_t flags) const
422 // Loops over list of VtxBins, fills hists of bins for current vertex
423 // and runs analysis on those bins
426 // list: list of VtxBins
427 // href: dN/detadphi histogram for ref. flow
428 // hdiff: dN/detadphi histogram for diff. flow
429 // vBin: current vertex bin
430 // flags: extra flags to handle calculations.
434 Int_t nVtxBins = fVtxAxis->GetNbins();
436 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
437 if (!bin->FillHists(href, fCent, kFillRef|flags|kReset)) return;
438 bin->FillHists(hdiff, fCent, kFillDiff|kReset);
439 bin->CumulantsAccumulate(fCent);
445 //_____________________________________________________________________
446 void AliForwardFlowTaskQC::FillVtxBinList3Cor(const TList& list, TH2D& hcent,
447 TH2D& hfwd, Int_t vtx, UShort_t flags)
450 // Loops over list of VtxBins, fills hists of bins for current vertex
451 // and runs analysis on those bins
454 // list: list of VtxBins
455 // hcent: dN/detadphi histogram for central coverage
456 // hfwd: dN/detadphi histogram for forward coverage
457 // vBin: current vertex bin
458 // flags: extra flags to handle calculations.
462 Int_t nVtxBins = fVtxAxis->GetNbins();
464 TH2D& h = CombineHists(hcent, hfwd);
466 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
467 if (!bin->FillHists(h, fCent, kFillBoth|flags|kReset)) return;
468 bin->CumulantsAccumulate3Cor(fCent);
474 //_____________________________________________________________________
475 TH2D& AliForwardFlowTaskQC::CombineHists(TH2D& hcent, TH2D& hfwd)
478 // Combines a forward and central d^2N/detadphi histogram.
479 // At some point it might need a flag to choose which histogram gets
480 // priority when there is an overlap, at the moment the average is chosen
483 // hcent: Central barrel detector
484 // hfwd: Forward detector
486 // Return: reference to combined hist
489 // If hists are the same (MC input) don't do anything
490 if (&hcent == &hfwd) return hcent;
492 fHistdNdedp3Cor.Reset();
494 if ((fFlowFlags & kFMD)) {
495 for (Int_t e = 1; e <= fHistdNdedp3Cor.GetNbinsX(); e++) {
496 Double_t eta = fHistdNdedp3Cor.GetXaxis()->GetBinCenter(e);
497 Bool_t fwdCov = (hfwd.GetBinContent(e, 0) != 0);
498 Bool_t centCov = (hcent.GetBinContent(e, 0) != 0);
499 if (!fwdCov && !centCov) continue;
500 else fHistdNdedp3Cor.SetBinContent(e, 0, 1);
501 for (Int_t p = 1; p <= fHistdNdedp3Cor.GetNbinsY(); p++) {
502 Double_t phi = fHistdNdedp3Cor.GetYaxis()->GetBinCenter(p);
506 cont += hfwd.GetBinContent(e, p);
510 cont += hcent.GetBinContent(e, p);
513 if (cont == 0 || n == 0) continue;
515 fHistdNdedp3Cor.Fill(eta, phi, cont);
518 // VZERO, SPD input, here we do not average but cut to avoid
519 // (too much) overlap.
520 } else if ((fFlowFlags & kVZERO)) {
522 for (Int_t eV = 1; eV <= hfwd.GetNbinsX(); eV++) {
523 Double_t eta = hfwd.GetXaxis()->GetBinLowEdge(eV)+0.1;
524 if (hfwd.GetBinContent(eV, 0) == 0) continue;
526 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
527 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
529 for (Int_t p = 1; p <= hfwd.GetNbinsY(); p++) {
530 Double_t phi = hfwd.GetYaxis()->GetBinCenter(p);
531 Double_t cont = hfwd.GetBinContent(eV, p);
532 fHistdNdedp3Cor.Fill(eta, phi, cont);
536 Int_t eSs = hcent.GetXaxis()->FindBin(-1.99);
537 Int_t eSe = hcent.GetXaxis()->FindBin(1.99);
538 for (Int_t eS = eSs; eS <= eSe; eS++) {
539 Double_t eta = hcent.GetXaxis()->GetBinCenter(eS);
540 if (hcent.GetBinContent(eS, 0) == 0) continue;
542 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
543 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
545 for (Int_t p = 1; p <= hcent.GetNbinsY(); p++) {
546 Double_t phi = hcent.GetYaxis()->GetBinCenter(p);
547 Double_t cont = hcent.GetBinContent(eS, p);
548 fHistdNdedp3Cor.Fill(eta, phi, cont);
552 return fHistdNdedp3Cor;
554 //_____________________________________________________________________
555 TObjArray* AliForwardFlowTaskQC::GetTracks() const
558 // Get TPC tracks to use for reference flow.
560 // Return: TObjArray with tracks
562 TObjArray* trList = 0;
564 UShort_t input = AliForwardUtil::CheckForAOD();
566 // If AOD input, simply get the track array from the event
567 case 1: trList = static_cast<TObjArray*>(fAOD->GetTracks());
570 // If ESD input get event, apply track cuts
571 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
573 // Warning! trList is now a new array, we need to delete it after use
574 // this is not a very good implementation!
575 trList = fESDTrackCuts->GetAcceptedTracks(esd, kTRUE);
578 default: AliFatal("Neither ESD or AOD input. This should never happen");
583 //_____________________________________________________________________
584 void AliForwardFlowTaskQC::Terminate(Option_t */*option*/)
587 // Calls the finalize function, done at the end of the analysis
593 // Make sure pointers are set to the correct lists
594 fSumList = dynamic_cast<TList*> (GetOutputData(1));
596 AliError("Could not retrieve TList fSumList");
600 fOutputList = new TList();
601 fOutputList->SetName("Results");
602 fOutputList->SetOwner();
604 if ((fFlowFlags & kEtaGap) || (fFlowFlags & kTPC)) {
605 TParameter<Double_t>* etaGap = new TParameter<Double_t>("EtaGap", fEtaGap);
606 fOutputList->Add(etaGap);
608 // We only add axes in terminate, as TAxis object do not merge well,
609 // and so we get a mess when running on the grid if we put them in the sum list...
610 fVtxAxis->SetName("VtxAxis");
611 fOutputList->Add(fVtxAxis);
612 fCentAxis->SetName("CentAxis");
613 fOutputList->Add(fCentAxis);
615 // Run finalize on VertexBins
618 // Loop over output to get dN/deta hists - used for diagnostics
619 TIter next(fOutputList);
624 while ((o = next())) {
626 if (name.Contains("dNdeta")) {
627 dNdeta = dynamic_cast<TH2D*>(o);
628 name.ReplaceAll("dNdeta", "cent");
629 name.ReplaceAll("Ref", "");
630 name.ReplaceAll("Diff", "");
631 cent = dynamic_cast<TH1D*>(fOutputList->FindObject(name.Data()));
632 if (!dNdeta || !cent) continue;
633 for (Int_t cBin = 1; cBin <= dNdeta->GetNbinsY(); cBin++) {
634 Double_t nEvents = cent->GetBinContent(cBin);
635 if (nEvents == 0) continue;
636 for (Int_t eBin = 1; eBin <= dNdeta->GetNbinsX(); eBin++) {
637 dNdeta->SetBinContent(eBin, cBin, dNdeta->GetBinContent(eBin, cBin)/nEvents);
638 dNdeta->SetBinError(eBin, cBin, dNdeta->GetBinError(eBin, cBin)/nEvents);
644 // Loop over output and make 1D projections for fast look at results
645 MakeCentralityHists(fOutputList);
646 TList* vtxList = (TList*)fOutputList->FindObject("vtxList");
647 if (vtxList) MakeCentralityHists(vtxList);
648 TList* nuaList = (TList*)fOutputList->FindObject("NUATerms");
649 TIter nextNua(nuaList);
652 while ((o = nextNua())) {
653 if (!(h = dynamic_cast<TH2D*>(o))) continue;
654 Double_t evts = h->GetBinContent(0, 0);
655 if (evts != 0) h->Scale(1./evts);
657 if (nuaList) MakeCentralityHists(nuaList);
659 PostData(2, fOutputList);
663 //_____________________________________________________________________
664 void AliForwardFlowTaskQC::Finalize()
667 // Finalize command, called by Terminate()
670 // Reinitiate vertex bins if Terminate is called separately!
671 if (fBinsForward.GetEntries() == 0) InitVertexBins();
673 // Iterate over all vertex bins objects and finalize cumulants
675 EndVtxBinList(fBinsForward);
676 EndVtxBinList(fBinsCentral);
680 //_____________________________________________________________________
681 void AliForwardFlowTaskQC::EndVtxBinList(const TList& list) const
684 // Loop over VertexBin list and call terminate on each
687 // list: VertexBin list
691 while ((bin = static_cast<VertexBin*>(next()))) {
692 bin->CumulantsTerminate(fSumList, fOutputList);
696 // _____________________________________________________________________
697 void AliForwardFlowTaskQC::MakeCentralityHists(TList* list) const
700 // Loop over a list containing a TH2D with flow results
701 // and project to TH1's in specific centrality bins
704 // list: Flow results list
710 TIter nextHist(list);
711 while ((helper = dynamic_cast<TObject*>(nextHist()))) {
712 if (!(hist2D = dynamic_cast<TH2D*>(helper))) continue;
713 for (Int_t cBin = 1; cBin <= hist2D->GetNbinsY(); cBin++) {
714 Int_t cMin = Int_t(hist2D->GetYaxis()->GetBinLowEdge(cBin));
715 Int_t cMax = Int_t(hist2D->GetYaxis()->GetBinUpEdge(cBin));
716 TString name = Form("cent_%d-%d", cMin, cMax);
717 centList = (TList*)list->FindObject(name.Data());
719 centList = new TList();
720 centList->SetName(name.Data());
723 hist1D = hist2D->ProjectionX(Form("%s_%s", hist2D->GetName(), name.Data()),
725 hist1D->SetTitle(hist1D->GetName());
726 centList->Add(hist1D);
730 // _____________________________________________________________________
731 Bool_t AliForwardFlowTaskQC::CheckEvent(const AliAODForwardMult* aodfm)
734 // Function to check that an AOD event meets the cuts
737 // AliAODForwardMult: forward mult object with trigger and vertex info
739 // Return: false if there is no trigger or if the centrality or vertex
740 // is out of range. Otherwise true.
743 // First check for trigger
744 if (!CheckTrigger(aodfm)) {
745 fHistEventSel->Fill(kNoTrigger);
749 // Then check for centrality
750 if (!GetCentrality(aodfm)) {
754 // And finally check for vertex
755 if (!GetVertex(aodfm)) {
759 // Ev. accepted - filling diag. hists
760 fHistCent->Fill(fCent);
761 fHistVertexSel->Fill(fVtx);
762 fHistEventSel->Fill(kOK);
766 // _____________________________________________________________________
767 Bool_t AliForwardFlowTaskQC::CheckTrigger(const AliAODForwardMult* aodfm) const
770 // Function to look for a trigger string in the event.
771 // First check for info in forward mult object, if not there, use the AOD header
774 // AliAODForwardMult: forward mult object with trigger and vertex info
776 // Return: true if offline trigger is present
778 if (aodfm) return aodfm->IsTriggerBits(AliAODForwardMult::kOffline);
779 // this may need to be changed for 2011 data to handle kCentral and so on...
780 else return (((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))
781 ->IsEventSelected() & AliVEvent::kMB);
783 // _____________________________________________________________________
784 Bool_t AliForwardFlowTaskQC::GetCentrality(const AliAODForwardMult* aodfm)
787 // Function to look get centrality of the event.
788 // First check for info in forward mult object, if not there, use the AOD header
791 // AliAODForwardMult: forward mult object with trigger and vertex info
793 // Return: true if centrality determination is present
796 if (aodfm->HasCentrality()) {
797 fCent = (Double_t)aodfm->GetCentrality();
798 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
799 fHistEventSel->Fill(kInvCent);
805 fHistEventSel->Fill(kNoCent);
809 AliCentrality* aodCent = fAOD->GetCentrality();
811 fCent = (Double_t)aodCent->GetCentralityPercentile("V0M");
812 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
813 fHistEventSel->Fill(kInvCent);
819 fHistEventSel->Fill(kNoCent);
824 //_____________________________________________________________________
825 Bool_t AliForwardFlowTaskQC::GetVertex(const AliAODForwardMult* aodfm)
828 // Function to look for vertex determination in the event.
829 // First check for info in forward mult object, if not there, use the AOD header
832 // AliAODForwardMult: forward mult object with trigger and vertex info
834 // Return: true if vertex is determined
837 if (aodfm->HasIpZ()) {
838 fVtx = aodfm->GetIpZ();
839 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
840 fHistEventSel->Fill(kInvVtx);
845 fHistEventSel->Fill(kNoVtx);
850 AliAODVertex* aodVtx = fAOD->GetPrimaryVertex();
852 fVtx = aodVtx->GetZ();
853 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
854 fHistEventSel->Fill(kInvVtx);
859 fHistEventSel->Fill(kNoVtx);
865 // _____________________________________________________________________
866 AliVVZERO* AliForwardFlowTaskQC::GetVZERO() const
868 AliVVZERO* vzero = 0;
870 UShort_t input = AliForwardUtil::CheckForAOD();
872 // If AOD input, simply get the track array from the event
873 case 1: vzero = (AliVVZERO*)fAOD->GetVZEROData();
876 // If ESD input get event, apply track cuts
877 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
879 vzero = (AliVVZERO*)esd->GetVZEROData();
882 default: AliFatal("Neither ESD or AOD input. This should never happen");
887 // _____________________________________________________________________
888 void AliForwardFlowTaskQC::FillVZEROHist(AliVVZERO* vzero)
891 // Loops over VZERO data object and fill up d^2N/detadphi histogram for flow analysis
894 // vzero: VZERO AOD data object
899 // Sort of right for 2010 data, do not use for 2011!
900 Double_t eq[64] = { 1.43536, 1.45727, 1.44993, 1.30051, 1.17425, 1.2335, 1.22247, 1.14362,
901 1.14647, 1.25208, 1.17681, 1.21642, 1.16604, 1.05532, 1.03212, 1.1032,
902 1.22941, 1.36986, 1.14652, 1.20056, 0.927086, 1.10809, 1.03343, 1.29472,
903 1.21204, 1.29217, 1.2003, 2.10382, 1.28513, 1.40558, 1.25784, 1.21848,
904 0.475162, 0.50421, 0.503617, 0.512471, 0.515276, 0.39831, 0.415199, 0.444664,
905 0.521922, 0.785915, 0.703658, 0.832479, 0.77461, 0.73129, 0.778697, 0.710265,
906 0.89686, 0.967688, 0.974225, 0.873445, 0.811096, 0.828493, 0.889609, 0.586056,
907 1.15877, 0.954656, 0.914557, 0.979028, 1.04907, 0.748518, 0.928043, 0.98175 };
908 for (Int_t i = 0; i < 64; i++) {
911 bin = (ring < 5 ? ring+1 : 15-ring);
912 eta = fHistdNdedpV0.GetXaxis()->GetBinCenter(bin);
913 fHistdNdedpV0.SetBinContent(bin, 0, 1);
915 Float_t amp = vzero->GetMultiplicity(i);
917 Double_t phi = TMath::Pi()/8.+TMath::TwoPi()*i/8.;
918 while (phi > TMath::TwoPi()) phi -= TMath::TwoPi();
919 fHistdNdedpV0.Fill(eta, phi, amp);
922 //_____________________________________________________________________
923 AliForwardFlowTaskQC::VertexBin::VertexBin()
925 fMaxMoment(0), // Max flow moment for this vertexbin
926 fVzMin(0), // Vertex z-coordinate min [cm]
927 fVzMax(0), // Vertex z-coordinate max [cm]
928 fType(), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
929 fFlags(0), // Flow flags
930 fSigmaCut(-1), // Sigma cut to remove outlier events
931 fEtaGap(-1), // Eta gap value
932 fEtaLims(), // Limits for binning in 3Cor method
933 fCumuRef(), // Histogram for reference flow
934 fCumuDiff(), // Histogram for differential flow
935 fCumuHists(0,0), // CumuHists object for keeping track of results
936 fCumuNUARef(), // Histogram for ref NUA terms
937 fCumuNUADiff(), // Histogram for diff NUA terms
938 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
939 fdNdedpDiffAcc(),// Diagnostics histogram for acc. maps
940 fOutliers(), // Histogram for sigma distribution
941 fDebug() // Debug level
944 // Default constructor
947 //_____________________________________________________________________
948 AliForwardFlowTaskQC::VertexBin::VertexBin(Int_t vLow, Int_t vHigh,
949 UShort_t moment, TString name,
950 UShort_t flags, Double_t cut,
953 fMaxMoment(moment), // Max flow moment for this vertexbin
954 fVzMin(vLow), // Vertex z-coordinate min [cm]
955 fVzMax(vHigh), // Vertex z-coordinate max [cm]
956 fType(name), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
957 fFlags(flags), // Flow flags
958 fSigmaCut(cut), // Sigma cut to remove outlier events
959 fEtaGap(etaGap), // Eta gap value
960 fEtaLims(), // Limits for binning in 3Cor method
961 fCumuRef(), // Histogram for reference flow
962 fCumuDiff(), // Histogram for differential flow
963 fCumuHists(moment,0),// CumuHists object for keeping track of results
964 fCumuNUARef(), // Histogram for ref NUA terms
965 fCumuNUADiff(), // Histogram for diff NUA terms
966 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
967 fdNdedpDiffAcc(), // Diagnostics histogram for acc. maps
968 fOutliers(), // Histogram for sigma distribution
969 fDebug(0) // Debug level
975 // vLow: min z-coordinate
976 // vHigh: max z-coordinate
977 // moment: max flow moment
978 // name: data type name (FMD/SPD/FMDTR/SPDTR/MC)
981 // etaGap: eta-gap value
985 SetName(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
986 SetTitle(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
988 fDebug = AliAnalysisManager::GetAnalysisManager()->GetDebugLevel();
989 if (fDebug > 0) Printf("AliForwardFlowTaskQC::VertexBin()\tDebugMode: %d", fDebug);
991 // Set limits for 3 correlator method
992 if ((fFlags & kFMD)) {
999 } else if ((fFlags & kVZERO)) {
1008 //_____________________________________________________________________
1009 AliForwardFlowTaskQC::VertexBin&
1010 AliForwardFlowTaskQC::VertexBin::operator=(const AliForwardFlowTaskQC::VertexBin& o)
1013 // Assignment operator
1016 // o: AliForwardFlowTaskQC::VertexBin
1018 if (&o == this) return *this;
1019 fMaxMoment = o.fMaxMoment;
1024 fSigmaCut = o.fSigmaCut;
1025 fEtaGap = o.fEtaGap;
1026 fCumuRef = o.fCumuRef;
1027 fCumuDiff = o.fCumuDiff;
1028 fCumuHists = o.fCumuHists;
1029 fCumuNUARef = o.fCumuNUARef;
1030 fCumuNUADiff = o.fCumuNUADiff;
1031 fdNdedpRefAcc = o.fdNdedpRefAcc;
1032 fdNdedpDiffAcc = o.fdNdedpDiffAcc;
1033 fOutliers = o.fOutliers;
1035 for (UInt_t i = 0; i < sizeof(fEtaLims)/sizeof(Double_t); i++) fEtaLims[i] = o.fEtaLims[i];
1039 //_____________________________________________________________________
1040 void AliForwardFlowTaskQC::VertexBin::AddOutput(TList* outputlist, TAxis* centAxis)
1043 // Add histograms to outputlist
1046 // outputlist: list of histograms
1047 // centAxis: centrality axis
1050 // First we try to find an outputlist for this vertexbin
1051 TList* list = (TList*)outputlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1052 // If it doesn't exist we make one
1055 list->SetName(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1056 outputlist->Add(list);
1059 // Get bin numbers and binning defined
1060 Int_t nHBins = GetBinNumberSin();
1061 Int_t nEtaBins = 48;
1062 if ((fFlags & k3Cor)) {
1063 if ((fFlags & kFMD)) nEtaBins = 24;
1064 else if ((fFlags & kVZERO)) nEtaBins = 19;
1066 else if ((fFlags & kVZERO) && (fFlags & kEtaGap)) nEtaBins = 19;
1067 else if ((fFlags & kVZERO)) nEtaBins = 11;
1069 Double_t vzeroBins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
1070 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
1071 Double_t vzeroBins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
1072 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
1073 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
1075 Int_t nRefBins = nEtaBins; // needs to be something as default
1076 if ((fFlags & kStdQC)) {
1077 if ((fFlags & kSymEta) && !((fFlags & kTPC) && (fFlags & kSPD))) nRefBins = 1;
1079 } else if ((fFlags & kEtaGap )) {
1081 } else if ((fFlags & k3Cor)) {
1085 // We initiate the reference histogram
1086 fCumuRef = new TH2D(Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1087 Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1089 nHBins, 0.5, nHBins+0.5);
1090 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuRef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1091 SetupNUALabels(fCumuRef->GetYaxis());
1092 list->Add(fCumuRef);
1093 // We initiate the differential histogram
1094 fCumuDiff = new TH2D(Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1095 Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1096 nEtaBins, -6., 6., nHBins, 0.5, nHBins+0.5);
1097 if ((fFlags & kVZERO)) {
1098 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1099 fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1100 else fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins);
1102 SetupNUALabels(fCumuDiff->GetYaxis());
1103 list->Add(fCumuDiff);
1105 // Cumulants sum hists
1106 Int_t cBins = centAxis->GetNbins();
1107 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1109 Int_t nC2Bins = ((fFlags & kEtaGap) || (fFlags & k3Cor) ? kW2 : k3pWeight);
1110 Int_t nC4Bins = ((fFlags & kEtaGap) ? kW2 : ((fFlags & k3Cor) ? kW4 : kSinphi1phi2phi3p));
1111 for (Int_t n = 2; n <= fMaxMoment; n++) {
1112 // Initiate the ref cumulant sum histogram
1113 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1114 Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1116 cBins, 0., 100., nC2Bins, 0.5, nC2Bins+0.5);
1117 if ((fFlags & kVZERO) && (fFlags & k3Cor)) cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1118 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1119 fCumuHists.Add(cumuHist);
1120 // Initiate the diff cumulant sum histogram
1121 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1122 Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1123 nEtaBins, -6., 6., cBins, 0., 100., nC4Bins, 0.5, nC4Bins+0.5);
1124 if ((fFlags & kVZERO)) {
1125 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1126 cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1127 else cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins);
1129 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1130 fCumuHists.Add(cumuHist);
1133 // Common NUA histograms
1134 fCumuNUARef = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1135 Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1137 cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1138 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuNUARef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1139 fCumuNUARef->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1140 SetupNUALabels(fCumuNUARef->GetZaxis());
1141 fCumuNUARef->Sumw2();
1142 list->Add(fCumuNUARef);
1144 fCumuNUADiff = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1145 Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1146 nEtaBins, -6., 6., cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1147 if ((fFlags & kVZERO)) {
1148 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1149 fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1150 else fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins);
1152 fCumuNUADiff->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1153 SetupNUALabels(fCumuNUADiff->GetZaxis());
1154 fCumuNUADiff->Sumw2();
1155 list->Add(fCumuNUADiff);
1157 // We create diagnostic histograms.
1158 TList* dList = (TList*)outputlist->FindObject("Diagnostics");
1159 if (!dList) AliFatal("No diagnostics list found");
1162 Int_t nPhiBins = ((fFlags & kFMD) ? 20 : 8);
1163 fdNdedpRefAcc = new TH2F(Form("h%sdNdedpRefAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1164 Form("%s reference flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
1165 nEtaBins, -6., 6., nPhiBins, 0, TMath::TwoPi());
1166 if ((fFlags & kVZERO)) {
1167 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1168 fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1169 else fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
1171 dList->Add(fdNdedpRefAcc);
1173 fdNdedpDiffAcc = new TH2F(Form("h%sdNdedpDiffAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1174 Form("%s differential flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
1175 nEtaBins, -6., 6., nPhiBins, 0, TMath::TwoPi());
1176 if ((fFlags & kVZERO)) {
1177 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1178 fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1179 else fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
1181 dList->Add(fdNdedpDiffAcc);
1183 fOutliers = new TH2F(Form("hOutliers_%s_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1184 Form("Maximum #sigma from mean N_{ch} pr. bin - %s, %d < v_{z} < %d",
1185 fType.Data(), fVzMin, fVzMax),
1186 20, 0., 100., 500, 0., ((fFlags & kMC) ? 15. : 5.));
1187 dList->Add(fOutliers);
1191 //_____________________________________________________________________
1192 Bool_t AliForwardFlowTaskQC::VertexBin::FillHists(TH2D& dNdetadphi, Double_t cent, UShort_t mode)
1195 // Fill reference and differential eta-histograms
1198 // dNdetadphi: 2D histogram with input data
1200 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
1202 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1203 Bool_t useEvent = kTRUE;
1205 // Fist we reset histograms
1206 if ((mode & kReset)) {
1207 if ((mode & kFillRef)) fCumuRef->Reset();
1208 if ((mode & kFillDiff)) fCumuDiff->Reset();
1211 // Then we loop over the input and calculate sum cos(k*n*phi)
1212 // and fill it in the reference and differential histograms
1214 Double_t limit = 9999.;
1215 for (Int_t etaBin = 1; etaBin <= dNdetadphi.GetNbinsX(); etaBin++) {
1216 Double_t eta = dNdetadphi.GetXaxis()->GetBinCenter(etaBin);
1217 // Numbers to cut away bad events
1218 Double_t runAvg = 0;
1221 Double_t avgSqr = 0;
1222 for (Int_t phiBin = 0; phiBin <= dNdetadphi.GetNbinsY(); phiBin++) {
1223 // Check for acceptance
1225 if (dNdetadphi.GetBinContent(etaBin, 0) == 0) break;
1226 // Central limit for eta gap break for reference flow
1227 if ((fFlags & kEtaGap) && (mode & kFillRef) &&
1228 TMath::Abs(eta) < fEtaGap) break;
1229 // Backward and forward eta gap break for reference flow
1230 if ((fFlags & kEtaGap) && (mode & kFillRef) && TMath::Abs(eta) > TMath::Abs(limit)) break;
1231 if ((fFlags & kStdQC) && (fFlags & kMC)) {
1232 if (!(fFlags & kSPD) && TMath::Abs(eta) < 1.75) break;
1233 if ((fFlags & kSPD) && TMath::Abs(eta) > 2.00) break;
1235 if (limit > 1e3) limit = dNdetadphi.GetXaxis()->GetBinLowEdge(etaBin);
1237 } // End of phiBin == 0
1238 Double_t phi = dNdetadphi.GetYaxis()->GetBinCenter(phiBin);
1239 Double_t weight = dNdetadphi.GetBinContent(etaBin, phiBin);
1241 // We calculate the average Nch per. bin
1242 avgSqr += weight*weight;
1245 if (weight == 0) continue;
1246 if (weight > max) max = weight;
1248 // Fill into Cos() and Sin() hists
1249 if ((mode & kFillRef)) {
1250 fCumuRef->Fill(eta, 0., weight);// mult goes in underflowbin - no visual, but not needed?
1251 fdNdedpRefAcc->Fill(eta, phi, weight);
1253 if ((mode & kFillDiff)) {
1254 fCumuDiff->Fill(eta, 0., weight);
1255 fdNdedpDiffAcc->Fill(eta, phi, weight);
1257 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1258 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1259 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1260 Double_t cosnPhi = weight*TMath::Cos(n*phi);
1261 Double_t sinnPhi = weight*TMath::Sin(n*phi);
1263 if ((mode & kFillRef)) {
1264 fCumuRef->Fill(eta, cosBin, cosnPhi);
1265 fCumuRef->Fill(eta, sinBin, sinnPhi);
1268 if ((mode & kFillDiff)) {
1269 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1270 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1272 } // End of NUA loop
1273 } // End of phi loop
1274 // Outlier cut calculations
1278 Double_t stdev = (nInAvg > 1 ? TMath::Sqrt(nInAvg/(nInAvg-1))*TMath::Sqrt(avgSqr - runAvg*runAvg) : 0);
1279 Double_t nSigma = (stdev == 0 ? 0 : (max-runAvg)/stdev);
1280 if (fSigmaCut > 0. && nSigma >= fSigmaCut && cent < 60) nBadBins++;
1282 fOutliers->Fill(cent, nSigma);
1283 // We still finish the loop, for fOutliers to make sense,
1284 // but we do no keep the event for analysis
1285 if (nBadBins > 3) useEvent = kFALSE;
1291 //_____________________________________________________________________
1292 Bool_t AliForwardFlowTaskQC::VertexBin::FillTracks(TObjArray* trList, UShort_t mode)
1295 // Fill reference and differential eta-histograms
1298 // trList: list of tracks
1299 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
1301 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1303 // Fist we reset histograms
1304 if ((mode & kReset)) {
1305 if ((mode & kFillRef)) fCumuRef->Reset();
1306 if ((mode & kFillDiff)) fCumuDiff->Reset();
1309 UShort_t input = AliForwardUtil::CheckForAOD();
1310 // Then we loop over the input and calculate sum cos(k*n*phi)
1311 // and fill it in the reference and differential histograms
1312 Int_t nTr = trList->GetEntries();
1313 if (nTr == 0) return kFALSE;
1315 AliAODTrack* aodTr = 0;
1316 // Cuts for AOD tracks (have already been applied to ESD tracks)
1317 const Double_t pTMin = 0.2, pTMax = 5., etaMin = -0.8, etaMax = 0.8, minNCl = 70;
1318 for (Int_t i = 0; i < nTr; i++) { // track loop
1319 tr = (AliVTrack*)trList->At(i);
1321 if (input == 1) { // If AOD input
1322 // A dynamic cast would be more safe here, but this is faster...
1323 aodTr = (AliAODTrack*)tr;
1324 if (aodTr->GetID() > -1) continue;
1325 if (!aodTr->TestFilterBit(128) || !aodTr->Pt() > pTMax || aodTr->Pt() < pTMin ||
1326 aodTr->Eta() > etaMax || aodTr->Eta() < etaMin || aodTr->GetTPCNcls() < minNCl) continue;
1329 Double_t eta = tr->Eta();
1330 if ((fFlags & kSPD) && TMath::Abs(eta) < fEtaGap) continue;
1331 Double_t phi = tr->Phi();
1332 if ((mode & kFillRef)) {
1333 fCumuRef->Fill(eta, 0.);// mult goes in underflowbin - no visual, but not needed?
1334 fdNdedpRefAcc->Fill(eta, phi);
1336 if ((mode & kFillDiff)) {
1337 fCumuDiff->Fill(eta, 0);
1338 fdNdedpDiffAcc->Fill(eta, phi);
1340 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1341 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1342 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1343 Double_t cosnPhi = TMath::Cos(n*phi);
1344 Double_t sinnPhi = TMath::Sin(n*phi);
1346 if ((mode & kFillRef)) {
1347 fCumuRef->Fill(eta, cosBin, cosnPhi);
1348 fCumuRef->Fill(eta, sinBin, sinnPhi);
1351 if ((mode & kFillDiff)) {
1352 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1353 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1355 } // End of NUA loop
1356 } // End of track loop
1359 //_____________________________________________________________________
1360 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate(Double_t cent)
1363 // Calculate the Q cumulant up to order fMaxMoment
1366 // cent: centrality of event
1368 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1370 // Fill out NUA hists
1371 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1372 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1373 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1374 if ((fFlags & kTPC) && (fFlags && kSPD)) eta = -eta;
1375 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1376 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1379 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1380 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1381 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1382 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1383 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1387 // We create the objects needed for the analysis
1390 // For each n we loop over the hists
1391 for (Int_t n = 2; n <= fMaxMoment; n++) {
1392 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1393 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1394 Int_t prevRefEtaBin = 0;
1396 // Per mom. quantities
1397 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1398 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1399 Double_t dQ2nReA = 0, dQ2nImA = 0;
1400 Double_t two = 0, w2 = 0, four = 0, w4 = 0;
1401 Double_t cosPhi1Phi2 = 0, cosPhi1Phi2Phi3m = 0;
1402 Double_t sinPhi1Phi2 = 0, sinPhi1Phi2Phi3m = 0;
1403 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1404 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1405 Double_t refEta = eta;
1406 if ((fFlags & kTPC) && (fFlags && kSPD)) refEta = -eta;
1407 Int_t refEtaBinA = fCumuRef->GetXaxis()->FindBin(refEta);
1408 if ((fFlags & kEtaGap)) refEta = -eta;
1409 Int_t refEtaBinB = fCumuRef->GetXaxis()->FindBin(refEta);
1410 if (refEtaBinA != prevRefEtaBin) {
1411 prevRefEtaBin = refEtaBinA;
1413 multA = fCumuRef->GetBinContent(refEtaBinA, 0);
1414 dQnReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n));
1415 dQnImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n));
1416 dQ2nReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n*2));
1417 dQ2nImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n*2));
1419 multB = fCumuRef->GetBinContent(refEtaBinB, 0);
1420 dQnReB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberCos(n));
1421 dQnImB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberSin(n));
1423 if (multA <= 3 || multB <= 3) return;
1424 // The reference flow is calculated
1426 if ((fFlags & kStdQC)) {
1427 w2 = multA * (multA - 1.);
1428 two = dQnReA*dQnReA + dQnImA*dQnImA - multA;
1431 two = dQnReA*dQnReB + dQnImA*dQnImB;
1433 cumuRef->Fill(eta, cent, kW2Two, two);
1434 cumuRef->Fill(eta, cent, kW2, w2);
1436 // The reference flow is calculated
1438 if ((fFlags & kStdQC)) {
1439 w4 = multA * (multA - 1.) * (multA - 2.) * (multA - 3.);
1441 four = 2.*multA*(multA-3.) + TMath::Power((TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.)),2.)
1442 -4.*(multA-2.)*(TMath::Power(dQnReA,2.) + TMath::Power(dQnImA,2.))
1443 -2.*(TMath::Power(dQnReA,2.)*dQ2nReA+2.*dQnReA*dQnImA*dQ2nImA-TMath::Power(dQnImA,2.)*dQ2nReA)
1444 +(TMath::Power(dQ2nReA,2.)+TMath::Power(dQ2nImA,2.));
1446 cumuRef->Fill(eta, cent, kW4Four, four);
1447 cumuRef->Fill(eta, cent, kW4, w4);
1450 cosPhi1Phi2 = dQnReA*dQnReA - dQnImA*dQnImA - dQ2nReA;
1451 sinPhi1Phi2 = 2.*dQnReA*dQnImA - dQ2nImA;
1453 cosPhi1Phi2Phi3m = dQnReA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1454 -dQnReA*dQ2nReA-dQnImA*dQ2nImA-2.*(multA-1)*dQnReA;
1456 sinPhi1Phi2Phi3m = -dQnImA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1457 +dQnReA*dQ2nImA-dQnImA*dQ2nReA+2.*(multA-1)*dQnImA;
1459 cumuRef->Fill(eta, cent, kCosphi1phi2, cosPhi1Phi2);
1460 cumuRef->Fill(eta, cent, kSinphi1phi2, sinPhi1Phi2);
1461 cumuRef->Fill(eta, cent, kCosphi1phi2phi3m, cosPhi1Phi2Phi3m);
1462 cumuRef->Fill(eta, cent, kSinphi1phi2phi3m, sinPhi1Phi2Phi3m);
1463 cumuRef->Fill(eta, cent, k3pWeight, multA*(multA-1.)*(multA-2.));
1465 } // End of reference flow
1466 // For each etaBin bin the necessary values for differential flow is calculated
1467 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1468 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1469 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1470 Double_t p2nRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n*2));
1471 Double_t p2nIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n*2));
1472 if (mp == 0) continue;
1479 // Differential flow calculations for each eta bin is done:
1480 // 2-particle differential flow
1481 if ((fFlags & kStdQC) && !(fFlags & kTPC)) {
1489 Double_t w2p = mp * multB - mq;
1490 Double_t twoPrime = pnRe*dQnReB + pnIm*dQnImB - mq;
1492 cumuDiff->Fill(eta, cent, kW2Two, twoPrime);
1493 cumuDiff->Fill(eta, cent, kW2, w2p);
1495 if ((fFlags & kEtaGap)) continue;
1496 // Differential flow calculations for each eta bin bin is done:
1497 // 4-particle differential flow
1498 Double_t w4p = (mp * multA - 3.*mq)*(multA - 1.)*(multA - 2.);
1500 Double_t fourPrime = (TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*(pnRe*dQnReA+pnIm*dQnImA)
1501 - q2nRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))
1502 - 2.*q2nIm*dQnReA*dQnImA
1503 - pnRe*(dQnReA*dQ2nReA+dQnImA*dQ2nImA)
1504 + pnIm*(dQnImA*dQ2nReA-dQnReA*dQ2nImA)
1505 - 2.*multA*(pnRe*dQnReA+pnIm*dQnImA)
1506 - 2.*(TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*mq
1507 + 6.*(qnRe*dQnReA+qnIm*dQnImA)
1508 + 1.*(q2nRe*dQ2nReA+q2nIm*dQ2nImA)
1509 + 2.*(pnRe*dQnReA+pnIm*dQnImA)
1513 cumuDiff->Fill(eta, cent, kW4Four, fourPrime);
1514 cumuDiff->Fill(eta, cent, kW4, w4p);
1517 Double_t cosPsi1Phi2 = pnRe*dQnReA - pnIm*dQnImA - q2nRe;
1518 Double_t sinPsi1Phi2 = pnRe*dQnImA + pnIm*dQnReA - q2nIm;
1520 Double_t cosPsi1Phi2Phi3p = pnRe*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1521 - 1.*(q2nRe*dQnReA+q2nIm*dQnImA)
1522 - mq*dQnReA+2.*qnRe;
1524 Double_t sinPsi1Phi2Phi3p = pnIm*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1525 - 1.*(q2nIm*dQnReA-q2nRe*dQnImA)
1526 - mq*dQnImA+2.*qnIm;
1528 Double_t cosPsi1Phi2Phi3m = pnRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))+2.*pnIm*dQnReA*dQnImA
1529 - 1.*(pnRe*dQ2nReA+pnIm*dQ2nImA)
1530 - 2.*mq*dQnReA+2.*qnRe;
1532 Double_t sinPsi1Phi2Phi3m = pnIm*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))-2.*pnRe*dQnReA*dQnImA
1533 - 1.*(pnIm*dQ2nReA-pnRe*dQ2nImA)
1534 + 2.*mq*dQnImA-2.*qnIm;
1536 cumuDiff->Fill(eta, cent, kCosphi1phi2, cosPsi1Phi2);
1537 cumuDiff->Fill(eta, cent, kSinphi1phi2, sinPsi1Phi2);
1538 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3m, cosPsi1Phi2Phi3m);
1539 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3m, sinPsi1Phi2Phi3m);
1540 cumuDiff->Fill(eta, cent, k3pWeight, (mp*multA-2.*mq)*(multA-1.));
1541 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3p, cosPsi1Phi2Phi3p);
1542 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3p, sinPsi1Phi2Phi3p);
1543 } // End of eta loop
1545 cumuRef->Fill(-7., cent, -0.5, 1.);
1546 } // End of moment loop
1549 //_____________________________________________________________________
1550 void AliForwardFlowTaskQC::VertexBin::GetLimits(Int_t bin, Int_t& aLow, Int_t& aHigh,
1551 Int_t& bLow, Int_t& bHigh) const
1554 // Get the limits for the 3 correlator method
1557 // bin : reference bin #
1558 // aLow : Lowest bin to be included in v_A calculations
1559 // aHigh: Highest bin to be included in v_A calculations
1560 // bLow : Lowest bin to be included in v_B calculations
1561 // bHigh: Highest bin to be included in v_B calculations
1563 if ((fFlags & kFMD)) {
1566 aLow = 14; aHigh = 15;
1567 bLow = 20; bHigh = 22;
1570 aLow = 16; aHigh = 16;
1571 bLow = 21; bHigh = 22;
1574 aLow = 6; aHigh = 7;
1575 bLow = 21; bHigh = 22;
1578 aLow = 6; aHigh = 7;
1579 bLow = 12; bHigh = 12;
1582 aLow = 6; aHigh = 8;
1583 bLow = 13; bHigh = 14;
1586 AliFatal(Form("No limits for this eta region! (%d)", bin));
1589 else if ((fFlags & kVZERO)) {
1592 aLow = 6; aHigh = 13;
1593 bLow = 17; bHigh = 18;
1596 aLow = 6; aHigh = 9;
1597 bLow = 17; bHigh = 18;
1600 aLow = 2; aHigh = 3;
1601 bLow = 17; bHigh = 18;
1604 aLow = 2; aHigh = 3;
1605 bLow = 6; bHigh = 9;
1608 aLow = 2; aHigh = 3;
1609 bLow = 6; bHigh = 13;
1612 AliFatal(Form("No limits for this eta region! (%d)", bin));
1615 // Try to catch cases where fEtaLimits and these values do not correspond to each other
1616 if (aHigh > fCumuNUARef->GetNbinsX() || bHigh > fCumuNUARef->GetNbinsX())
1617 AliFatal(Form("Limits outside vtx range! (%d) - aHigh = %d, bHigh = %d, Nbins = %d",
1618 bin, aHigh, bHigh, fCumuNUARef->GetNbinsX()));
1620 //_____________________________________________________________________
1621 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate3Cor(Double_t cent)
1624 // Calculate the Q cumulant up to order fMaxMoment
1627 // cent: centrality of event
1629 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1631 // Fill out NUA hists
1632 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1633 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1634 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1635 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1636 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1639 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1640 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1641 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1642 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1643 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1647 // We create the objects needed for the analysis
1650 // For each n we loop over the hists
1651 for (Int_t n = 2; n <= fMaxMoment; n++) {
1652 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1653 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1655 // Per mom. quantities
1657 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
1658 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1659 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1660 Double_t two = 0, w2 = 0;
1661 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1662 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1663 if (fEtaLims[prevLim] < eta) {
1664 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
1666 multA = 0; dQnReA = 0; dQnImA = 0;
1667 multB = 0; dQnReB = 0; dQnImB = 0;
1669 for (Int_t a = aLow; a <= aHigh; a++) {
1670 multA += fCumuRef->GetBinContent(a, 0);
1671 dQnReA += fCumuRef->GetBinContent(a, GetBinNumberCos(n));
1672 dQnImA += fCumuRef->GetBinContent(a, GetBinNumberSin(n));
1674 for (Int_t b = bLow; b <= bHigh; b++) {
1675 multB += fCumuRef->GetBinContent(b, 0);
1676 dQnReB += fCumuRef->GetBinContent(b, GetBinNumberCos(n));
1677 dQnImB += fCumuRef->GetBinContent(b, GetBinNumberSin(n));
1679 // The reference flow is calculated
1682 two = dQnReA*dQnReB + dQnImA*dQnImB;
1683 } // End of reference flow
1684 cumuRef->Fill(eta, cent, kW2Two, two);
1685 cumuRef->Fill(eta, cent, kW2, w2);
1687 // For each etaBin bin the necessary values for differential flow is calculated
1688 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1689 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1690 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1691 if (mp == 0) continue;
1693 // Differential flow calculations for each eta bin is done:
1694 // 2-particle differential flow
1695 Double_t w2pA = mp * multA;
1696 Double_t twoPrimeA = pnRe*dQnReA + pnIm*dQnImA;
1697 cumuDiff->Fill(eta, cent, kW2Two, twoPrimeA);
1698 cumuDiff->Fill(eta, cent, kW2, w2pA);
1700 Double_t w2pB = mp * multB;
1701 Double_t twoPrimeB = pnRe*dQnReB + pnIm*dQnImB;
1702 cumuDiff->Fill(eta, cent, kW4Four, twoPrimeB);
1703 cumuDiff->Fill(eta, cent, kW4, w2pB);
1704 } // End of eta loop
1706 cumuRef->Fill(-7., cent, -0.5, 1.);
1707 } // End of moment loop
1711 //_____________________________________________________________________
1712 void AliForwardFlowTaskQC::VertexBin::CumulantsTerminate(TList* inlist, TList* outlist)
1715 // Finalizes the Q cumulant calculations
1718 // inlist: input sumlist
1719 // outlist: output result list
1722 // Re-find cumulants hist if Terminate is called separately
1723 if (!fCumuHists.IsConnected()) {
1724 TList* list = (TList*)inlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1725 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1728 fCumuNUARef = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1730 fCumuNUADiff = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1732 // Clone to avoid normalization problems when redoing terminate locally
1733 fCumuNUARef = (TH3D*)fCumuNUARef->Clone(Form("%s_vertex_%d_%d%s_cumuNUARefNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1734 fCumuNUADiff = (TH3D*)fCumuNUADiff->Clone(Form("%s_vertex_%d_%d%s_cumuNUADiffNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1736 // Diagnostics histograms
1737 TH2I* quality = (TH2I*)outlist->FindObject(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1739 quality = MakeQualityHist(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1740 outlist->Add(quality);
1742 TH1D* cent = (TH1D*)outlist->FindObject(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)));
1744 cent = new TH1D(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1745 Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1746 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1747 cent->GetXaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1750 TH2D* dNdetaRef = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)));
1752 dNdetaRef = new TH2D(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1753 Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1754 fCumuNUARef->GetNbinsX(), fCumuNUARef->GetXaxis()->GetXmin(), fCumuNUARef->GetXaxis()->GetXmax(),
1755 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1756 dNdetaRef->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1758 outlist->Add(dNdetaRef);
1760 TH2D* dNdetaDiff = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)));
1762 dNdetaDiff = new TH2D(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1763 Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1764 fCumuNUADiff->GetNbinsX(), fCumuNUADiff->GetXaxis()->GetXmin(), fCumuNUADiff->GetXaxis()->GetXmax(),
1765 fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXmin(), fCumuNUADiff->GetYaxis()->GetXmax());
1766 dNdetaDiff->GetYaxis()->Set(fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXbins()->GetArray());
1767 dNdetaDiff->Sumw2();
1768 outlist->Add(dNdetaDiff);
1771 // Setting up outputs
1772 // Create output lists and diagnostics
1773 TList* vtxList = (TList*)outlist->FindObject("vtxList");
1775 vtxList = new TList();
1776 vtxList->SetName("vtxList");
1777 outlist->Add(vtxList);
1779 vtxList->Add(fCumuNUARef);
1780 vtxList->Add(fCumuNUADiff);
1782 // Setup output profiles
1783 CumuHistos cumu2(fMaxMoment, ((fFlags & kNUAcorr) ? 2 : 0));
1784 CumuHistos cumu4(fMaxMoment, ((fFlags & kNUAcorr) ? 1 : 0));
1786 cumu2.ConnectList(Form("%sQC2_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1787 if ((fFlags & kStdQC))
1788 cumu4.ConnectList(Form("%sQC4_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1790 for (Int_t n = 2; n <= fMaxMoment; n++) {
1792 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNoNUA));
1793 if ((fFlags & k3Cor)){
1794 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNoNUA));
1795 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNoNUA));
1797 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNoNUA));
1800 if ((fFlags & kStdQC)) {
1801 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNoNUA));
1802 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNoNUA));
1804 } // End of v_n result loop
1806 if ((fFlags & kNUAcorr)) {
1807 for (Int_t n = 2; n <= fMaxMoment; n++) {
1809 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUAOld));
1810 if ((fFlags & k3Cor)) {
1811 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUAOld));
1812 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUAOld));
1814 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUAOld));
1817 if ((fFlags & kStdQC)) {
1818 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNUAOld));
1819 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNUAOld));
1822 for (Int_t n = 2; n <= fMaxMoment; n++) {
1824 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUA));
1825 if ((fFlags & k3Cor)) {
1826 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUA));
1827 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUA));
1829 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUA));
1834 // Calculating the cumulants
1835 if ((fFlags & k3Cor)) {
1836 Calculate3CorFlow(cumu2, quality, cent, dNdetaRef, dNdetaDiff);
1838 CalculateReferenceFlow(cumu2, cumu4, quality, cent, dNdetaRef);
1839 CalculateDifferentialFlow(cumu2, cumu4, quality, dNdetaDiff);
1841 if ((fFlags & kNUAcorr)) {
1842 SolveCoupledFlowEquations(cumu2, 'r');
1843 if ((fFlags & k3Cor)) {
1844 SolveCoupledFlowEquations(cumu2, 'a');
1845 SolveCoupledFlowEquations(cumu2, 'b');
1847 SolveCoupledFlowEquations(cumu2, 'd');
1851 // Add to output for immediate viewing - individual vtx bins are used for final results
1852 AddVertexBins(cumu2, outlist, ((fFlags & kNUAcorr) ? 2 : 0));
1853 if ((fFlags & kStdQC)) AddVertexBins(cumu4, outlist, ((fFlags & kNUAcorr) ? 1 : 0));
1855 // Setup NUA diagnoastics histograms
1856 TList* nualist = (TList*)outlist->FindObject("NUATerms");
1858 nualist = new TList();
1859 nualist->SetName("NUATerms");
1860 outlist->Add(nualist);
1863 TH2D* nuaRef = (TH2D*)nualist->FindObject(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1866 nuaRef = (TH2D*)fCumuNUARef->Project3D("yz");
1867 nuaRef->Scale(1./fCumuNUARef->GetNbinsX());
1868 nuaRef->SetName(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1869 nuaRef->SetTitle(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1870 nualist->Add(nuaRef);
1872 temp = (TH2D*)fCumuNUARef->Project3D("yz");
1873 temp->Scale(1./fCumuNUARef->GetNbinsX());
1877 // Filling in underflow to make scaling possible in Terminate()
1878 nuaRef->Fill(0., -1., 1.);
1880 TH2D* nuaDiff = (TH2D*)nualist->FindObject(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1882 nuaDiff = (TH2D*)fCumuNUADiff->Project3D("yz");
1883 nuaDiff->SetName(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1884 nuaDiff->SetTitle(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1885 nualist->Add(nuaDiff);
1887 temp = (TH2D*)fCumuNUADiff->Project3D("yz");
1891 // Filling in underflow to make scaling possible in Terminate()
1892 nuaDiff->Fill(0., -1., 1.);
1896 //_____________________________________________________________________
1897 void AliForwardFlowTaskQC::VertexBin::CalculateReferenceFlow(CumuHistos& cumu2h, CumuHistos& cumu4h, TH2I* quality,
1898 TH1D* chist, TH2D* dNdetaRef) const
1901 // Calculates the reference flow
1904 // cumu2h: CumuHistos object with QC{2} cumulants
1905 // cumu4h: CumuHistos object with QC{4} cumulants
1906 // quality: Histogram for success rate of cumulants
1907 // chist: Centrality histogram
1908 // dNdetaRef: dN/deta histogram for estimating multiplicity used for ref calculations
1911 // Normalizing common NUA hists
1912 for (Int_t cBin = 1; cBin <= fCumuNUARef->GetNbinsY(); cBin++) {
1913 Double_t cent = fCumuNUARef->GetYaxis()->GetBinCenter(cBin);
1914 for (Int_t eBin = 1; eBin <= fCumuNUARef->GetNbinsX(); eBin++) {
1915 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(eBin);
1916 Double_t mult = fCumuNUARef->GetBinContent(eBin, cBin, 0);
1917 if (mult == 0) continue;
1918 for (Int_t qBin = 1; qBin <= fCumuNUARef->GetNbinsZ(); qBin++) {
1919 fCumuNUARef->SetBinContent(eBin, cBin, qBin, fCumuNUARef->GetBinContent(eBin, cBin, qBin)/mult);
1920 fCumuNUARef->SetBinError(eBin, cBin, qBin, fCumuNUARef->GetBinError(eBin, cBin, qBin)/mult);
1922 // Fill dN/deta diagnostics
1923 dNdetaRef->Fill(eta, cent, mult);
1927 // For flow calculations
1930 TH2D* cumu2NUAold = 0;
1933 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
1934 // Loop over cumulant histogram for final calculations
1935 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
1936 cumu2 = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
1937 if ((fFlags & kNUAcorr)) {
1938 cumu2NUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
1940 if ((fFlags & kStdQC)) {
1941 cumu4 = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNoNUA);
1942 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNUAOld);
1944 cumuRef = (TH3D*)fCumuHists.Get('r', n);
1946 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
1947 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
1948 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
1949 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
1950 for (Int_t etaBin = 1; etaBin <= cumuRef->GetNbinsX(); etaBin++) { // Eta loop begins
1951 Double_t eta = cumuRef->GetXaxis()->GetBinCenter(etaBin);
1952 Double_t refEta = eta;
1953 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(refEta);
1954 if ((fFlags & kEtaGap)) refEta = -eta;
1955 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(refEta);
1956 // 2-particle reference flow
1957 Double_t w2Two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
1958 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
1959 if (w2 == 0) continue;
1960 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
1961 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
1962 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
1963 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
1964 Double_t cos2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(2*n));
1965 Double_t sin2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(2*n));
1966 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
1967 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
1968 Double_t two = w2Two / w2;
1970 if (qc2 >= 0) cumu2->Fill(eta, cent, TMath::Sqrt(qc2));
1972 if ((fFlags & kNUAcorr)) {
1974 // With no eta gap the last two terms are <<cos(phi)>>^2 and <<sin(phi)>>^2,
1975 // with eta gap the different coverage is taken into account.
1976 // The next line covers both cases.
1977 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
1978 // Extra NUA term from 2n cosines and sines
1979 Double_t den = 1-(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB);
1980 if (den != 0) qc2 /= den;
1985 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
1986 fType.Data(), n, qc2, eta, cent));
1987 quality->Fill((n-2)*qualityFactor+2, Int_t(cent));
1990 Double_t vnTwo = TMath::Sqrt(qc2);
1991 if (!TMath::IsNaN(vnTwo)) {
1992 quality->Fill((n-2)*qualityFactor+1, Int_t(cent));
1993 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, vnTwo);
1996 if (!(fFlags & kStdQC)) continue;
1997 // 4-particle reference flow
1998 Double_t w4Four = cumuRef->GetBinContent(refEtaBinA, cBin, kW4Four);
1999 Double_t w4 = cumuRef->GetBinContent(refEtaBinA, cBin, kW4);
2000 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
2001 if (w4 == 0 || multm1m2 == 0) continue;
2002 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2003 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2004 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2005 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2007 cosP1nPhi1P1nPhi2 /= w2;
2008 sinP1nPhi1P1nPhi2 /= w2;
2009 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2010 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2011 Double_t four = w4Four / w4;
2012 Double_t qc4 = four-2.*TMath::Power(two,2.);
2013 if (qc4 < 0) cumu4->Fill(eta, cent, TMath::Power(-qc4, 0.25));
2015 if ((fFlags & kNUAcorr)) {
2016 qc4 += - 4.*cosP1nPhiA*cosP1nPhi1M1nPhi2M1nPhi3
2017 + 4.*sinP1nPhiA*sinP1nPhi1M1nPhi2M1nPhi3-TMath::Power(cosP1nPhi1P1nPhi2,2.)-TMath::Power(sinP1nPhi1P1nPhi2,2.)
2018 + 4.*cosP1nPhi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2019 + 8.*sinP1nPhi1P1nPhi2*sinP1nPhiA*cosP1nPhiA
2020 + 8.*two*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2021 - 6.*TMath::Power((TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.)),2.);
2025 AliInfo(Form("%s: QC_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2026 fType.Data(), n, qc2, eta, cent));
2027 quality->Fill((n-2)*qualityFactor+6, Int_t(cent));
2030 Double_t vnFour = TMath::Power(-qc4, 0.25);
2031 if (!TMath::IsNaN(vnFour*multm1m2)) {
2032 quality->Fill((n-2)*qualityFactor+5, Int_t(cent));
2033 if ((fFlags & kNUAcorr)) cumu4NUA->Fill(eta, cent, vnFour);
2041 //_____________________________________________________________________
2042 void AliForwardFlowTaskQC::VertexBin::CalculateDifferentialFlow(CumuHistos& cumu2h, CumuHistos& cumu4h,
2043 TH2I* quality, TH2D* dNdetaDiff) const
2046 // Calculates the differential flow
2049 // cumu2h: CumuHistos object with QC{2} cumulants
2050 // cumu4h: CumuHistos object with QC{4} cumulants
2051 // quality: Histogram for success rate of cumulants
2052 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2055 for (Int_t cBin = 1; cBin <= fCumuNUADiff->GetNbinsY(); cBin++) {
2056 Double_t cent = fCumuNUADiff->GetYaxis()->GetBinCenter(cBin);
2057 for (Int_t eBin = 1; eBin <= fCumuNUADiff->GetNbinsX(); eBin++) {
2058 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(eBin);
2059 Double_t mult = fCumuNUADiff->GetBinContent(eBin, cBin, 0);
2060 if (mult == 0) continue;
2061 for (Int_t qBin = 1; qBin <= fCumuNUADiff->GetNbinsZ(); qBin++) {
2062 fCumuNUADiff->SetBinContent(eBin, cBin, qBin, fCumuNUADiff->GetBinContent(eBin, cBin, qBin)/mult);
2063 fCumuNUADiff->SetBinError(eBin, cBin, qBin, fCumuNUADiff->GetBinError(eBin, cBin, qBin)/mult);
2065 dNdetaDiff->Fill(eta, cent, mult);
2069 // For flow calculations
2073 TH2D* cumu2NUAold = 0;
2076 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
2077 // Loop over cumulant histogram for final calculations
2078 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2079 cumu2 = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNoNUA);
2080 if ((fFlags & kNUAcorr)) {
2081 cumu2NUAold = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNUAOld);
2083 if ((fFlags & kStdQC)) {
2084 cumu4 = (TH2D*)cumu4h.Get('d',n);
2085 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('d', n, CumuHistos::kNUAOld);
2087 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2088 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2089 for (Int_t cBin = 1; cBin <= cumuDiff->GetNbinsY(); cBin++) { // Centrality loop begins
2090 Double_t cent = cumuDiff->GetYaxis()->GetBinCenter(cBin);
2091 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2092 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2093 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2094 Double_t refEta = eta;
2095 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(refEta);
2096 if ((fFlags & kEtaGap)) refEta = -eta;
2097 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(refEta);
2099 // Reference objects
2100 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
2101 if (w2 == 0) continue;
2102 Double_t two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
2104 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
2105 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
2106 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
2107 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
2108 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
2109 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
2111 // 2-particle differential flow
2112 Double_t w2pTwoPrime = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2113 Double_t w2p = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2114 if (w2p == 0) continue;
2115 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2116 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2117 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2118 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2119 Double_t twoPrime = w2pTwoPrime / w2p;
2121 Double_t qc2Prime = twoPrime;
2122 cumu2->Fill(eta, cent, qc2Prime);
2123 if ((fFlags & kNUAcorr)) {
2125 qc2Prime -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB;
2126 // Extra NUA term from 2n cosines and sines
2127 qc2Prime /= (1.-(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
2129 if (!TMath::IsNaN(qc2Prime)) {
2130 quality->Fill((n-2)*qualityFactor+3, Int_t(cent));
2131 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, qc2Prime);
2134 quality->Fill((n-2)*qualityFactor+4, Int_t(cent));
2136 AliInfo(Form("%s: QC'_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2137 fType.Data(), n, qc2Prime, eta, cent));
2139 if (!(fFlags & kStdQC)) continue;
2140 // Reference objects
2141 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2142 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2143 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2144 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2145 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
2146 cosP1nPhi1P1nPhi2 /= w2;
2147 sinP1nPhi1P1nPhi2 /= w2;
2148 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2149 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2151 // 4-particle differential flow
2152 Double_t w4pFourPrime = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2153 Double_t w4p = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2154 Double_t mpqMult = cumuDiff->GetBinContent(etaBin, cBin, k3pWeight);
2155 if (w4p == 0 || mpqMult == 0) continue;
2156 Double_t cosP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2);
2157 Double_t sinP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2);
2158 Double_t cosP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3m);
2159 Double_t sinP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3m);
2160 Double_t cosP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3p);
2161 Double_t sinP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3p);
2163 cosP1nPsi1P1nPhi2 /= w2p;
2164 sinP1nPsi1P1nPhi2 /= w2p;
2165 cosP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2166 sinP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2167 cosP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2168 sinP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2170 Double_t fourPrime = w4pFourPrime / w4p;
2171 Double_t qc4Prime = fourPrime-2.*twoPrime*two;
2172 if (cumu4) cumu4->Fill(eta, cent, qc4Prime);
2174 if ((fFlags & kNUAcorr)) {
2175 qc4Prime += - cosP1nPsi*cosP1nPhi1M1nPhi2M1nPhi3
2176 + sinP1nPsi*sinP1nPhi1M1nPhi2M1nPhi3
2177 - cosP1nPhiA*cosP1nPsi1M1nPhi2M1nPhi3
2178 + sinP1nPhiA*sinP1nPsi1M1nPhi2M1nPhi3
2179 - 2.*cosP1nPhiA*cosP1nPsi1P1nPhi2M1nPhi3
2180 - 2.*sinP1nPhiA*sinP1nPsi1P1nPhi2M1nPhi3
2181 - cosP1nPsi1P1nPhi2*cosP1nPhi1P1nPhi2
2182 - sinP1nPsi1P1nPhi2*sinP1nPhi1P1nPhi2
2183 + 2.*cosP1nPhi1P1nPhi2*(cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2184 + 2.*sinP1nPhi1P1nPhi2*(cosP1nPsi*sinP1nPhiA+sinP1nPsi*cosP1nPhiA)
2185 + 4.*two*(cosP1nPsi*cosP1nPhiA+sinP1nPsi*sinP1nPhiA)
2186 + 2.*cosP1nPsi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2187 + 4.*sinP1nPsi1P1nPhi2*cosP1nPhiA*sinP1nPhiA
2188 + 4.*twoPrime*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2189 - 6.*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2190 * (cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2191 - 12.*cosP1nPhiA*sinP1nPhiA
2192 * (sinP1nPsi*cosP1nPhiA+cosP1nPsi*sinP1nPhiA);
2194 // Double_t vnFourDiff = - qc4Prime / TMath::Power(-qc4, 0.75);
2195 if (!TMath::IsNaN(qc4Prime*mpqMult)) {
2196 quality->Fill((n-2)*qualityFactor+7, Int_t(cent));
2197 if (cumu4NUA) cumu4NUA->Fill(eta, cent, qc4Prime);
2200 quality->Fill((n-2)*qualityFactor+8, Int_t(cent));
2202 AliInfo(Form("%s: v_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f",
2203 fType.Data(), n, qc4Prime, eta, cent));
2204 } // End of eta loop
2205 } // End of centrality loop
2210 //_____________________________________________________________________
2211 void AliForwardFlowTaskQC::VertexBin::Calculate3CorFlow(CumuHistos& cumu2h, TH2I* quality, TH1D* chist,
2212 TH2D* dNdetaRef, TH2D* dNdetaDiff) const
2215 // Calculates the 3 sub flow
2218 // cumu2h: CumuHistos object with QC{2} cumulants
2219 // quality: Histogram for success rate of cumulants
2220 // chist: Centrality histogram
2221 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2224 // For flow calculations
2228 TH2D* cumu2rNUAold = 0;
2230 TH2D* cumu2aNUAold = 0;
2232 TH2D* cumu2bNUAold = 0;
2233 // Loop over cumulant histogram for final calculations
2234 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2235 cumu2r = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
2236 cumu2a = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNoNUA);
2237 cumu2b = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNoNUA);
2238 if ((fFlags & kNUAcorr)) {
2239 cumu2rNUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
2240 cumu2aNUAold = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNUAOld);
2241 cumu2bNUAold = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNUAOld);
2243 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2244 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2245 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
2246 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
2247 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
2248 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2251 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2252 Double_t cosP1nPhiA = 0;
2253 Double_t sinP1nPhiA = 0;
2254 Double_t cos2nPhiA = 0;
2255 Double_t sin2nPhiA = 0;
2256 Double_t cosP1nPhiB = 0;
2257 Double_t sinP1nPhiB = 0;
2258 Double_t cos2nPhiB = 0;
2259 Double_t sin2nPhiB = 0;
2263 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2264 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2265 // 2-particle reference flow
2266 Double_t w2Two = cumuRef->GetBinContent(etaBin, cBin, kW2Two);
2267 Double_t w2 = cumuRef->GetBinContent(etaBin, cBin, kW2);
2268 if (w2 == 0) continue;
2270 // Update NUA for new range!
2271 if (fEtaLims[prevLim] < eta) {
2272 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
2274 cosP1nPhiA = 0; sinP1nPhiA = 0; cos2nPhiA = 0; sin2nPhiA = 0; multA = 0;
2275 cosP1nPhiB = 0; sinP1nPhiB = 0; cos2nPhiB = 0; sin2nPhiB = 0; multB = 0;
2276 for (Int_t a = aLow; a <= aHigh; a++) {
2277 cosP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n));
2278 sinP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n));
2279 cos2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2280 sin2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2281 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2283 for (Int_t b = bLow; b <= bHigh; b++) {
2284 cosP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n));
2285 sinP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n));
2286 cos2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2287 sin2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2288 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2290 if (multA == 0 || multB == 0) AliFatal("Empty NUA values for 3Cor!");
2291 cosP1nPhiA /= multA;
2292 sinP1nPhiA /= multA;
2295 cosP1nPhiB /= multB;
2296 sinP1nPhiB /= multB;
2300 dNdetaRef->Fill(eta, cent, multA+multB);
2302 Double_t two = w2Two / w2;
2305 if (qc2 >= 0) cumu2r->Fill(eta, cent, TMath::Sqrt(qc2));
2307 if ((fFlags & kNUAcorr)) {
2309 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
2310 // Extra NUA term from 2n cosines and sines
2311 qc2 /= (1-(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB));
2315 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2316 fType.Data(), n, qc2, eta, cent));
2317 quality->Fill((n-2)*4+2, Int_t(cent));
2320 Double_t vnTwo = TMath::Sqrt(qc2);
2321 if (!TMath::IsNaN(vnTwo)) {
2322 quality->Fill((n-2)*4+1, Int_t(cent));
2323 if ((fFlags & kNUAcorr)) cumu2rNUAold->Fill(eta, cent, vnTwo);
2326 // 2-particle differential flow
2327 Double_t w2pTwoPrimeA = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2328 Double_t w2pA = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2329 Double_t w2pTwoPrimeB = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2330 Double_t w2pB = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2331 if (w2pA == 0 || w2pB == 0) continue;
2332 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2333 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2334 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2335 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2336 Double_t mult = fCumuNUADiff->GetBinContent(etaBin, cBin, 0);
2337 if (mult == 0) continue;
2342 Double_t twoPrimeA = w2pTwoPrimeA / w2pA;
2343 Double_t twoPrimeB = w2pTwoPrimeB / w2pB;
2344 dNdetaDiff->Fill(eta, cent, mult);
2346 Double_t qc2PrimeA = twoPrimeA;
2347 Double_t qc2PrimeB = twoPrimeB;
2348 if (qc2PrimeA*qc2PrimeB >= 0) {
2349 cumu2a->Fill(eta, cent, qc2PrimeA);
2350 cumu2b->Fill(eta, cent, qc2PrimeB);
2352 if ((fFlags & kNUAcorr)) {
2354 qc2PrimeA -= cosP1nPsi*cosP1nPhiA + sinP1nPsi*sinP1nPhiA;
2355 qc2PrimeB -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB; // Is this OK?
2356 // Extra NUA term from 2n cosines and sines
2357 qc2PrimeA /= (1.-(cos2nPsi*cos2nPhiA + sin2nPsi*sin2nPhiA));
2358 qc2PrimeB /= (1.-(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
2360 if (!TMath::IsNaN(qc2PrimeA) && !TMath::IsNaN(qc2PrimeB) && qc2 != 0) {
2361 if (qc2PrimeA*qc2PrimeB >= 0) {
2362 quality->Fill((n-2)*4+3, Int_t(cent));
2363 if ((fFlags & kNUAcorr)) cumu2aNUAold->Fill(eta, cent, qc2PrimeA);
2364 if ((fFlags & kNUAcorr)) cumu2bNUAold->Fill(eta, cent, qc2PrimeB);
2368 quality->Fill((n-2)*4+4, Int_t(cent));
2370 AliInfo(Form("%s: QC'a_%d{2} = %1.3f, QC'b_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2371 fType.Data(), n, qc2PrimeA, n, qc2PrimeB, eta, cent));
2372 } // End of eta loop
2373 } // End of centrality loop
2378 //_____________________________________________________________________
2379 void AliForwardFlowTaskQC::VertexBin::SolveCoupledFlowEquations(CumuHistos& cumu, const Char_t type) const
2382 // Function to solve the coupled flow equations
2383 // We solve it by using matrix calculations:
2384 // A*v_n = V => v_n = A^-1*V
2385 // First we set up a TMatrixD container to make ROOT
2386 // do the inversions in an efficient way, we multiply the current <<2>> estimates.
2387 // Then we fill new TH2D's if the corrected <<2>>'s (cumuNUA object).
2390 // cumu: CumuHistos object - uncorrected
2391 // type: Reference ('r') or differential ('d') or ('a' or 'b') for 3 correlator
2394 // We start by declaring Matrix and vector objects, as their constructors are quite heavy
2395 TMatrixD mNUA(fMaxMoment-1, fMaxMoment-1);
2396 TVectorD vQC2(fMaxMoment-1);
2398 for (Int_t cBin = 1; cBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsY(); cBin++) { // cent loop
2399 Double_t cent = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinCenter(cBin);
2400 for (Int_t eBin = 1; eBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsX(); eBin++) { // eta loop
2401 Double_t eta = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin);
2402 mNUA.Zero(); // reset matrix
2403 vQC2.Zero(); // reset vector
2404 for (Int_t n = 0; n < fMaxMoment-1; n++) { // moment loop
2405 vQC2(n) = static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUAOld))->GetBinContent(eBin, cBin);
2406 if (type == 'r' || type == 'R') vQC2(n) *= vQC2(n); // going back to <<2>>
2407 for (Int_t m = 0; m < fMaxMoment-1; m++) { // cross moment
2408 mNUA(n,m) = CalculateNUAMatrixElement(n, m, type, eBin, cBin);
2409 } // End of cross moment loop
2410 } // End of moment loop
2414 // If determinant is non-zero we go with corrected results
2415 if (det != 0 ) vQC2 = mNUA*vQC2;
2416 else AliWarning(Form("Determinant == 0 - cent: %d-%d, eta: %f, type: '%c', data: %s, vtx: %d-%d%s",
2417 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinLowEdge(cBin)),
2418 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinUpEdge(cBin)),
2419 cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin),
2420 type, fType.Data(), fVzMin, fVzMax,
2421 GetQCType(fFlags, kTRUE)));
2422 // Go back to v_n for ref. keep <<2'>> for diff. flow).
2423 for (Int_t n = 0; n < fMaxMoment-1; n++) {
2425 if (type == 'r' || type == 'R')
2426 vnTwo = (vQC2(n) > 0. ? TMath::Sqrt(vQC2(n)) : 0.);
2428 // is really more <<2'>> in this case
2431 // Fill in corrected v_n
2432 if (vnTwo != 0) static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUA))->Fill(eta, cent, vnTwo);
2433 } // End of moment loop
2434 } // End of eta loop
2435 } // End of centrality loop
2438 //_____________________________________________________________________
2439 Double_t AliForwardFlowTaskQC::VertexBin::CalculateNUAMatrixElement(Int_t n, Int_t m, Char_t type, Int_t binA, Int_t cBin) const
2442 // Calculates the (n,m)-th element in the NUA matrix: 1 if n == m, otherwise:
2443 // <<cos[(n-m)phi1]>>*<<cos[(n-m)phi2]>> + <<sin[(n-m)phi1]>>*<<sin[(n-m)phi2]>>
2444 // NUA(n,m) = -----------------------------------------------------------------------------
2445 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
2447 // <<cos[(n+m)phi1]>>*<<cos[(n+m)phi2]>> + <<sin[(n+m)phi1]>>*<<sin[(n+m)phi2]>>
2448 // + -----------------------------------------------------------------------------
2449 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
2454 // type: Reference ('r') or differential ('d') or ('a' or 'b')
2455 // binA: eta bin of phi1
2456 // cBin: centrality bin
2460 if (n == m) return 1.;
2464 Double_t cosnMmPhi1 = 0, cosnMmPhi2 = 0, sinnMmPhi1 = 0, sinnMmPhi2 = 0;
2465 Double_t cosnPmPhi1 = 0, cosnPmPhi2 = 0, sinnPmPhi1 = 0, sinnPmPhi2 = 0;
2466 Double_t cos2nPhi1 = 0, cos2nPhi2 = 0, sin2nPhi1 = 0, sin2nPhi2 = 0;
2469 if (type == 'r' || type == 'R') {
2470 if ((fFlags & k3Cor)) {
2471 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(binA);
2473 while (fEtaLims[i] < eta) i++;
2474 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2475 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2476 Double_t multA = 0, multB = 0;
2477 for (Int_t a = aLow; a <= aHigh; a++) {
2478 cosnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n-m));
2479 sinnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n-m));
2480 cosnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n+m));
2481 sinnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n+m));
2482 cos2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2483 sin2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2484 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2486 for (Int_t b = bLow; b <= bHigh; b++) {
2487 cosnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n-m));
2488 sinnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n-m));
2489 cosnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n+m));
2490 sinnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n+m));
2491 cos2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2492 sin2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2493 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2495 if (multA == 0 || multB == 0) {
2496 if (fDebug > 0) AliWarning("multA or multB == 0 in matrix elements, aborting NUA");
2499 cosnMmPhi1 /= multA;
2500 sinnMmPhi1 /= multA;
2501 cosnPmPhi1 /= multA;
2502 sinnPmPhi1 /= multA;
2505 cosnMmPhi2 /= multB;
2506 sinnMmPhi2 /= multB;
2507 cosnPmPhi2 /= multB;
2508 sinnPmPhi2 /= multB;
2512 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUARef->GetXaxis()->GetBinCenter(binA));
2513 cosnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2514 sinnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2515 cosnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2516 sinnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2517 cos2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2518 sin2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2519 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2520 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2521 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2522 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2523 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2524 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2526 } // differential flow
2527 else if (type == 'd' || type == 'D') {
2528 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUADiff->GetXaxis()->GetBinCenter(binA));
2529 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2530 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2531 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2532 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2533 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2534 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2535 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2536 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2537 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2538 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2539 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2540 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2541 } // 3 correlator part a or b
2542 else if (type == 'a' || type == 'A' || type == 'b' || type == 'B') {
2543 Double_t mult1 = 0, mult2 = 0;
2545 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2546 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2547 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2548 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2549 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2550 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2551 mult1 = fCumuNUADiff->GetBinContent(binA, cBin, 0);
2553 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(binA);
2555 while (fEtaLims[i] < eta) i++;
2556 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2557 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2558 Int_t lLow = ((type == 'a' || type == 'A') ? aLow : bLow);
2559 Int_t lHigh = ((type == 'a' || type == 'A') ? aHigh : bHigh);
2560 for (Int_t l = lLow; l <= lHigh; l++) {
2561 cosnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n-m));
2562 sinnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n-m));
2563 cosnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n+m));
2564 sinnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n+m));
2565 cos2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(2*n));
2566 sin2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(2*n));
2567 mult2 += fCumuNUARef->GetBinContent(l, cBin, 0);
2569 if (mult1 == 0 || mult2 == 0) {
2570 if (fDebug > 0) AliWarning("mult1 or mult2 == 0 in matrix elements, aborting NUA");
2573 cosnMmPhi1 /= mult1;
2574 sinnMmPhi1 /= mult1;
2575 cosnPmPhi1 /= mult1;
2576 sinnPmPhi1 /= mult1;
2579 cosnMmPhi2 /= mult2;
2580 sinnMmPhi2 /= mult2;
2581 cosnPmPhi2 /= mult2;
2582 sinnPmPhi2 /= mult2;
2587 // Actual calculation
2588 Double_t e = cosnMmPhi1*cosnMmPhi2 + sinnMmPhi1*sinnMmPhi2 + cosnPmPhi1*cosnPmPhi2 + sinnPmPhi1*sinnPmPhi2;
2589 Double_t den = 1 + cos2nPhi1*cos2nPhi2 + sin2nPhi1*sin2nPhi2;
2590 if (den != 0) e /= den;
2595 //_____________________________________________________________________
2596 void AliForwardFlowTaskQC::VertexBin::AddVertexBins(CumuHistos& cumu, TList* list, UInt_t nNUA) const
2599 // Add up vertex bins with flow results
2602 // cumu: CumuHistos object with vtxbin results
2603 // list: Outout list with added results
2604 // nNUA: # of NUA histograms to loop over
2607 TProfile2D* avgProf = 0;
2609 Int_t nT = ((fFlags & k3Cor) ? 3 : 2);
2611 for (UInt_t nua = 0; nua <= nNUA; nua++) { // NUA loop
2612 for (Int_t n = 2; n <= fMaxMoment; n++) { // moment loop
2613 for (Int_t t = 0; t < nT; t++) { // type loop (r/d/a/b)
2616 case 0: ct = 'r'; break;
2617 case 1: ct = ((fFlags & k3Cor) ? 'a' : 'd'); break;
2618 case 2: ct = 'b'; break;
2619 default: ct = '\0'; break;
2621 vtxHist = static_cast<TH2D*>(cumu.Get(ct,n,nua));
2623 AliWarning("VertexBin::AddVertexBins: vtxHist not found!");
2626 name = vtxHist->GetName();
2627 // Strip name of vtx info
2628 Ssiz_t l = name.Last('x')-3;
2630 avgProf = (TProfile2D*)list->FindObject(name.Data());
2631 // if no output profile yet, make one
2633 avgProf = new TProfile2D(name.Data(), name.Data(),
2634 vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXmin(), vtxHist->GetXaxis()->GetXmax(),
2635 vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXmin(), vtxHist->GetYaxis()->GetXmax());
2636 if (vtxHist->GetXaxis()->IsVariableBinSize())
2637 avgProf->GetXaxis()->Set(vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXbins()->GetArray());
2638 if (vtxHist->GetYaxis()->IsVariableBinSize())
2639 avgProf->GetYaxis()->Set(vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXbins()->GetArray());
2642 // Fill in, cannot be done with Add function.
2643 for (Int_t e = 1; e <= vtxHist->GetNbinsX(); e++) { // eta loop
2644 Double_t eta = vtxHist->GetXaxis()->GetBinCenter(e);
2645 for (Int_t c = 1; c <= vtxHist->GetNbinsY(); c++) { // cent loop
2646 Double_t cent = vtxHist->GetYaxis()->GetBinCenter(c);
2647 Double_t cont = vtxHist->GetBinContent(e, c);
2648 if (cont == 0) continue;
2649 avgProf->Fill(eta, cent, cont);
2650 } // End of cent loop
2651 } // End of eta loop
2652 } // End of type loop
2653 } // End of moment loop
2654 } // End of nua loop
2656 //_____________________________________________________________________
2657 Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberCos(Int_t n) const
2660 // Get the bin number of <<cos(nphi)>>
2665 // Return: bin number
2670 if (n == 0) bin = fMaxMoment*4-1;
2675 //_____________________________________________________________________
2676 Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberSin(Int_t n) const
2679 // Get the bin number of <<sin(nphi)>>
2684 // Return: bin number
2689 if (n == 0) bin = fMaxMoment*4;
2694 //_____________________________________________________________________
2695 void AliForwardFlowTaskQC::VertexBin::SetupNUALabels(TAxis* a) const
2698 // Setup NUA labels on axis
2701 // a: Axis to set up
2703 if (a->GetNbins() != GetBinNumberSin()) AliFatal("SetupNUALabels: Wrong number of bins on axis");
2706 while (i <= a->GetNbins()) {
2707 a->SetBinLabel(i++, Form("<<cos(%d#varphi)>>", j));
2708 a->SetBinLabel(i++, Form("<<sin(%d#varphi)>>", j++));
2713 //_____________________________________________________________________
2714 TH2I* AliForwardFlowTaskQC::VertexBin::MakeQualityHist(const Char_t* name) const
2717 // Add a histogram for checking the analysis quality
2720 // const char*: name of data type
2722 // Return: histogram for tracking successful calculations
2724 Int_t nBins = ((fFlags & kStdQC) ? 8 : 4);
2725 TH2I* quality = new TH2I(name, name, (fMaxMoment-1)*nBins, 1, (fMaxMoment-1)*nBins+1, fCumuNUARef->GetNbinsY(),
2726 fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
2727 quality->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
2728 for (Int_t i = 2, j = 1; i <= fMaxMoment; i++) {
2729 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} > 0", i));
2730 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} <= 0", i));
2731 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} > 0", i));
2732 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} <= 0", i));
2733 if ((fFlags & kStdQC)) {
2734 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} < 0", i));
2735 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} >= 0", i));
2736 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} < 0", i));
2737 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} >= 0", i));
2743 //_____________________________________________________________________
2744 TH2D* AliForwardFlowTaskQC::VertexBin::MakeOutputHist(Int_t qc, Int_t n, const Char_t* ctype, UInt_t nua) const
2747 // Setup a TH2D for the output
2750 // qc # of particle correlations
2752 // ref Type: r/d/a/b
2753 // nua For nua corrected hists?
2755 // Return: 2D hist for results
2757 Bool_t ref = ((ctype[0] == 'R') || (ctype[0] == 'r'));
2758 TAxis* xAxis = (ref ? fCumuNUARef->GetXaxis() : fCumuNUADiff->GetXaxis());
2759 TAxis* yAxis = (ref ? fCumuNUARef->GetYaxis() : fCumuNUADiff->GetYaxis());
2762 case CumuHistos::kNoNUA: ntype = "Un"; break;
2763 case CumuHistos::kNUAOld: ntype = "NUAOld"; break;
2764 case CumuHistos::kNUA: ntype = "NUA"; break;
2767 TH2D* h = new TH2D(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 Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2771 fType.Data(), qc, n, ctype, ntype.Data(),
2772 GetQCType(fFlags), fVzMin, fVzMax),
2773 xAxis->GetNbins(), xAxis->GetXmin(), xAxis->GetXmax(),
2774 yAxis->GetNbins(), yAxis->GetXmin(), yAxis->GetXmax());
2775 if (xAxis->IsVariableBinSize()) h->GetXaxis()->Set(xAxis->GetNbins(), xAxis->GetXbins()->GetArray());
2776 h->GetYaxis()->Set(yAxis->GetNbins(), yAxis->GetXbins()->GetArray());
2780 //_____________________________________________________________________
2781 void AliForwardFlowTaskQC::PrintFlowSetup() const
2784 // Print the setup of the flow task
2786 Printf("=======================================================");
2787 Printf("%s::Print", this->IsA()->GetName());
2788 Printf("Forward detector: :\t%s", ((fFlowFlags & kFMD) ? "FMD" : "VZERO"));
2789 Printf("Number of bins in vertex axis :\t%d", fVtxAxis->GetNbins());
2790 Printf("Range of vertex axis :\t[%3.1f,%3.1f]",
2791 fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
2792 Printf("Number of bins in centrality axis :\t%d", fCentAxis->GetNbins());
2793 printf("Centrality binning :\t");
2794 for (Int_t cBin = 1; cBin <= fCentAxis->GetNbins(); cBin++) {
2795 printf("%02d-%02d%% ", Int_t(fCentAxis->GetBinLowEdge(cBin)), Int_t(fCentAxis->GetBinUpEdge(cBin)));
2796 if (cBin == fCentAxis->GetNbins()) printf("\n");
2797 else if (cBin % 4 == 0) printf("\n\t\t\t\t\t");
2799 printf("Doing flow analysis for :\t");
2800 for (Int_t n = 2; n <= fMaxMoment; n++) printf("v%d ", n);
2802 TString type = "Standard QC{2} and QC{4} calculations.";
2803 if ((fFlowFlags & kTPC)) type.ReplaceAll(".", " with TPC tracks for reference.");
2804 if ((fFlowFlags & kEtaGap)) type = "QC{2} with a rapidity gap.";
2805 if ((fFlowFlags & k3Cor)) type = "QC{2} with 3 correlators.";
2806 Printf("QC calculation type :\t%s", type.Data());
2807 Printf("Symmetrize ref. flow wrt. eta = 0 :\t%s", ((fFlowFlags & kSymEta) ? "true" : "false"));
2808 Printf("Apply NUA correction terms :\t%s", ((fFlowFlags & kNUAcorr) ? "true" : "false"));
2809 Printf("Satellite vertex flag :\t%s", ((fFlowFlags & kSatVtx) ? "true" : "false"));
2810 Printf("FMD sigma cut: :\t%f", fFMDCut);
2811 Printf("SPD sigma cut: :\t%f", fSPDCut);
2812 if ((fFlowFlags & kEtaGap) || (fFlowFlags & kTPC))
2813 Printf("Eta gap: :\t%f", fEtaGap);
2814 Printf("=======================================================");
2816 //_____________________________________________________________________
2817 const Char_t* AliForwardFlowTaskQC::GetQCType(UShort_t flags, Bool_t prependUS)
2820 // Get the type of the QC calculations
2821 // Used for naming of objects in the VertexBin class,
2822 // important to avoid memory problems when running multiple
2823 // initializations of the class with different setups
2826 // flags: Flow flags for type determination
2827 // prependUS: Prepend an underscore (_) to the name
2829 // Return: QC calculation type
2832 if ((flags & kStdQC)) type = "StdQC";
2833 else if ((flags & kEtaGap)) type = "EtaGap";
2834 else if ((flags & k3Cor)) type = "3Cor";
2835 else type = "UNKNOWN";
2836 if (prependUS) type.Prepend("_");
2837 if ((flags & kTPC)) type.Append("TPCTr");
2840 //_____________________________________________________________________
2841 TH1* AliForwardFlowTaskQC::CumuHistos::Get(Char_t t, Int_t n, UInt_t nua) const
2844 // Get histogram/profile for type t and moment n
2847 // t: type = 'r'/'d'
2852 if (n < 0) AliFatal(Form("CumuHistos out of range: (%c,%d)", t, n));
2856 if (t == 'r' || t == 'R') pos = n;
2857 else if (t == 'd' || t == 'D') pos = n;
2858 else if (t == 'a' || t == 'A') pos = 2*n;
2859 else if (t == 'b' || t == 'B') pos = 2*n+1;
2860 else AliFatal(Form("CumuHistos wrong type: %c", t));
2862 if (t == 'r' || t == 'R') {
2863 if (pos < fRefHists->GetEntries()) {
2864 h = (TH1*)fRefHists->At(pos);
2866 } else if (pos < fDiffHists->GetEntries()) {
2867 h = (TH1*)fDiffHists->At(pos);
2869 if (!h) AliFatal(Form("No hist found in list %c at pos %d", t, pos));
2873 //_____________________________________________________________________
2874 void AliForwardFlowTaskQC::CumuHistos::ConnectList(TString name, TList* l)
2877 // Connect an output list with this object
2881 // l: list to keep outputs in
2884 ref.ReplaceAll("Cumu","CumuRef");
2885 fRefHists = (TList*)l->FindObject(ref.Data());
2887 fRefHists = new TList();
2888 fRefHists->SetName(ref.Data());
2891 // Check that the list correspond to fMaxMoments
2892 if (fRefHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1))
2893 AliError("CumuHistos::ConnectList Wrong number of hists in ref list,"
2894 "you are doing something wrong!");
2896 TString diff = name;
2897 diff.ReplaceAll("Cumu","CumuDiff");
2898 fDiffHists = (TList*)l->FindObject(diff.Data());
2900 fDiffHists = new TList();
2901 fDiffHists->SetName(diff.Data());
2904 // Check that the list correspond to fMaxMoment
2905 if ((fDiffHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1)) &&
2906 (fDiffHists->GetEntries() != 2*(fMaxMoment-1.)*(fNUA+1)))
2907 AliError(Form("CumuHistos::ConnectList Wrong number of hists in diff list,"
2908 "you are doing something wrong! (%s)",name.Data()));
2912 //_____________________________________________________________________
2913 void AliForwardFlowTaskQC::CumuHistos::Add(TH1* h) const
2916 // Add a histogram to this objects lists
2919 // h: histogram/profile to add
2921 TString name = h->GetName();
2922 if (name.Contains("Ref")) {
2923 if (fRefHists) fRefHists->Add(h);
2924 else AliFatal("CumuHistos::Add() - fRefHists does not exist");
2925 // Check that the list correspond to fMaxMoments
2926 if (fRefHists->GetEntries() > (fNUA+1)*(fMaxMoment-1.))
2927 AliError("CumuHistos::Add wrong number of hists in ref list, "
2928 "you are doing something wrong!");
2930 else if (name.Contains("Diff")) {
2931 if (fDiffHists) fDiffHists->Add(h);
2932 else AliFatal("CumuHistos::Add() - fDiffHists does not exist");
2933 // Check that the list correspond to fMaxMoment
2934 if (fDiffHists->GetEntries() > 2*(fNUA+1)*(fMaxMoment-1.))
2935 AliError("CumuHistos::Add wrong number of hists in diff list, "
2936 "you are doing something wrong!");
2940 //_____________________________________________________________________
2941 Int_t AliForwardFlowTaskQC::CumuHistos::GetPos(Int_t n, UInt_t nua) const
2944 // Get position in list of moment n objects
2945 // To take care of different numbering schemes
2949 // nua: # of nua corrections applied
2951 // Return: position #
2953 if (n > fMaxMoment) return -1;
2954 else return (n-2)+nua*(fMaxMoment-1);
2956 //_____________________________________________________________________