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 "AliAODVZERO.h"
34 #include "AliAODVertex.h"
35 #include "AliCentrality.h"
36 #include "AliESDEvent.h"
37 #include "AliVTrack.h"
38 #include "AliESDtrackCuts.h"
39 #include "AliAODTrack.h"
41 ClassImp(AliForwardFlowTaskQC)
46 AliForwardFlowTaskQC::AliForwardFlowTaskQC()
47 : AliAnalysisTaskSE(),
48 fVtxAxis(), // Axis to control vertex binning
49 fCentAxis(), // Axis to control centrality/multiplicity binning
50 fFMDCut(-1), // FMD sigma cut
51 fSPDCut(-1), // SPD sigma cut
52 fFlowFlags(0), // Flow flags
53 fEtaGap(-1), // Eta gap value
54 fBinsForward(), // List with forward flow hists
55 fBinsCentral(), // List with central flow hists
56 fSumList(0), // Event sum list
57 fOutputList(0), // Result output list
58 fAOD(0), // AOD input event
59 fESDTrackCuts(0), // ESD track cuts
60 fMaxMoment(0), // Max flow moment
61 fVtx(1111), // Z vertex coordinate
62 fCent(-1), // Centrality
63 fHistdNdedpV0(), // Hist for v0
64 fHistdNdedp3Cor(), // Hist for combining detectors
65 fHistFMDSPDCorr(), // FMD SPD correlation
66 fHistCent(), // Hist for centrality
67 fHistVertexSel(), // Hist for selected vertices
68 fHistEventSel() // Hist for event selection
71 // Default constructor
74 //_____________________________________________________________________
75 AliForwardFlowTaskQC::AliForwardFlowTaskQC(const char* name)
76 : AliAnalysisTaskSE(name),
77 fVtxAxis(), // Axis to control vertex binning
78 fCentAxis(), // Axis to control centrality/multiplicity binning
79 fFMDCut(-1), // FMD sigma cut
80 fSPDCut(-1), // SPD sigma cut
81 fFlowFlags(kSymEta|kStdQC), // Flow flags
82 fEtaGap(2.), // Eta gap value
83 fBinsForward(), // List with forward flow hists
84 fBinsCentral(), // List with central flow hists
85 fSumList(0), // Event sum list
86 fOutputList(0), // Result output list
87 fAOD(0), // AOD input event
88 fESDTrackCuts(0), // ESD track cuts
89 fMaxMoment(4), // Max flow moment
90 fVtx(1111), // Z vertex coordinate
91 fCent(-1), // Centrality
92 fHistdNdedpV0(), // Histo for v0
93 fHistdNdedp3Cor(), // Histo for combining detectors
94 fHistFMDSPDCorr(), // FMD SPD correlation
95 fHistCent(), // Hist for centrality
96 fHistVertexSel(), // Hist for selected vertices
97 fHistEventSel() // Hist for event selection
103 // name: Name of task
105 DefineOutput(1, TList::Class());
106 DefineOutput(2, TList::Class());
108 //_____________________________________________________________________
109 AliForwardFlowTaskQC::AliForwardFlowTaskQC(const AliForwardFlowTaskQC& o)
110 : AliAnalysisTaskSE(o),
111 fVtxAxis(o.fVtxAxis), // Axis to control vertex binning
112 fCentAxis(o.fCentAxis), // Array to control centrality/multiplicity binning
113 fFMDCut(o.fFMDCut), // FMD sigma cut
114 fSPDCut(o.fSPDCut), // SPD sigma cut
115 fFlowFlags(o.fFlowFlags), // Flow flags
116 fEtaGap(o.fEtaGap), // Eta gap value
117 fBinsForward(), // List with forward flow hists
118 fBinsCentral(), // List with central flow hists
119 fSumList(o.fSumList), // Event sum list
120 fOutputList(o.fOutputList), // Result output list
121 fAOD(o.fAOD), // AOD input event
122 fESDTrackCuts(o.fESDTrackCuts), // ESD track cuts
123 fMaxMoment(o.fMaxMoment), // Flow moments
124 fVtx(o.fVtx), // Z vertex coordinate
125 fCent(o.fCent), // Centrality
126 fHistdNdedpV0(o.fHistdNdedpV0), // Histo for v0
127 fHistdNdedp3Cor(o.fHistdNdedp3Cor),// Histo for combining detectors
128 fHistFMDSPDCorr(o.fHistFMDSPDCorr),// FMD SPD correlation
129 fHistCent(o.fHistCent), // Hist for centrality
130 fHistVertexSel(o.fHistVertexSel), // Hist for selected vertices
131 fHistEventSel(o.fHistEventSel) // Hist for event selection
137 // o: Object to copy from
140 //_____________________________________________________________________
141 AliForwardFlowTaskQC&
142 AliForwardFlowTaskQC::operator=(const AliForwardFlowTaskQC& o)
145 // Assignment operator
147 if (&o == this) return *this;
148 fVtxAxis = o.fVtxAxis;
149 fCentAxis = o.fCentAxis;
152 fFlowFlags = o.fFlowFlags;
154 fSumList = o.fSumList;
155 fOutputList = o.fOutputList;
157 fESDTrackCuts = o.fESDTrackCuts;
158 fMaxMoment = o.fMaxMoment;
161 fHistdNdedpV0 = o.fHistdNdedpV0;
162 fHistdNdedp3Cor = o.fHistdNdedp3Cor;
163 fHistFMDSPDCorr = o.fHistFMDSPDCorr;
164 fHistCent = o.fHistCent;
165 fHistVertexSel = o.fHistVertexSel;
166 fHistEventSel = o.fHistEventSel;
170 //_____________________________________________________________________
171 void AliForwardFlowTaskQC::SetFlowFlags(UShort_t flags)
174 // Set flow flags, making sure the detector setup is right
179 if ((flags & kFMD) && (flags & kVZERO))
180 AliFatal("Cannot do analysis on more than one forward detector!");
181 else if (!(flags & kFMD) && !(flags & kVZERO))
182 AliFatal("You need to add a forward detector!");
183 else fFlowFlags = flags;
185 //_____________________________________________________________________
186 void AliForwardFlowTaskQC::UserCreateOutputObjects()
189 // Create output objects
193 if (fFlowFlags & kTPC) {
194 fESDTrackCuts = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts();
198 PostData(1, fSumList);
200 //_____________________________________________________________________
201 void AliForwardFlowTaskQC::InitVertexBins()
204 // Init vertexbin objects for forward and central detectors, and add them to the lists
206 for (Int_t v = 1; v <= fVtxAxis->GetNbins(); v++) {
207 Int_t vL = Int_t(fVtxAxis->GetBinLowEdge(v));
208 Int_t vH = Int_t(fVtxAxis->GetBinUpEdge(v));
209 if ((fFlowFlags & kFMD)) {
210 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "FMD", fFlowFlags, fFMDCut, fEtaGap));
211 if (!(fFlowFlags & k3Cor)) fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-FMD", fFlowFlags|kNUAcorr, fSPDCut, fEtaGap));
213 else if ((fFlowFlags & kVZERO)) {
214 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "VZERO", fFlowFlags, 0, fEtaGap));
215 if (!(fFlowFlags & k3Cor)) fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-VZERO", fFlowFlags|kNUAcorr, fSPDCut, fEtaGap));
219 //_____________________________________________________________________
220 void AliForwardFlowTaskQC::InitHists()
223 // Init histograms and add vertex bin histograms to the sum list
226 fSumList = new TList();
227 fSumList->SetName("Sums");
228 fSumList->SetOwner();
230 if (!fVtxAxis) fVtxAxis = new TAxis(20, -10, 10);
231 fVtxAxis->SetName("VtxAxis");
232 if (!fCentAxis) fCentAxis = new TAxis(20, 0, 100);
233 fVtxAxis->SetName("CentAxis");
235 fHistCent = new TH1D("hCent", "Centralities", 100, 0, 100);
236 fHistVertexSel = new TH1D("hVertexSel", "Selected vertices", fVtxAxis->GetNbins(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
237 fHistEventSel = new TH1I("hEventSel", "Event Selection", kOK, 0.5, kOK+0.5);
238 fHistEventSel->GetXaxis()->SetBinLabel(kNoEvent, "No AOD event");
239 fHistEventSel->GetXaxis()->SetBinLabel(kNoForward, "No forward det");
240 fHistEventSel->GetXaxis()->SetBinLabel(kNoCentral, "No central det");
241 fHistEventSel->GetXaxis()->SetBinLabel(kNoTrigger, "Not triggered");
242 fHistEventSel->GetXaxis()->SetBinLabel(kNoCent, "No centrality");
243 fHistEventSel->GetXaxis()->SetBinLabel(kInvCent, "Centrality outside range");
244 fHistEventSel->GetXaxis()->SetBinLabel(kNoVtx, "No vertex");
245 fHistEventSel->GetXaxis()->SetBinLabel(kInvVtx, "Vtx outside range");
246 fHistEventSel->GetXaxis()->SetBinLabel(kOK, "OK!");
248 fHistFMDSPDCorr = new TH2D("hFMDSPDCorr", "hFMDSPCCorr", 200, 0., 20000., 200, 0, 7500);
250 TList* dList = new TList();
251 dList->SetName("Diagnostics");
252 dList->Add(fHistCent);
253 dList->Add(fHistVertexSel);
254 dList->Add(fHistEventSel);
255 dList->Add(fHistFMDSPDCorr);
256 fSumList->Add(dList);
258 fHistdNdedp3Cor = TH2D(Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)), Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)),
259 200, -4., 6., 20, 0., TMath::TwoPi());
260 if ((fFlowFlags & kVZERO)) {
261 Double_t bins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
262 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
263 fHistdNdedpV0 = TH2D(Form("hdNdedpv0%s", GetQCType(fFlowFlags)), Form("hdNdedpv0%s", GetQCType(fFlowFlags)),
264 11, -6, 6, 8, 0, TMath::TwoPi());
265 fHistdNdedpV0.GetXaxis()->Set(11, bins);
266 if ((fFlowFlags & k3Cor)) {
267 Double_t bins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
268 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
269 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
270 fHistdNdedp3Cor.GetXaxis()->Set(19, bins2);
271 fHistdNdedp3Cor.GetYaxis()->Set(8, 0., TMath::TwoPi());
275 TIter nextForward(&fBinsForward);
277 while ((bin = static_cast<VertexBin*>(nextForward()))) {
278 bin->AddOutput(fSumList, fCentAxis);
280 TIter nextCentral(&fBinsCentral);
281 while ((bin = static_cast<VertexBin*>(nextCentral()))) {
282 bin->AddOutput(fSumList, fCentAxis);
285 //_____________________________________________________________________
286 void AliForwardFlowTaskQC::UserExec(Option_t */*option*/)
289 // Calls the analyze function - called every event
295 // Reset data members
301 PostData(1, fSumList);
305 //_____________________________________________________________________
306 Bool_t AliForwardFlowTaskQC::Analyze()
309 // Load forward and central detector objects from aod tree and call the
310 // cumulants calculation for the correct vertex bin
312 // Return: true on success
316 fAOD = dynamic_cast<AliAODEvent*>(AliForwardUtil::GetAODEvent(this));
318 fHistEventSel->Fill(kNoEvent);
322 // Get detector objects
323 AliAODForwardMult* aodfmult = static_cast<AliAODForwardMult*>(fAOD->FindListObject("Forward"));
324 AliAODCentralMult* aodcmult = static_cast<AliAODCentralMult*>(fAOD->FindListObject("CentralClusters"));
325 AliAODVZERO* aodvzero = fAOD->GetVZEROData();
326 if ((fFlowFlags & kVZERO)) {
328 fHistdNdedpV0.Reset();
329 FillVZEROHist(aodvzero);
333 // We make sure that the necessary forward object is there
334 if ((fFlowFlags & kFMD) && !aodfmult) {
335 fHistEventSel->Fill(kNoForward);
338 else if ((fFlowFlags & kVZERO) && !aodvzero) {
339 fHistEventSel->Fill(kNoForward);
342 if (!aodcmult) fHistEventSel->Fill(kNoCentral);
344 // Check event for triggers, get centrality, vtx etc.
345 if (!CheckEvent(aodfmult)) return kFALSE;
346 Int_t vtx = fVtxAxis->FindBin(fVtx)-1;
348 // Then we assign a reference to the forward histogram of interest
349 TH2D& forwarddNdedp = ((fFlowFlags & kFMD) ? aodfmult->GetHistogram() : fHistdNdedpV0);
350 TH2D& spddNdedp = aodcmult->GetHistogram();
351 if ((fFlowFlags & kStdQC)) {
352 FillVtxBinList(fBinsForward, forwarddNdedp, vtx);
353 } else if ((fFlowFlags & kEtaGap)) {
354 FillVtxBinListEtaGap(fBinsForward, forwarddNdedp, forwarddNdedp, vtx);
356 // At the moment only clusters are supported for the central region (some day add tracks?)
357 // So no extra checks necessary
359 if ((fFlowFlags & kStdQC)) {
360 FillVtxBinList(fBinsCentral, spddNdedp, vtx);
361 } else if ((fFlowFlags & kEtaGap)) {
362 FillVtxBinListEtaGap(fBinsCentral, forwarddNdedp, spddNdedp, vtx);
363 } else if ((fFlowFlags & k3Cor)) {
364 FillVtxBinList3Cor(fBinsForward, spddNdedp, forwarddNdedp, vtx);
368 Double_t totForward = forwarddNdedp.Integral(1, forwarddNdedp.GetNbinsX(), 1, forwarddNdedp.GetNbinsY());
369 Double_t totSPD = spddNdedp.Integral(1, spddNdedp.GetNbinsX(), 1, spddNdedp.GetNbinsY());
370 fHistFMDSPDCorr->Fill(totForward, totSPD);
376 //_____________________________________________________________________
377 void AliForwardFlowTaskQC::FillVtxBinList(const TList& list, TH2D& h, Int_t vtx, UShort_t flags) const
380 // Loops over list of VtxBins, fills hists of bins for current vertex
381 // and runs analysis on those bins
384 // list: list of VtxBins
385 // h: dN/detadphi histogram
386 // vtx: current vertex bin
387 // flags: extra flags to handle calculations.
389 // Note: The while loop is used in this function and the next 2 for historical reasons,
390 // as originally each moment had it's own VertexBin object.
393 Int_t nVtxBins = fVtxAxis->GetNbins();
395 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
396 // If no tracks do things normally
397 if (!(fFlowFlags & kTPC) && !bin->FillHists(h, fCent, kFillBoth|flags|kReset)) return;
398 // if tracks things are more complicated
399 else if ((fFlowFlags & kTPC)) {
400 TObjArray* trList = GetTracks();
402 Bool_t useEvent = bin->FillTracks(trList, kFillRef|kReset|flags);
403 // If esd input trList is a new object owned by this task and should be cleaned up
404 if (AliForwardUtil::CheckForAOD() == 2) delete trList;
405 if (!useEvent) return;
406 if (!bin->FillHists(h, fCent, kFillDiff|kReset|flags)) return;
408 bin->CumulantsAccumulate(fCent);
414 //_____________________________________________________________________
415 void AliForwardFlowTaskQC::FillVtxBinListEtaGap(const TList& list, TH2D& href,
416 TH2D& hdiff, Int_t vtx, UShort_t flags) const
419 // Loops over list of VtxBins, fills hists of bins for current vertex
420 // and runs analysis on those bins
423 // list: list of VtxBins
424 // href: dN/detadphi histogram for ref. flow
425 // hdiff: dN/detadphi histogram for diff. flow
426 // vBin: current vertex bin
427 // flags: extra flags to handle calculations.
431 Int_t nVtxBins = fVtxAxis->GetNbins();
433 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
434 if (!bin->FillHists(href, fCent, kFillRef|flags|kReset)) return;
435 bin->FillHists(hdiff, fCent, kFillDiff|kReset);
436 bin->CumulantsAccumulate(fCent);
442 //_____________________________________________________________________
443 void AliForwardFlowTaskQC::FillVtxBinList3Cor(const TList& list, TH2D& hcent,
444 TH2D& hfwd, Int_t vtx, UShort_t flags)
447 // Loops over list of VtxBins, fills hists of bins for current vertex
448 // and runs analysis on those bins
451 // list: list of VtxBins
452 // hcent: dN/detadphi histogram for central coverage
453 // hfwd: dN/detadphi histogram for forward coverage
454 // vBin: current vertex bin
455 // flags: extra flags to handle calculations.
459 Int_t nVtxBins = fVtxAxis->GetNbins();
461 TH2D& h = CombineHists(hcent, hfwd);
463 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
464 if (!bin->FillHists(h, fCent, kFillBoth|flags|kReset)) return;
465 bin->CumulantsAccumulate3Cor(fCent);
471 //_____________________________________________________________________
472 TH2D& AliForwardFlowTaskQC::CombineHists(TH2D& hcent, TH2D& hfwd)
475 // Combines a forward and central d^2N/detadphi histogram.
476 // At some point it might need a flag to choose which histogram gets
477 // priority when there is an overlap, at the moment the average is chosen
480 // hcent: Central barrel detector
481 // hfwd: Forward detector
483 // Return: reference to combined hist
486 // If hists are the same (MC input) don't do anything
487 if (&hcent == &hfwd) return hcent;
489 fHistdNdedp3Cor.Reset();
491 if ((fFlowFlags & kFMD)) {
492 for (Int_t e = 1; e <= fHistdNdedp3Cor.GetNbinsX(); e++) {
493 Double_t eta = fHistdNdedp3Cor.GetXaxis()->GetBinCenter(e);
494 Bool_t fwdCov = (hfwd.GetBinContent(e, 0) != 0);
495 Bool_t centCov = (hcent.GetBinContent(e, 0) != 0);
496 if (!fwdCov && !centCov) continue;
497 else fHistdNdedp3Cor.SetBinContent(e, 0, 1);
498 for (Int_t p = 1; p <= fHistdNdedp3Cor.GetNbinsY(); p++) {
499 Double_t phi = fHistdNdedp3Cor.GetYaxis()->GetBinCenter(p);
503 cont += hfwd.GetBinContent(e, p);
507 cont += hcent.GetBinContent(e, p);
510 if (cont == 0 || n == 0) continue;
512 fHistdNdedp3Cor.Fill(eta, phi, cont);
515 // VZERO, SPD input, here we do not average but cut to avoid
516 // (too much) overlap.
517 } else if ((fFlowFlags & kVZERO)) {
519 for (Int_t eV = 1; eV <= hfwd.GetNbinsX(); eV++) {
520 Double_t eta = hfwd.GetXaxis()->GetBinLowEdge(eV)+0.1;
521 if (hfwd.GetBinContent(eV, 0) == 0) continue;
523 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
524 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
526 for (Int_t p = 1; p <= hfwd.GetNbinsY(); p++) {
527 Double_t phi = hfwd.GetYaxis()->GetBinCenter(p);
528 Double_t cont = hfwd.GetBinContent(eV, p);
529 fHistdNdedp3Cor.Fill(eta, phi, cont);
533 Int_t eSs = hcent.GetXaxis()->FindBin(-1.99);
534 Int_t eSe = hcent.GetXaxis()->FindBin(1.99);
535 for (Int_t eS = eSs; eS <= eSe; eS++) {
536 Double_t eta = hcent.GetXaxis()->GetBinCenter(eS);
537 if (hcent.GetBinContent(eS, 0) == 0) continue;
539 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
540 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
542 for (Int_t p = 1; p <= hcent.GetNbinsY(); p++) {
543 Double_t phi = hcent.GetYaxis()->GetBinCenter(p);
544 Double_t cont = hcent.GetBinContent(eS, p);
545 fHistdNdedp3Cor.Fill(eta, phi, cont);
549 return fHistdNdedp3Cor;
551 //_____________________________________________________________________
552 TObjArray* AliForwardFlowTaskQC::GetTracks() const
555 // Get TPC tracks to use for reference flow.
557 // Return: TObjArray with tracks
559 TObjArray* trList = 0;
561 UShort_t input = AliForwardUtil::CheckForAOD();
563 // If AOD input, simply get the track array from the event
564 case 1: trList = static_cast<TObjArray*>(fAOD->GetTracks());
567 // If ESD input get event, apply track cuts
568 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
570 // Warning! trList is now a new array, we need to delete it after use
571 // this is not a very good implementation!
572 trList = fESDTrackCuts->GetAcceptedTracks(esd, kTRUE);
575 default: AliFatal("Neither ESD or AOD input. This should never happen");
580 //_____________________________________________________________________
581 void AliForwardFlowTaskQC::Terminate(Option_t */*option*/)
584 // Calls the finalize function, done at the end of the analysis
590 // Make sure pointers are set to the correct lists
591 fSumList = dynamic_cast<TList*> (GetOutputData(1));
593 AliError("Could not retrieve TList fSumList");
597 fOutputList = new TList();
598 fOutputList->SetName("Results");
599 fOutputList->SetOwner();
601 if ((fFlowFlags & kEtaGap)) {
602 TParameter<Double_t>* etaGap = new TParameter<Double_t>("EtaGap", fEtaGap);
603 fOutputList->Add(etaGap);
605 // We only add axes in terminate, as TAxis object do not merge well,
606 // and so we get a mess when running on the grid if we put them in the sum list...
607 fVtxAxis->SetName("VtxAxis");
608 fOutputList->Add(fVtxAxis);
609 fCentAxis->SetName("CentAxis");
610 fOutputList->Add(fCentAxis);
612 // Run finalize on VertexBins
615 // Loop over output to get dN/deta hists - used for diagnostics
616 TIter next(fOutputList);
621 while ((o = next())) {
623 if (name.Contains("dNdeta")) {
624 dNdeta = dynamic_cast<TH2D*>(o);
625 name.ReplaceAll("dNdeta", "cent");
626 name.ReplaceAll("Ref", "");
627 name.ReplaceAll("Diff", "");
628 cent = dynamic_cast<TH1D*>(fOutputList->FindObject(name.Data()));
629 if (!dNdeta || !cent) continue;
630 for (Int_t cBin = 1; cBin <= dNdeta->GetNbinsY(); cBin++) {
631 Double_t nEvents = cent->GetBinContent(cBin);
632 if (nEvents == 0) continue;
633 for (Int_t eBin = 1; eBin <= dNdeta->GetNbinsX(); eBin++) {
634 dNdeta->SetBinContent(eBin, cBin, dNdeta->GetBinContent(eBin, cBin)/nEvents);
635 dNdeta->SetBinError(eBin, cBin, dNdeta->GetBinError(eBin, cBin)/nEvents);
641 // Loop over output and make 1D projections for fast look at results
642 MakeCentralityHists(fOutputList);
643 TList* vtxList = (TList*)fOutputList->FindObject("vtxList");
644 if (vtxList) MakeCentralityHists(vtxList);
645 TList* nuaList = (TList*)fOutputList->FindObject("NUATerms");
646 TIter nextNua(nuaList);
649 while ((o = nextNua())) {
650 if (!(h = dynamic_cast<TH2D*>(o))) continue;
651 Double_t evts = h->GetBinContent(0, 0);
652 if (evts != 0) h->Scale(1./evts);
654 if (nuaList) MakeCentralityHists(nuaList);
656 PostData(2, fOutputList);
660 //_____________________________________________________________________
661 void AliForwardFlowTaskQC::Finalize()
664 // Finalize command, called by Terminate()
667 // Reinitiate vertex bins if Terminate is called separately!
668 if (fBinsForward.GetEntries() == 0) InitVertexBins();
670 // Iterate over all vertex bins objects and finalize cumulants
672 EndVtxBinList(fBinsForward);
673 EndVtxBinList(fBinsCentral);
677 //_____________________________________________________________________
678 void AliForwardFlowTaskQC::EndVtxBinList(const TList& list) const
681 // Loop over VertexBin list and call terminate on each
684 // list: VertexBin list
688 while ((bin = static_cast<VertexBin*>(next()))) {
689 bin->CumulantsTerminate(fSumList, fOutputList);
693 // _____________________________________________________________________
694 void AliForwardFlowTaskQC::MakeCentralityHists(TList* list) const
697 // Loop over a list containing a TH2D with flow results
698 // and project to TH1's in specific centrality bins
701 // list: Flow results list
707 TIter nextHist(list);
708 while ((helper = dynamic_cast<TObject*>(nextHist()))) {
709 if (!(hist2D = dynamic_cast<TH2D*>(helper))) continue;
710 for (Int_t cBin = 1; cBin <= hist2D->GetNbinsY(); cBin++) {
711 Int_t cMin = Int_t(hist2D->GetYaxis()->GetBinLowEdge(cBin));
712 Int_t cMax = Int_t(hist2D->GetYaxis()->GetBinUpEdge(cBin));
713 TString name = Form("cent_%d-%d", cMin, cMax);
714 centList = (TList*)list->FindObject(name.Data());
716 centList = new TList();
717 centList->SetName(name.Data());
720 hist1D = hist2D->ProjectionX(Form("%s_%s", hist2D->GetName(), name.Data()),
722 hist1D->SetTitle(hist1D->GetName());
723 centList->Add(hist1D);
727 // _____________________________________________________________________
728 Bool_t AliForwardFlowTaskQC::CheckEvent(const AliAODForwardMult* aodfm)
731 // Function to check that an AOD event meets the cuts
734 // AliAODForwardMult: forward mult object with trigger and vertex info
736 // Return: false if there is no trigger or if the centrality or vertex
737 // is out of range. Otherwise true.
740 // First check for trigger
741 if (!CheckTrigger(aodfm)) {
742 fHistEventSel->Fill(kNoTrigger);
746 // Then check for centrality
747 if (!GetCentrality(aodfm)) {
751 // And finally check for vertex
752 if (!GetVertex(aodfm)) {
756 // Ev. accepted - filling diag. hists
757 fHistCent->Fill(fCent);
758 fHistVertexSel->Fill(fVtx);
759 fHistEventSel->Fill(kOK);
763 // _____________________________________________________________________
764 Bool_t AliForwardFlowTaskQC::CheckTrigger(const AliAODForwardMult* aodfm) const
767 // Function to look for a trigger string in the event.
768 // First check for info in forward mult object, if not there, use the AOD header
771 // AliAODForwardMult: forward mult object with trigger and vertex info
773 // Return: true if offline trigger is present
775 if (aodfm) return aodfm->IsTriggerBits(AliAODForwardMult::kOffline);
776 // this may need to be changed for 2011 data to handle kCentral and so on...
777 else return (((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))
778 ->IsEventSelected() & AliVEvent::kMB);
780 // _____________________________________________________________________
781 Bool_t AliForwardFlowTaskQC::GetCentrality(const AliAODForwardMult* aodfm)
784 // Function to look get centrality of the event.
785 // First check for info in forward mult object, if not there, use the AOD header
788 // AliAODForwardMult: forward mult object with trigger and vertex info
790 // Return: true if centrality determination is present
793 if (aodfm->HasCentrality()) {
794 fCent = (Double_t)aodfm->GetCentrality();
795 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
796 fHistEventSel->Fill(kInvCent);
802 fHistEventSel->Fill(kNoCent);
806 AliCentrality* aodCent = fAOD->GetCentrality();
808 fCent = (Double_t)aodCent->GetCentralityPercentile("V0M");
809 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
810 fHistEventSel->Fill(kInvCent);
816 fHistEventSel->Fill(kNoCent);
821 //_____________________________________________________________________
822 Bool_t AliForwardFlowTaskQC::GetVertex(const AliAODForwardMult* aodfm)
825 // Function to look for vertex determination in the event.
826 // First check for info in forward mult object, if not there, use the AOD header
829 // AliAODForwardMult: forward mult object with trigger and vertex info
831 // Return: true if vertex is determined
834 if (aodfm->HasIpZ()) {
835 fVtx = aodfm->GetIpZ();
836 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
837 fHistEventSel->Fill(kInvVtx);
842 fHistEventSel->Fill(kNoVtx);
847 AliAODVertex* aodVtx = fAOD->GetPrimaryVertex();
849 fVtx = aodVtx->GetZ();
850 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
851 fHistEventSel->Fill(kInvVtx);
856 fHistEventSel->Fill(kNoVtx);
862 // _____________________________________________________________________
863 void AliForwardFlowTaskQC::FillVZEROHist(AliAODVZERO* aodVZero)
866 // Loops over VZERO data object and fill up d^2N/detadphi histogram for flow analysis
869 // aodVZero: VZERO AOD data object
874 // Sort of right for 2010 data, do not use for 2011!
875 Double_t eq[64] = { 1.43536, 1.45727, 1.44993, 1.30051, 1.17425, 1.2335, 1.22247, 1.14362,
876 1.14647, 1.25208, 1.17681, 1.21642, 1.16604, 1.05532, 1.03212, 1.1032,
877 1.22941, 1.36986, 1.14652, 1.20056, 0.927086, 1.10809, 1.03343, 1.29472,
878 1.21204, 1.29217, 1.2003, 2.10382, 1.28513, 1.40558, 1.25784, 1.21848,
879 0.475162, 0.50421, 0.503617, 0.512471, 0.515276, 0.39831, 0.415199, 0.444664,
880 0.521922, 0.785915, 0.703658, 0.832479, 0.77461, 0.73129, 0.778697, 0.710265,
881 0.89686, 0.967688, 0.974225, 0.873445, 0.811096, 0.828493, 0.889609, 0.586056,
882 1.15877, 0.954656, 0.914557, 0.979028, 1.04907, 0.748518, 0.928043, 0.98175 };
883 for (Int_t i = 0; i < 64; i++) {
886 bin = (ring < 5 ? ring+1 : 15-ring);
887 eta = fHistdNdedpV0.GetXaxis()->GetBinCenter(bin);
888 fHistdNdedpV0.SetBinContent(bin, 0, 1);
890 Float_t amp = aodVZero->GetMultiplicity(i);
892 Double_t phi = TMath::Pi()/8.+TMath::TwoPi()*i/8.;
893 while (phi > TMath::TwoPi()) phi -= TMath::TwoPi();
894 fHistdNdedpV0.Fill(eta, phi, amp);
897 //_____________________________________________________________________
898 AliForwardFlowTaskQC::VertexBin::VertexBin()
900 fMaxMoment(0), // Max flow moment for this vertexbin
901 fVzMin(0), // Vertex z-coordinate min [cm]
902 fVzMax(0), // Vertex z-coordinate max [cm]
903 fType(), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
904 fFlags(0), // Flow flags
905 fSigmaCut(-1), // Sigma cut to remove outlier events
906 fEtaGap(-1), // Eta gap value
907 fEtaLims(), // Limits for binning in 3Cor method
908 fCumuRef(), // Histogram for reference flow
909 fCumuDiff(), // Histogram for differential flow
910 fCumuHists(0,0), // CumuHists object for keeping track of results
911 fCumuNUARef(), // Histogram for ref NUA terms
912 fCumuNUADiff(), // Histogram for diff NUA terms
913 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
914 fdNdedpDiffAcc(),// Diagnostics histogram for acc. maps
915 fOutliers(), // Histogram for sigma distribution
916 fDebug() // Debug level
919 // Default constructor
922 //_____________________________________________________________________
923 AliForwardFlowTaskQC::VertexBin::VertexBin(Int_t vLow, Int_t vHigh,
924 UShort_t moment, TString name,
925 UShort_t flags, Double_t cut,
928 fMaxMoment(moment), // Max flow moment for this vertexbin
929 fVzMin(vLow), // Vertex z-coordinate min [cm]
930 fVzMax(vHigh), // Vertex z-coordinate max [cm]
931 fType(name), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
932 fFlags(flags), // Flow flags
933 fSigmaCut(cut), // Sigma cut to remove outlier events
934 fEtaGap(etaGap), // Eta gap value
935 fEtaLims(), // Limits for binning in 3Cor method
936 fCumuRef(), // Histogram for reference flow
937 fCumuDiff(), // Histogram for differential flow
938 fCumuHists(moment,0),// CumuHists object for keeping track of results
939 fCumuNUARef(), // Histogram for ref NUA terms
940 fCumuNUADiff(), // Histogram for diff NUA terms
941 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
942 fdNdedpDiffAcc(), // Diagnostics histogram for acc. maps
943 fOutliers(), // Histogram for sigma distribution
944 fDebug(0) // Debug level
950 // vLow: min z-coordinate
951 // vHigh: max z-coordinate
952 // moment: max flow moment
953 // name: data type name (FMD/SPD/FMDTR/SPDTR/MC)
956 // etaGap: eta-gap value
960 SetName(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
961 SetTitle(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
963 fDebug = AliAnalysisManager::GetAnalysisManager()->GetDebugLevel();
964 if (fDebug > 0) Printf("AliForwardFlowTaskQC::VertexBin()\tDebugMode: %d", fDebug);
966 // Set limits for 3 correlator method
967 if ((fFlags & kFMD)) {
974 } else if ((fFlags & kVZERO)) {
983 //_____________________________________________________________________
984 AliForwardFlowTaskQC::VertexBin&
985 AliForwardFlowTaskQC::VertexBin::operator=(const AliForwardFlowTaskQC::VertexBin& o)
988 // Assignment operator
991 // o: AliForwardFlowTaskQC::VertexBin
993 if (&o == this) return *this;
994 fMaxMoment = o.fMaxMoment;
999 fSigmaCut = o.fSigmaCut;
1000 fEtaGap = o.fEtaGap;
1001 fCumuRef = o.fCumuRef;
1002 fCumuDiff = o.fCumuDiff;
1003 fCumuHists = o.fCumuHists;
1004 fCumuNUARef = o.fCumuNUARef;
1005 fCumuNUADiff = o.fCumuNUADiff;
1006 fdNdedpRefAcc = o.fdNdedpRefAcc;
1007 fdNdedpDiffAcc = o.fdNdedpDiffAcc;
1008 fOutliers = o.fOutliers;
1010 for (UInt_t i = 0; i < sizeof(fEtaLims)/sizeof(Int_t); i++) fEtaLims[i] = o.fEtaLims[i];
1014 //_____________________________________________________________________
1015 void AliForwardFlowTaskQC::VertexBin::AddOutput(TList* outputlist, TAxis* centAxis)
1018 // Add histograms to outputlist
1021 // outputlist: list of histograms
1022 // centAxis: centrality axis
1025 // First we try to find an outputlist for this vertexbin
1026 TList* list = (TList*)outputlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1027 // If it doesn't exist we make one
1030 list->SetName(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1031 outputlist->Add(list);
1034 // Get bin numbers and binning defined
1035 Int_t nHBins = GetBinNumberSin();
1036 Int_t nEtaBins = 48;
1037 if ((fFlags & k3Cor)) {
1038 if ((fFlags & kFMD)) nEtaBins = 24;
1039 else if ((fFlags & kVZERO)) nEtaBins = 19;
1041 else if ((fFlags & kVZERO) && !fType.Contains("SPD")) nEtaBins = 11;
1042 Double_t vzeroBins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
1043 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
1044 Double_t vzeroBins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
1045 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
1046 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
1048 // We initiate the reference histogram
1049 fCumuRef = new TH2D(Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1050 Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1051 ((fFlags & k3Cor) ? 24 : ((fFlags & kEtaGap) || !(fFlags & kSymEta) ? 2 : 1)), -6., 6.,
1052 nHBins, 0.5, nHBins+0.5);
1053 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuRef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1054 SetupNUALabels(fCumuRef->GetYaxis());
1055 list->Add(fCumuRef);
1057 // We initiate the differential histogram
1058 fCumuDiff = new TH2D(Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1059 Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1060 nEtaBins, -6., 6., nHBins, 0.5, nHBins+0.5);
1061 if ((fFlags & kVZERO)) {
1062 if ((fFlags & k3Cor)) fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1063 else if (!fType.Contains("SPD")) fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins);
1065 SetupNUALabels(fCumuDiff->GetYaxis());
1066 list->Add(fCumuDiff);
1068 // Cumulants sum hists
1069 Int_t cBins = centAxis->GetNbins();
1070 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1072 Int_t nC2Bins = ((fFlags & kEtaGap) || (fFlags & k3Cor) ? kW2 : k3pWeight);
1073 Int_t nC4Bins = ((fFlags & kEtaGap) ? kW2 : ((fFlags & k3Cor) ? kW4 : kSinphi1phi2phi3p));
1074 for (Int_t n = 2; n <= fMaxMoment; n++) {
1075 // Initiate the ref cumulant sum histogram
1076 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1077 Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1078 ((fFlags & k3Cor) ? 24 : ((fFlags & kEtaGap) || !(fFlags & kSymEta) ? 2 : 1)), -6., 6.,
1079 cBins, 0., 100., nC2Bins, 0.5, nC2Bins+0.5);
1080 if ((fFlags & kVZERO) && (fFlags & k3Cor)) cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1081 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1082 fCumuHists.Add(cumuHist);
1083 // Initiate the diff cumulant sum histogram
1084 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1085 Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1086 nEtaBins, -6., 6., cBins, 0., 100., nC4Bins, 0.5, nC4Bins+0.5);
1087 if ((fFlags & kVZERO)) {
1088 if ((fFlags & k3Cor)) cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1089 else if (!fType.Contains("SPD")) cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins);
1091 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1092 fCumuHists.Add(cumuHist);
1095 // Common NUA histograms
1096 fCumuNUARef = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1097 Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1098 ((fFlags & k3Cor) ? 24 : ((fFlags & kEtaGap) || !(fFlags & kSymEta) ? 2 : 1)), -6., 6.,
1099 cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1100 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuNUARef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1101 fCumuNUARef->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1102 SetupNUALabels(fCumuNUARef->GetZaxis());
1103 fCumuNUARef->Sumw2();
1104 list->Add(fCumuNUARef);
1106 fCumuNUADiff = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1107 Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1108 nEtaBins, -6., 6., cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1109 if ((fFlags & kVZERO)) {
1110 if ((fFlags & k3Cor)) fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1111 else if (!fType.Contains("SPD")) fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins);
1113 fCumuNUADiff->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1114 SetupNUALabels(fCumuNUADiff->GetZaxis());
1115 fCumuNUADiff->Sumw2();
1116 list->Add(fCumuNUADiff);
1118 // We create diagnostic histograms.
1119 TList* dList = (TList*)outputlist->FindObject("Diagnostics");
1120 if (!dList) AliFatal("No diagnostics list found");
1123 Double_t nPhiBins = ((fFlags & kFMD) ? 20 : 8);
1124 fdNdedpRefAcc = new TH2F(Form("h%sdNdedpRefAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1125 Form("%s reference flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
1126 nEtaBins, -6, 6, nPhiBins, 0, TMath::TwoPi());
1127 if ((fFlags & kVZERO)) {
1128 if ((fFlags & k3Cor)) fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1129 else if (!fType.Contains("SPD")) fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
1131 dList->Add(fdNdedpRefAcc);
1133 fdNdedpDiffAcc = new TH2F(Form("h%sdNdedpDiffAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1134 Form("%s differential flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
1135 nEtaBins, -6, 6, nPhiBins, 0, TMath::TwoPi());
1136 if ((fFlags & kVZERO)) {
1137 if ((fFlags & k3Cor)) fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1138 else if (!fType.Contains("SPD")) fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
1140 dList->Add(fdNdedpDiffAcc);
1142 fOutliers = new TH2F(Form("hOutliers_%s_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1143 Form("Maximum #sigma from mean N_{ch} pr. bin - %s, %d < v_{z} < %d",
1144 fType.Data(), fVzMin, fVzMax),
1145 20, 0., 100., 500, 0., (fType.Contains("MC") ? 15. : 5.));
1146 dList->Add(fOutliers);
1150 //_____________________________________________________________________
1151 Bool_t AliForwardFlowTaskQC::VertexBin::FillHists(TH2D& dNdetadphi, Double_t cent, UShort_t mode)
1154 // Fill reference and differential eta-histograms
1157 // dNdetadphi: 2D histogram with input data
1159 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
1161 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1162 Bool_t useEvent = kTRUE;
1164 // Fist we reset histograms
1165 if ((mode & kReset)) {
1166 if ((mode & kFillRef)) fCumuRef->Reset();
1167 if ((mode & kFillDiff)) fCumuDiff->Reset();
1170 // Then we loop over the input and calculate sum cos(k*n*phi)
1171 // and fill it in the reference and differential histograms
1173 Double_t limit = 9999.;
1174 for (Int_t etaBin = 1; etaBin <= dNdetadphi.GetNbinsX(); etaBin++) {
1175 Double_t eta = dNdetadphi.GetXaxis()->GetBinCenter(etaBin);
1176 // Numbers to cut away bad events
1177 Double_t runAvg = 0;
1180 Double_t avgSqr = 0;
1181 for (Int_t phiBin = 0; phiBin <= dNdetadphi.GetNbinsY(); phiBin++) {
1182 // Check for acceptance
1184 if (dNdetadphi.GetBinContent(etaBin, 0) == 0) break;
1185 // Central limit for eta gap break for reference flow
1186 if ((fFlags & kEtaGap) && (mode & kFillRef) &&
1187 TMath::Abs(eta) < fEtaGap) break;
1188 // Backward and forward eta gap break for reference flow
1189 if ((fFlags & kEtaGap) && (mode & kFillRef) && TMath::Abs(eta) > TMath::Abs(limit)) break;
1190 if (limit > 1e3) limit = dNdetadphi.GetXaxis()->GetBinLowEdge(etaBin);
1192 } // End of phiBin == 0
1193 Double_t phi = dNdetadphi.GetYaxis()->GetBinCenter(phiBin);
1194 Double_t weight = dNdetadphi.GetBinContent(etaBin, phiBin);
1196 // We calculate the average Nch per. bin
1197 avgSqr += weight*weight;
1200 if (weight == 0) continue;
1201 if (weight > max) max = weight;
1203 // Fill into Cos() and Sin() hists
1204 if ((mode & kFillRef)) {
1205 fCumuRef->Fill(eta, 0., weight);// mult goes in underflowbin - no visual, but not needed?
1206 fdNdedpRefAcc->Fill(eta, phi, weight);
1208 if ((mode & kFillDiff)) {
1209 fCumuDiff->Fill(eta, 0., weight);
1210 fdNdedpDiffAcc->Fill(eta, phi, weight);
1212 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1213 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1214 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1215 Double_t cosnPhi = weight*TMath::Cos(n*phi);
1216 Double_t sinnPhi = weight*TMath::Sin(n*phi);
1218 if ((mode & kFillRef)) {
1219 fCumuRef->Fill(eta, cosBin, cosnPhi);
1220 fCumuRef->Fill(eta, sinBin, sinnPhi);
1223 if ((mode & kFillDiff)) {
1224 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1225 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1227 } // End of NUA loop
1228 } // End of phi loop
1229 // Outlier cut calculations
1233 Double_t stdev = (nInAvg > 1 ? TMath::Sqrt(nInAvg/(nInAvg-1))*TMath::Sqrt(avgSqr - runAvg*runAvg) : 0);
1234 Double_t nSigma = (stdev == 0 ? 0 : (max-runAvg)/stdev);
1235 if (fSigmaCut > 0. && nSigma >= fSigmaCut && cent < 60) nBadBins++;
1237 fOutliers->Fill(cent, nSigma);
1238 // We still finish the loop, for fOutliers to make sense,
1239 // but we do no keep the event for analysis
1240 if (nBadBins > 3) useEvent = kFALSE;
1246 //_____________________________________________________________________
1247 Bool_t AliForwardFlowTaskQC::VertexBin::FillTracks(TObjArray* trList, UShort_t mode)
1250 // Fill reference and differential eta-histograms
1253 // trList: list of tracks
1254 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
1256 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1258 // Fist we reset histograms
1259 if ((mode & kReset)) {
1260 if ((mode & kFillRef)) fCumuRef->Reset();
1261 if ((mode & kFillDiff)) fCumuDiff->Reset();
1264 UShort_t input = AliForwardUtil::CheckForAOD();
1265 // Then we loop over the input and calculate sum cos(k*n*phi)
1266 // and fill it in the reference and differential histograms
1267 Int_t nTr = trList->GetEntries();
1268 if (nTr == 0) return kFALSE;
1270 AliAODTrack* aodTr = 0;
1271 // Cuts for AOD tracks (have already been applied to ESD tracks)
1272 const Double_t pTMin = 0.5, pTMax = 20., etaMin = -0.8, etaMax = 0.8, minNCl = 50;
1273 for (Int_t i = 0; i < nTr; i++) { // track loop
1274 tr = (AliVTrack*)trList->At(i);
1276 if (input == 1) { // If AOD input
1277 // A dynamic cast would be more safe here, but this is faster...
1278 aodTr = (AliAODTrack*)tr;
1279 if (aodTr->GetID() > -1) continue;
1280 if (!aodTr->TestFilterBit(128) || !aodTr->Pt() > pTMax || aodTr->Pt() < pTMin ||
1281 aodTr->Eta() > etaMax || aodTr->Eta() < etaMin || aodTr->GetTPCNcls() < minNCl) continue;
1284 Double_t eta = tr->Eta();
1285 Double_t phi = tr->Phi();
1286 if ((mode & kFillRef)) {
1287 fCumuRef->Fill(eta, 0.);// mult goes in underflowbin - no visual, but not needed?
1288 fdNdedpRefAcc->Fill(eta, phi);
1290 if ((mode & kFillDiff)) {
1291 fCumuDiff->Fill(eta, 0);
1292 fdNdedpDiffAcc->Fill(eta, phi);
1294 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1295 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1296 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1297 Double_t cosnPhi = TMath::Cos(n*phi);
1298 Double_t sinnPhi = TMath::Sin(n*phi);
1300 if ((mode & kFillRef)) {
1301 fCumuRef->Fill(eta, cosBin, cosnPhi);
1302 fCumuRef->Fill(eta, sinBin, sinnPhi);
1305 if ((mode & kFillDiff)) {
1306 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1307 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1309 } // End of NUA loop
1310 } // End of track loop
1313 //_____________________________________________________________________
1314 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate(Double_t cent)
1317 // Calculate the Q cumulant up to order fMaxMoment
1320 // cent: centrality of event
1322 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1324 // Fill out NUA hists
1325 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1326 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1327 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1328 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1329 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1332 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1333 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1334 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1335 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1336 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1340 // We create the objects needed for the analysis
1343 // For each n we loop over the hists
1344 for (Int_t n = 2; n <= fMaxMoment; n++) {
1345 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1346 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1347 Int_t prevRefEtaBin = 0;
1349 // Per mom. quantities
1350 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1351 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1352 Double_t dQ2nReA = 0, dQ2nImA = 0;
1353 Double_t two = 0, w2 = 0, four = 0, w4 = 0;
1354 Double_t cosPhi1Phi2 = 0, cosPhi1Phi2Phi3m = 0;
1355 Double_t sinPhi1Phi2 = 0, sinPhi1Phi2Phi3m = 0;
1356 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1357 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1358 Int_t refEtaBinA = fCumuRef->GetXaxis()->FindBin(eta);
1359 Int_t refEtaBinB = fCumuRef->GetXaxis()->FindBin(-eta);
1360 if (refEtaBinA != prevRefEtaBin) {
1361 prevRefEtaBin = refEtaBinA;
1363 multA = fCumuRef->GetBinContent(refEtaBinA, 0);
1364 dQnReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n));
1365 dQnImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n));
1366 dQ2nReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n*2));
1367 dQ2nImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n*2));
1369 multB = fCumuRef->GetBinContent(refEtaBinB, 0);
1370 dQnReB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberCos(n));
1371 dQnImB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberSin(n));
1373 if (multA <= 3 || multB <= 3) return;
1374 // The reference flow is calculated
1376 if ((fFlags & kStdQC)) {
1377 w2 = multA * (multA - 1.);
1378 two = dQnReA*dQnReA + dQnImA*dQnImA - multA;
1381 two = dQnReA*dQnReB + dQnImA*dQnImB;
1383 cumuRef->Fill(eta, cent, kW2Two, two);
1384 cumuRef->Fill(eta, cent, kW2, w2);
1386 // The reference flow is calculated
1388 if ((fFlags & kStdQC)) {
1389 w4 = multA * (multA - 1.) * (multA - 2.) * (multA - 3.);
1391 four = 2.*multA*(multA-3.) + TMath::Power((TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.)),2.)
1392 -4.*(multA-2.)*(TMath::Power(dQnReA,2.) + TMath::Power(dQnImA,2.))
1393 -2.*(TMath::Power(dQnReA,2.)*dQ2nReA+2.*dQnReA*dQnImA*dQ2nImA-TMath::Power(dQnImA,2.)*dQ2nReA)
1394 +(TMath::Power(dQ2nReA,2.)+TMath::Power(dQ2nImA,2.));
1396 cumuRef->Fill(eta, cent, kW4Four, four);
1397 cumuRef->Fill(eta, cent, kW4, w4);
1400 cosPhi1Phi2 = dQnReA*dQnReA - dQnImA*dQnImA - dQ2nReA;
1401 sinPhi1Phi2 = 2.*dQnReA*dQnImA - dQ2nImA;
1403 cosPhi1Phi2Phi3m = dQnReA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1404 -dQnReA*dQ2nReA-dQnImA*dQ2nImA-2.*(multA-1)*dQnReA;
1406 sinPhi1Phi2Phi3m = -dQnImA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1407 +dQnReA*dQ2nImA-dQnImA*dQ2nReA+2.*(multA-1)*dQnImA;
1409 cumuRef->Fill(eta, cent, kCosphi1phi2, cosPhi1Phi2);
1410 cumuRef->Fill(eta, cent, kSinphi1phi2, sinPhi1Phi2);
1411 cumuRef->Fill(eta, cent, kCosphi1phi2phi3m, cosPhi1Phi2Phi3m);
1412 cumuRef->Fill(eta, cent, kSinphi1phi2phi3m, sinPhi1Phi2Phi3m);
1413 cumuRef->Fill(eta, cent, k3pWeight, multA*(multA-1.)*(multA-2.));
1415 } // End of reference flow
1416 // For each etaBin bin the necessary values for differential flow is calculated
1417 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1418 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1419 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1420 Double_t p2nRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n*2));
1421 Double_t p2nIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n*2));
1422 if (mp == 0) continue;
1429 // Differential flow calculations for each eta bin is done:
1430 // 2-particle differential flow
1431 if ((fFlags & kStdQC) && !(fFlags & kTPC)) {
1439 Double_t w2p = mp * multB - mq;
1440 Double_t twoPrime = pnRe*dQnReB + pnIm*dQnImB - mq;
1442 cumuDiff->Fill(eta, cent, kW2Two, twoPrime);
1443 cumuDiff->Fill(eta, cent, kW2, w2p);
1445 if ((fFlags & kEtaGap)) continue;
1446 // Differential flow calculations for each eta bin bin is done:
1447 // 4-particle differential flow
1448 Double_t w4p = (mp * multA - 3.*mq)*(multA - 1.)*(multA - 2.);
1450 Double_t fourPrime = (TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*(pnRe*dQnReA+pnIm*dQnImA)
1451 - q2nRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))
1452 - 2.*q2nIm*dQnReA*dQnImA
1453 - pnRe*(dQnReA*dQ2nReA+dQnImA*dQ2nImA)
1454 + pnIm*(dQnImA*dQ2nReA-dQnReA*dQ2nImA)
1455 - 2.*multA*(pnRe*dQnReA+pnIm*dQnImA)
1456 - 2.*(TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*mq
1457 + 6.*(qnRe*dQnReA+qnIm*dQnImA)
1458 + 1.*(q2nRe*dQ2nReA+q2nIm*dQ2nImA)
1459 + 2.*(pnRe*dQnReA+pnIm*dQnImA)
1463 cumuDiff->Fill(eta, cent, kW4Four, fourPrime);
1464 cumuDiff->Fill(eta, cent, kW4, w4p);
1467 Double_t cosPsi1Phi2 = pnRe*dQnReA - pnIm*dQnImA - q2nRe;
1468 Double_t sinPsi1Phi2 = pnRe*dQnImA + pnIm*dQnReA - q2nIm;
1470 Double_t cosPsi1Phi2Phi3p = pnRe*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1471 - 1.*(q2nRe*dQnReA+q2nIm*dQnImA)
1472 - mq*dQnReA+2.*qnRe;
1474 Double_t sinPsi1Phi2Phi3p = pnIm*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1475 - 1.*(q2nIm*dQnReA-q2nRe*dQnImA)
1476 - mq*dQnImA+2.*qnIm;
1478 Double_t cosPsi1Phi2Phi3m = pnRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))+2.*pnIm*dQnReA*dQnImA
1479 - 1.*(pnRe*dQ2nReA+pnIm*dQ2nImA)
1480 - 2.*mq*dQnReA+2.*qnRe;
1482 Double_t sinPsi1Phi2Phi3m = pnIm*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))-2.*pnRe*dQnReA*dQnImA
1483 - 1.*(pnIm*dQ2nReA-pnRe*dQ2nImA)
1484 + 2.*mq*dQnImA-2.*qnIm;
1486 cumuDiff->Fill(eta, cent, kCosphi1phi2, cosPsi1Phi2);
1487 cumuDiff->Fill(eta, cent, kSinphi1phi2, sinPsi1Phi2);
1488 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3m, cosPsi1Phi2Phi3m);
1489 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3m, sinPsi1Phi2Phi3m);
1490 cumuDiff->Fill(eta, cent, k3pWeight, (mp*multA-2.*mq)*(multA-1.));
1491 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3p, cosPsi1Phi2Phi3p);
1492 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3p, sinPsi1Phi2Phi3p);
1493 } // End of eta loop
1495 cumuRef->Fill(-7., cent, -0.5, 1.);
1496 } // End of moment loop
1499 //_____________________________________________________________________
1500 void AliForwardFlowTaskQC::VertexBin::GetLimits(Int_t bin, Int_t& aLow, Int_t& aHigh,
1501 Int_t& bLow, Int_t& bHigh) const
1504 // Get the limits for the 3 correlator method
1507 // bin : reference bin #
1508 // aLow : Lowest bin to be included in v_A calculations
1509 // aHigh: Highest bin to be included in v_A calculations
1510 // bLow : Lowest bin to be included in v_B calculations
1511 // bHigh: Highest bin to be included in v_B calculations
1513 if ((fFlags & kFMD)) {
1516 aLow = 14; aHigh = 15;
1517 bLow = 20; bHigh = 22;
1520 aLow = 16; aHigh = 16;
1521 bLow = 21; bHigh = 22;
1524 aLow = 6; aHigh = 7;
1525 bLow = 21; bHigh = 22;
1528 aLow = 6; aHigh = 7;
1529 bLow = 12; bHigh = 12;
1532 aLow = 6; aHigh = 8;
1533 bLow = 13; bHigh = 14;
1536 AliFatal(Form("No limits for this eta region! (%d)", bin));
1539 else if ((fFlags & kVZERO)) {
1542 aLow = 6; aHigh = 13;
1543 bLow = 17; bHigh = 18;
1546 aLow = 6; aHigh = 9;
1547 bLow = 17; bHigh = 18;
1550 aLow = 2; aHigh = 3;
1551 bLow = 17; bHigh = 18;
1554 aLow = 2; aHigh = 3;
1555 bLow = 6; bHigh = 9;
1558 aLow = 2; aHigh = 3;
1559 bLow = 6; bHigh = 13;
1562 AliFatal(Form("No limits for this eta region! (%d)", bin));
1565 // Try to catch cases where fEtaLimits and these values do not correspond to each other
1566 if (aHigh > fCumuNUARef->GetNbinsX() || bHigh > fCumuNUARef->GetNbinsX())
1567 AliFatal(Form("Limits outside vtx range! (%d) - aHigh = %d, bHigh = %d, Nbins = %d",
1568 bin, aHigh, bHigh, fCumuNUARef->GetNbinsX()));
1570 //_____________________________________________________________________
1571 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate3Cor(Double_t cent)
1574 // Calculate the Q cumulant up to order fMaxMoment
1577 // cent: centrality of event
1579 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
1581 // Fill out NUA hists
1582 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1583 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1584 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1585 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1586 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1589 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1590 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1591 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1592 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1593 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1597 // We create the objects needed for the analysis
1600 // For each n we loop over the hists
1601 for (Int_t n = 2; n <= fMaxMoment; n++) {
1602 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1603 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1605 // Per mom. quantities
1607 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
1608 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1609 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1610 Double_t two = 0, w2 = 0;
1611 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1612 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1613 if (fEtaLims[prevLim] < eta) {
1614 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
1616 multA = 0; dQnReA = 0; dQnImA = 0;
1617 multB = 0; dQnReB = 0; dQnImB = 0;
1619 for (Int_t a = aLow; a <= aHigh; a++) {
1620 multA += fCumuRef->GetBinContent(a, 0);
1621 dQnReA += fCumuRef->GetBinContent(a, GetBinNumberCos(n));
1622 dQnImA += fCumuRef->GetBinContent(a, GetBinNumberSin(n));
1624 for (Int_t b = bLow; b <= bHigh; b++) {
1625 multB += fCumuRef->GetBinContent(b, 0);
1626 dQnReB += fCumuRef->GetBinContent(b, GetBinNumberCos(n));
1627 dQnImB += fCumuRef->GetBinContent(b, GetBinNumberSin(n));
1629 // The reference flow is calculated
1632 two = dQnReA*dQnReB + dQnImA*dQnImB;
1633 } // End of reference flow
1634 cumuRef->Fill(eta, cent, kW2Two, two);
1635 cumuRef->Fill(eta, cent, kW2, w2);
1637 // For each etaBin bin the necessary values for differential flow is calculated
1638 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1639 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1640 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1641 if (mp == 0) continue;
1643 // Differential flow calculations for each eta bin is done:
1644 // 2-particle differential flow
1645 Double_t w2pA = mp * multA;
1646 Double_t twoPrimeA = pnRe*dQnReA + pnIm*dQnImA;
1647 cumuDiff->Fill(eta, cent, kW2Two, twoPrimeA);
1648 cumuDiff->Fill(eta, cent, kW2, w2pA);
1650 Double_t w2pB = mp * multB;
1651 Double_t twoPrimeB = pnRe*dQnReB + pnIm*dQnImB;
1652 cumuDiff->Fill(eta, cent, kW4Four, twoPrimeB);
1653 cumuDiff->Fill(eta, cent, kW4, w2pB);
1654 } // End of eta loop
1656 cumuRef->Fill(-7., cent, -0.5, 1.);
1657 } // End of moment loop
1661 //_____________________________________________________________________
1662 void AliForwardFlowTaskQC::VertexBin::CumulantsTerminate(TList* inlist, TList* outlist)
1665 // Finalizes the Q cumulant calculations
1668 // inlist: input sumlist
1669 // outlist: output result list
1672 // Re-find cumulants hist if Terminate is called separately
1673 if (!fCumuHists.IsConnected()) {
1674 TList* list = (TList*)inlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1675 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1678 fCumuNUARef = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1680 fCumuNUADiff = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1682 // Clone to avoid normalization problems when redoing terminate locally
1683 fCumuNUARef = (TH3D*)fCumuNUARef->Clone(Form("%s_vertex_%d_%d%s_cumuNUARefNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1684 fCumuNUADiff = (TH3D*)fCumuNUADiff->Clone(Form("%s_vertex_%d_%d%s_cumuNUADiffNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1686 // Diagnostics histograms
1687 TH2I* quality = (TH2I*)outlist->FindObject(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1689 quality = MakeQualityHist(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1690 outlist->Add(quality);
1692 TH1D* cent = (TH1D*)outlist->FindObject(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)));
1694 cent = new TH1D(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1695 Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1696 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1697 cent->GetXaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1700 TH2D* dNdetaRef = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)));
1702 dNdetaRef = new TH2D(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1703 Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1704 fCumuNUARef->GetNbinsX(), fCumuNUARef->GetXaxis()->GetXmin(), fCumuNUARef->GetXaxis()->GetXmax(),
1705 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1706 dNdetaRef->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1708 outlist->Add(dNdetaRef);
1710 TH2D* dNdetaDiff = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)));
1712 dNdetaDiff = new TH2D(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1713 Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1714 fCumuNUADiff->GetNbinsX(), fCumuNUADiff->GetXaxis()->GetXmin(), fCumuNUADiff->GetXaxis()->GetXmax(),
1715 fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXmin(), fCumuNUADiff->GetYaxis()->GetXmax());
1716 dNdetaDiff->GetYaxis()->Set(fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXbins()->GetArray());
1717 dNdetaDiff->Sumw2();
1718 outlist->Add(dNdetaDiff);
1721 // Setting up outputs
1722 // Create output lists and diagnostics
1723 TList* vtxList = (TList*)outlist->FindObject("vtxList");
1725 vtxList = new TList();
1726 vtxList->SetName("vtxList");
1727 outlist->Add(vtxList);
1729 vtxList->Add(fCumuNUARef);
1730 vtxList->Add(fCumuNUADiff);
1732 // Setup output profiles
1733 CumuHistos cumu2(fMaxMoment, ((fFlags & kNUAcorr) ? 2 : 0));
1734 CumuHistos cumu4(fMaxMoment, ((fFlags & kNUAcorr) ? 1 : 0));
1736 cumu2.ConnectList(Form("%sQC2_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1737 if ((fFlags & kStdQC))
1738 cumu4.ConnectList(Form("%sQC4_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1740 for (Int_t n = 2; n <= fMaxMoment; n++) {
1742 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNoNUA));
1743 if ((fFlags & k3Cor)){
1744 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNoNUA));
1745 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNoNUA));
1747 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNoNUA));
1750 if ((fFlags & kStdQC)) {
1751 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNoNUA));
1752 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNoNUA));
1754 } // End of v_n result loop
1756 if ((fFlags & kNUAcorr)) {
1757 for (Int_t n = 2; n <= fMaxMoment; n++) {
1759 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUAOld));
1760 if ((fFlags & k3Cor)) {
1761 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUAOld));
1762 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUAOld));
1764 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUAOld));
1767 if ((fFlags & kStdQC)) {
1768 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNUAOld));
1769 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNUAOld));
1772 for (Int_t n = 2; n <= fMaxMoment; n++) {
1774 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUA));
1775 if ((fFlags & k3Cor)) {
1776 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUA));
1777 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUA));
1779 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUA));
1784 // Calculating the cumulants
1785 if ((fFlags & k3Cor)) {
1786 Calculate3CorFlow(cumu2, quality, cent, dNdetaRef, dNdetaDiff);
1788 CalculateReferenceFlow(cumu2, cumu4, quality, cent, dNdetaRef);
1789 CalculateDifferentialFlow(cumu2, cumu4, quality, dNdetaDiff);
1791 if ((fFlags & kNUAcorr)) {
1792 SolveCoupledFlowEquations(cumu2, 'r');
1793 if ((fFlags & k3Cor)) {
1794 SolveCoupledFlowEquations(cumu2, 'a');
1795 SolveCoupledFlowEquations(cumu2, 'b');
1797 SolveCoupledFlowEquations(cumu2, 'd');
1801 // Add to output for immediate viewing - individual vtx bins are used for final results
1802 AddVertexBins(cumu2, outlist, ((fFlags & kNUAcorr) ? 2 : 0));
1803 if ((fFlags & kStdQC)) AddVertexBins(cumu4, outlist, ((fFlags & kNUAcorr) ? 1 : 0));
1805 // Setup NUA diagnoastics histograms
1806 TList* nualist = (TList*)outlist->FindObject("NUATerms");
1808 nualist = new TList();
1809 nualist->SetName("NUATerms");
1810 outlist->Add(nualist);
1813 TH2D* nuaRef = (TH2D*)nualist->FindObject(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1816 nuaRef = (TH2D*)fCumuNUARef->Project3D("yz");
1817 nuaRef->Scale(1./fCumuNUARef->GetNbinsX());
1818 nuaRef->SetName(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1819 nuaRef->SetTitle(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1820 nualist->Add(nuaRef);
1822 temp = (TH2D*)fCumuNUARef->Project3D("yz");
1823 temp->Scale(1./fCumuNUARef->GetNbinsX());
1827 // Filling in underflow to make scaling possible in Terminate()
1828 nuaRef->Fill(0., -1., 1.);
1830 TH2D* nuaDiff = (TH2D*)nualist->FindObject(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1832 nuaDiff = (TH2D*)fCumuNUADiff->Project3D("yz");
1833 nuaDiff->SetName(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1834 nuaDiff->SetTitle(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1835 nualist->Add(nuaDiff);
1837 temp = (TH2D*)fCumuNUADiff->Project3D("yz");
1841 // Filling in underflow to make scaling possible in Terminate()
1842 nuaDiff->Fill(0., -1., 1.);
1846 //_____________________________________________________________________
1847 void AliForwardFlowTaskQC::VertexBin::CalculateReferenceFlow(CumuHistos& cumu2h, CumuHistos& cumu4h, TH2I* quality,
1848 TH1D* chist, TH2D* dNdetaRef) const
1851 // Calculates the reference flow
1854 // cumu2h: CumuHistos object with QC{2} cumulants
1855 // cumu4h: CumuHistos object with QC{4} cumulants
1856 // quality: Histogram for success rate of cumulants
1857 // chist: Centrality histogram
1858 // dNdetaRef: dN/deta histogram for estimating multiplicity used for ref calculations
1861 // Normalizing common NUA hists
1862 for (Int_t cBin = 1; cBin <= fCumuNUARef->GetNbinsY(); cBin++) {
1863 Double_t cent = fCumuNUARef->GetYaxis()->GetBinCenter(cBin);
1864 for (Int_t eBin = 1; eBin <= fCumuNUARef->GetNbinsX(); eBin++) {
1865 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(eBin);
1866 Double_t mult = fCumuNUARef->GetBinContent(eBin, cBin, 0);
1867 if (mult == 0) continue;
1868 for (Int_t qBin = 1; qBin <= fCumuNUARef->GetNbinsZ(); qBin++) {
1869 fCumuNUARef->SetBinContent(eBin, cBin, qBin, fCumuNUARef->GetBinContent(eBin, cBin, qBin)/mult);
1870 fCumuNUARef->SetBinError(eBin, cBin, qBin, fCumuNUARef->GetBinError(eBin, cBin, qBin)/mult);
1872 // Fill dN/deta diagnostics
1873 dNdetaRef->Fill(eta, cent, mult);
1877 // For flow calculations
1880 TH2D* cumu2NUAold = 0;
1884 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
1885 // Loop over cumulant histogram for final calculations
1886 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
1887 cumu2 = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
1888 if ((fFlags & kNUAcorr)) {
1889 cumu2NUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
1890 cumu2NUA = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUA);
1892 if ((fFlags & kStdQC)) {
1893 cumu4 = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNoNUA);
1894 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNUAOld);
1896 cumuRef = (TH3D*)fCumuHists.Get('r', n);
1898 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
1899 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
1900 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
1901 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
1902 for (Int_t etaBin = 1; etaBin <= cumuRef->GetNbinsX(); etaBin++) { // Eta loop begins
1903 Double_t eta = cumuRef->GetXaxis()->GetBinCenter(etaBin);
1904 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(eta);
1905 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(-eta);
1906 // 2-particle reference flow
1907 Double_t w2Two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
1908 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
1909 if (w2 == 0) continue;
1910 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
1911 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
1912 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
1913 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
1914 Double_t cos2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(2*n));
1915 Double_t sin2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(2*n));
1916 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
1917 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
1918 Double_t two = w2Two / w2;
1920 if (qc2 >= 0) cumu2->Fill(eta, cent, TMath::Sqrt(qc2));
1922 if ((fFlags & kNUAcorr)) {
1924 // With no eta gap the last two terms are <<cos(phi)>>^2 and <<sin(phi)>>^2,
1925 // with eta gap the different coverage is taken into account.
1926 // The next line covers both cases.
1927 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
1928 // Extra NUA term from 2n cosines and sines
1929 Double_t den = 1-(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB);
1930 if (den != 0) qc2 /= den;
1935 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
1936 fType.Data(), n, qc2, eta, cent));
1937 quality->Fill((n-2)*qualityFactor+2, Int_t(cent));
1940 Double_t vnTwo = TMath::Sqrt(qc2);
1941 if (!TMath::IsNaN(vnTwo)) {
1942 quality->Fill((n-2)*qualityFactor+1, Int_t(cent));
1943 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, vnTwo);
1946 if (!(fFlags & kStdQC)) continue;
1947 // 4-particle reference flow
1948 Double_t w4Four = cumuRef->GetBinContent(refEtaBinA, cBin, kW4Four);
1949 Double_t w4 = cumuRef->GetBinContent(refEtaBinA, cBin, kW4);
1950 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
1951 if (w4 == 0 || multm1m2 == 0) continue;
1952 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
1953 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
1954 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
1955 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
1957 cosP1nPhi1P1nPhi2 /= w2;
1958 sinP1nPhi1P1nPhi2 /= w2;
1959 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
1960 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
1961 Double_t four = w4Four / w4;
1962 Double_t qc4 = four-2.*TMath::Power(two,2.);
1963 if (qc4 < 0) cumu4->Fill(eta, cent, TMath::Power(-qc4, 0.25));
1965 if ((fFlags & kNUAcorr)) {
1966 qc4 += - 4.*cosP1nPhiA*cosP1nPhi1M1nPhi2M1nPhi3
1967 + 4.*sinP1nPhiA*sinP1nPhi1M1nPhi2M1nPhi3-TMath::Power(cosP1nPhi1P1nPhi2,2.)-TMath::Power(sinP1nPhi1P1nPhi2,2.)
1968 + 4.*cosP1nPhi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
1969 + 8.*sinP1nPhi1P1nPhi2*sinP1nPhiA*cosP1nPhiA
1970 + 8.*two*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
1971 - 6.*TMath::Power((TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.)),2.);
1975 AliInfo(Form("%s: QC_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
1976 fType.Data(), n, qc2, eta, cent));
1977 quality->Fill((n-2)*qualityFactor+6, Int_t(cent));
1980 Double_t vnFour = TMath::Power(-qc4, 0.25);
1981 if (!TMath::IsNaN(vnFour*multm1m2)) {
1982 quality->Fill((n-2)*qualityFactor+5, Int_t(cent));
1983 if ((fFlags & kNUAcorr)) cumu4NUA->Fill(eta, cent, vnFour);
1991 //_____________________________________________________________________
1992 void AliForwardFlowTaskQC::VertexBin::CalculateDifferentialFlow(CumuHistos& cumu2h, CumuHistos& cumu4h,
1993 TH2I* quality, TH2D* dNdetaDiff) const
1996 // Calculates the differential flow
1999 // cumu2h: CumuHistos object with QC{2} cumulants
2000 // cumu4h: CumuHistos object with QC{4} cumulants
2001 // quality: Histogram for success rate of cumulants
2002 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2005 for (Int_t cBin = 1; cBin <= fCumuNUADiff->GetNbinsY(); cBin++) {
2006 Double_t cent = fCumuNUADiff->GetYaxis()->GetBinCenter(cBin);
2007 for (Int_t eBin = 1; eBin <= fCumuNUADiff->GetNbinsX(); eBin++) {
2008 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(eBin);
2009 Double_t mult = fCumuNUADiff->GetBinContent(eBin, cBin, 0);
2010 if (mult == 0) continue;
2011 for (Int_t qBin = 1; qBin <= fCumuNUADiff->GetNbinsZ(); qBin++) {
2012 fCumuNUADiff->SetBinContent(eBin, cBin, qBin, fCumuNUADiff->GetBinContent(eBin, cBin, qBin)/mult);
2013 fCumuNUADiff->SetBinError(eBin, cBin, qBin, fCumuNUADiff->GetBinError(eBin, cBin, qBin)/mult);
2015 dNdetaDiff->Fill(eta, cent, mult);
2019 // For flow calculations
2023 TH2D* cumu2NUAold = 0;
2027 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
2028 // Loop over cumulant histogram for final calculations
2029 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2030 cumu2 = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNoNUA);
2031 if ((fFlags & kNUAcorr)) {
2032 cumu2NUAold = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNUAOld);
2033 cumu2NUA = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNUA);
2035 if (!(fFlags & kEtaGap)) {
2036 cumu4 = (TH2D*)cumu4h.Get('d',n);
2037 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('d', n, CumuHistos::kNUAOld);
2039 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2040 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2041 for (Int_t cBin = 1; cBin <= cumuDiff->GetNbinsY(); cBin++) { // Centrality loop begins
2042 Double_t cent = cumuDiff->GetYaxis()->GetBinCenter(cBin);
2043 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2044 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2045 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2046 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(eta);
2047 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(-eta);
2049 // Reference objects
2050 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
2051 if (w2 == 0) continue;
2052 Double_t two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
2054 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
2055 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
2056 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
2057 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
2058 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
2059 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
2061 // 2-particle differential flow
2062 Double_t w2pTwoPrime = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2063 Double_t w2p = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2064 if (w2p == 0) continue;
2065 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2066 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2067 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2068 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2069 Double_t twoPrime = w2pTwoPrime / w2p;
2071 Double_t qc2Prime = twoPrime;
2072 cumu2->Fill(eta, cent, qc2Prime);
2073 if ((fFlags & kNUAcorr)) {
2075 qc2Prime -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB;
2076 // Extra NUA term from 2n cosines and sines
2077 qc2Prime /= (1.-(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
2079 if (!TMath::IsNaN(qc2Prime)) {
2080 quality->Fill((n-2)*qualityFactor+3, Int_t(cent));
2081 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, qc2Prime);
2084 quality->Fill((n-2)*qualityFactor+4, Int_t(cent));
2086 AliInfo(Form("%s: QC'_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2087 fType.Data(), n, qc2Prime, eta, cent));
2089 if (!(fFlags & kStdQC)) continue;
2090 // Reference objects
2091 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2092 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2093 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2094 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2095 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
2096 cosP1nPhi1P1nPhi2 /= w2;
2097 sinP1nPhi1P1nPhi2 /= w2;
2098 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2099 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2101 // 4-particle differential flow
2102 Double_t w4pFourPrime = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2103 Double_t w4p = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2104 Double_t mpqMult = cumuDiff->GetBinContent(etaBin, cBin, k3pWeight);
2105 if (w4p == 0 || mpqMult == 0) continue;
2106 Double_t cosP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2);
2107 Double_t sinP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2);
2108 Double_t cosP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3m);
2109 Double_t sinP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3m);
2110 Double_t cosP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3p);
2111 Double_t sinP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3p);
2113 cosP1nPsi1P1nPhi2 /= w2p;
2114 sinP1nPsi1P1nPhi2 /= w2p;
2115 cosP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2116 sinP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2117 cosP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2118 sinP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2120 Double_t fourPrime = w4pFourPrime / w4p;
2121 Double_t qc4Prime = fourPrime-2.*twoPrime*two;
2122 cumu4->Fill(eta, cent, qc4Prime);
2124 if ((fFlags & kNUAcorr)) {
2125 qc4Prime += - cosP1nPsi*cosP1nPhi1M1nPhi2M1nPhi3
2126 + sinP1nPsi*sinP1nPhi1M1nPhi2M1nPhi3
2127 - cosP1nPhiA*cosP1nPsi1M1nPhi2M1nPhi3
2128 + sinP1nPhiA*sinP1nPsi1M1nPhi2M1nPhi3
2129 - 2.*cosP1nPhiA*cosP1nPsi1P1nPhi2M1nPhi3
2130 - 2.*sinP1nPhiA*sinP1nPsi1P1nPhi2M1nPhi3
2131 - cosP1nPsi1P1nPhi2*cosP1nPhi1P1nPhi2
2132 - sinP1nPsi1P1nPhi2*sinP1nPhi1P1nPhi2
2133 + 2.*cosP1nPhi1P1nPhi2*(cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2134 + 2.*sinP1nPhi1P1nPhi2*(cosP1nPsi*sinP1nPhiA+sinP1nPsi*cosP1nPhiA)
2135 + 4.*two*(cosP1nPsi*cosP1nPhiA+sinP1nPsi*sinP1nPhiA)
2136 + 2.*cosP1nPsi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2137 + 4.*sinP1nPsi1P1nPhi2*cosP1nPhiA*sinP1nPhiA
2138 + 4.*twoPrime*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2139 - 6.*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2140 * (cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2141 - 12.*cosP1nPhiA*sinP1nPhiA
2142 * (sinP1nPsi*cosP1nPhiA+cosP1nPsi*sinP1nPhiA);
2144 // Double_t vnFourDiff = - qc4Prime / TMath::Power(-qc4, 0.75);
2145 if (!TMath::IsNaN(qc4Prime*mpqMult)) {
2146 quality->Fill((n-2)*qualityFactor+7, Int_t(cent));
2147 if ((fFlags & kNUAcorr)) cumu4NUA->Fill(eta, cent, qc4Prime);
2150 quality->Fill((n-2)*qualityFactor+8, Int_t(cent));
2152 AliInfo(Form("%s: v_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f",
2153 fType.Data(), n, qc4Prime, eta, cent));
2154 } // End of eta loop
2155 } // End of centrality loop
2160 //_____________________________________________________________________
2161 void AliForwardFlowTaskQC::VertexBin::Calculate3CorFlow(CumuHistos& cumu2h, TH2I* quality, TH1D* chist,
2162 TH2D* dNdetaRef, TH2D* dNdetaDiff) const
2165 // Calculates the 3 sub flow
2168 // cumu2h: CumuHistos object with QC{2} cumulants
2169 // quality: Histogram for success rate of cumulants
2170 // chist: Centrality histogram
2171 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2174 // For flow calculations
2178 TH2D* cumu2rNUAold = 0;
2179 TH2D* cumu2rNUA = 0;
2181 TH2D* cumu2aNUAold = 0;
2182 TH2D* cumu2aNUA = 0;
2184 TH2D* cumu2bNUAold = 0;
2185 TH2D* cumu2bNUA = 0;
2186 // Loop over cumulant histogram for final calculations
2187 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2188 cumu2r = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
2189 cumu2a = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNoNUA);
2190 cumu2b = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNoNUA);
2191 if ((fFlags & kNUAcorr)) {
2192 cumu2rNUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
2193 cumu2rNUA = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUA);
2194 cumu2aNUAold = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNUAOld);
2195 cumu2aNUA = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNUA);
2196 cumu2bNUAold = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNUAOld);
2197 cumu2bNUA = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNUA);
2199 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2200 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2201 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
2202 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
2203 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
2204 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2207 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2208 Double_t cosP1nPhiA = 0;
2209 Double_t sinP1nPhiA = 0;
2210 Double_t cos2nPhiA = 0;
2211 Double_t sin2nPhiA = 0;
2212 Double_t cosP1nPhiB = 0;
2213 Double_t sinP1nPhiB = 0;
2214 Double_t cos2nPhiB = 0;
2215 Double_t sin2nPhiB = 0;
2219 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2220 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2221 // 2-particle reference flow
2222 Double_t w2Two = cumuRef->GetBinContent(etaBin, cBin, kW2Two);
2223 Double_t w2 = cumuRef->GetBinContent(etaBin, cBin, kW2);
2224 if (w2 == 0) continue;
2226 // Update NUA for new range!
2227 if (fEtaLims[prevLim] < eta) {
2228 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
2230 cosP1nPhiA = 0; sinP1nPhiA = 0; cos2nPhiA = 0; sin2nPhiA = 0; multA = 0;
2231 cosP1nPhiB = 0; sinP1nPhiB = 0; cos2nPhiB = 0; sin2nPhiB = 0; multB = 0;
2232 for (Int_t a = aLow; a <= aHigh; a++) {
2233 cosP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n));
2234 sinP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n));
2235 cos2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2236 sin2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2237 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2239 for (Int_t b = bLow; b <= bHigh; b++) {
2240 cosP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n));
2241 sinP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n));
2242 cos2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2243 sin2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2244 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2246 if (multA == 0 || multB == 0) AliFatal("Empty NUA values for 3Cor!");
2247 cosP1nPhiA /= multA;
2248 sinP1nPhiA /= multA;
2251 cosP1nPhiB /= multB;
2252 sinP1nPhiB /= multB;
2256 dNdetaRef->Fill(eta, cent, multA+multB);
2258 Double_t two = w2Two / w2;
2261 if (qc2 >= 0) cumu2r->Fill(eta, cent, TMath::Sqrt(qc2));
2263 if ((fFlags & kNUAcorr)) {
2265 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
2266 // Extra NUA term from 2n cosines and sines
2267 qc2 /= (1-(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB));
2271 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2272 fType.Data(), n, qc2, eta, cent));
2273 quality->Fill((n-2)*4+2, Int_t(cent));
2276 Double_t vnTwo = TMath::Sqrt(qc2);
2277 if (!TMath::IsNaN(vnTwo)) {
2278 quality->Fill((n-2)*4+1, Int_t(cent));
2279 if ((fFlags & kNUAcorr)) cumu2rNUAold->Fill(eta, cent, vnTwo);
2282 // 2-particle differential flow
2283 Double_t w2pTwoPrimeA = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2284 Double_t w2pA = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2285 Double_t w2pTwoPrimeB = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2286 Double_t w2pB = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2287 if (w2pA == 0 || w2pB == 0) continue;
2288 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2289 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2290 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2291 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2292 Double_t mult = fCumuNUADiff->GetBinContent(etaBin, cBin, 0);
2293 if (mult == 0) continue;
2298 Double_t twoPrimeA = w2pTwoPrimeA / w2pA;
2299 Double_t twoPrimeB = w2pTwoPrimeB / w2pB;
2300 dNdetaDiff->Fill(eta, cent, mult);
2302 Double_t qc2PrimeA = twoPrimeA;
2303 Double_t qc2PrimeB = twoPrimeB;
2304 if (qc2PrimeA*qc2PrimeB >= 0) {
2305 cumu2a->Fill(eta, cent, qc2PrimeA);
2306 cumu2b->Fill(eta, cent, qc2PrimeB);
2308 if ((fFlags & kNUAcorr)) {
2310 qc2PrimeA -= cosP1nPsi*cosP1nPhiA + sinP1nPsi*sinP1nPhiA;
2311 qc2PrimeB -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB; // Is this OK?
2312 // Extra NUA term from 2n cosines and sines
2313 qc2PrimeA /= (1.-(cos2nPsi*cos2nPhiA + sin2nPsi*sin2nPhiA));
2314 qc2PrimeB /= (1.-(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
2316 if (!TMath::IsNaN(qc2PrimeA) && !TMath::IsNaN(qc2PrimeB) && qc2 != 0) {
2317 if (qc2PrimeA*qc2PrimeB >= 0) {
2318 quality->Fill((n-2)*4+3, Int_t(cent));
2319 if ((fFlags & kNUAcorr)) cumu2aNUAold->Fill(eta, cent, qc2PrimeA);
2320 if ((fFlags & kNUAcorr)) cumu2bNUAold->Fill(eta, cent, qc2PrimeB);
2324 quality->Fill((n-2)*4+4, Int_t(cent));
2326 AliInfo(Form("%s: QC'a_%d{2} = %1.3f, QC'b_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2327 fType.Data(), n, qc2PrimeA, n, qc2PrimeB, eta, cent));
2328 } // End of eta loop
2329 } // End of centrality loop
2334 //_____________________________________________________________________
2335 void AliForwardFlowTaskQC::VertexBin::SolveCoupledFlowEquations(CumuHistos& cumu, const Char_t type) const
2338 // Function to solve the coupled flow equations
2339 // We solve it by using matrix calculations:
2340 // A*v_n = V => v_n = A^-1*V
2341 // First we set up a TMatrixD container to make ROOT
2342 // do the inversions in an efficient way, we multiply the current <<2>> estimates.
2343 // Then we fill new TH2D's if the corrected <<2>>'s (cumuNUA object).
2346 // cumu: CumuHistos object - uncorrected
2347 // type: Reference ('r') or differential ('d') or ('a' or 'b') for 3 correlator
2350 // We start by declaring Matrix and vector objects, as their constructors are quite heavy
2351 TMatrixD mNUA(fMaxMoment-1, fMaxMoment-1);
2352 TVectorD vQC2(fMaxMoment-1);
2354 for (Int_t cBin = 1; cBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsY(); cBin++) { // cent loop
2355 Double_t cent = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinCenter(cBin);
2356 for (Int_t eBin = 1; eBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsX(); eBin++) { // eta loop
2357 Double_t eta = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin);
2358 mNUA.Zero(); // reset matrix
2359 vQC2.Zero(); // reset vector
2360 for (Int_t n = 0; n < fMaxMoment-1; n++) { // moment loop
2361 vQC2(n) = static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUAOld))->GetBinContent(eBin, cBin);
2362 if (type == 'r' || type == 'R') vQC2(n) *= vQC2(n); // going back to <<2>>
2363 for (Int_t m = 0; m < fMaxMoment-1; m++) { // cross moment
2364 mNUA(n,m) = CalculateNUAMatrixElement(n, m, type, eBin, cBin);
2365 } // End of cross moment loop
2366 } // End of moment loop
2370 // If determinant is non-zero we go with corrected results
2371 if (det != 0 ) vQC2 = mNUA*vQC2;
2372 else AliWarning(Form("Determinant == 0 - cent: %d-%d, eta: %f, type: '%c', data: %s, vtx: %d-%d%s",
2373 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinLowEdge(cBin)),
2374 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinUpEdge(cBin)),
2375 cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin),
2376 type, fType.Data(), fVzMin, fVzMax,
2377 ((fFlags & kEtaGap) ? ", eta-gap" : "")));
2378 // Go back to v_n for ref. keep <<2'>> for diff. flow).
2379 for (Int_t n = 0; n < fMaxMoment-1; n++) {
2381 if (type == 'r' || type == 'R')
2382 vnTwo = (vQC2(n) > 0. ? TMath::Sqrt(vQC2(n)) : 0.);
2384 // is really more <<2'>> in this case
2387 // Fill in corrected v_n
2388 if (vnTwo != 0) static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUA))->Fill(eta, cent, vnTwo);
2389 } // End of moment loop
2390 } // End of eta loop
2391 } // End of centrality loop
2394 //_____________________________________________________________________
2395 Double_t AliForwardFlowTaskQC::VertexBin::CalculateNUAMatrixElement(Int_t n, Int_t m, Char_t type, Int_t binA, Int_t cBin) const
2398 // Calculates the (n,m)-th element in the NUA matrix: 1 if n == m, otherwise:
2399 // <<cos[(n-m)phi1]>>*<<cos[(n-m)phi2]>> + <<sin[(n-m)phi1]>>*<<sin[(n-m)phi2]>>
2400 // NUA(n,m) = -----------------------------------------------------------------------------
2401 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
2403 // <<cos[(n+m)phi1]>>*<<cos[(n+m)phi2]>> + <<sin[(n+m)phi1]>>*<<sin[(n+m)phi2]>>
2404 // + -----------------------------------------------------------------------------
2405 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
2410 // type: Reference ('r') or differential ('d') or ('a' or 'b')
2411 // binA: eta bin of phi1
2412 // cBin: centrality bin
2416 if (n == m) return 1.;
2420 Double_t cosnMmPhi1 = 0, cosnMmPhi2 = 0, sinnMmPhi1 = 0, sinnMmPhi2 = 0;
2421 Double_t cosnPmPhi1 = 0, cosnPmPhi2 = 0, sinnPmPhi1 = 0, sinnPmPhi2 = 0;
2422 Double_t cos2nPhi1 = 0, cos2nPhi2 = 0, sin2nPhi1 = 0, sin2nPhi2 = 0;
2425 if (type == 'r' || type == 'R') {
2426 if ((fFlags & k3Cor)) {
2427 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(binA);
2429 while (fEtaLims[i] < eta) i++;
2430 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2431 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2432 Double_t multA = 0, multB = 0;
2433 for (Int_t a = aLow; a <= aHigh; a++) {
2434 cosnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n-m));
2435 sinnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n-m));
2436 cosnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n+m));
2437 sinnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n+m));
2438 cos2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2439 sin2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2440 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2442 for (Int_t b = bLow; b <= bHigh; b++) {
2443 cosnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n-m));
2444 sinnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n-m));
2445 cosnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n+m));
2446 sinnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n+m));
2447 cos2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2448 sin2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2449 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2451 if (multA == 0 || multB == 0) {
2452 if (fDebug > 0) AliWarning("multA or multB == 0 in matrix elements, aborting NUA");
2455 cosnMmPhi1 /= multA;
2456 sinnMmPhi1 /= multA;
2457 cosnPmPhi1 /= multA;
2458 sinnPmPhi1 /= multA;
2461 cosnMmPhi2 /= multB;
2462 sinnMmPhi2 /= multB;
2463 cosnPmPhi2 /= multB;
2464 sinnPmPhi2 /= multB;
2468 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUARef->GetXaxis()->GetBinCenter(binA));
2469 cosnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2470 sinnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2471 cosnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2472 sinnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2473 cos2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2474 sin2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2475 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2476 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2477 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2478 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2479 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2480 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2482 } // differential flow
2483 else if (type == 'd' || type == 'D') {
2484 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUADiff->GetXaxis()->GetBinCenter(binA));
2485 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2486 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2487 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2488 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2489 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2490 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2491 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2492 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2493 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2494 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2495 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2496 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2497 } // 3 correlator part a or b
2498 else if (type == 'a' || type == 'A' || type == 'b' || type == 'B') {
2499 Double_t mult1 = 0, mult2 = 0;
2501 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2502 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2503 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2504 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2505 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2506 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2507 mult1 = fCumuNUADiff->GetBinContent(binA, cBin, 0);
2509 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(binA);
2511 while (fEtaLims[i] < eta) i++;
2512 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2513 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2514 Int_t lLow = ((type == 'a' || type == 'A') ? aLow : bLow);
2515 Int_t lHigh = ((type == 'a' || type == 'A') ? aHigh : bHigh);
2516 for (Int_t l = lLow; l <= lHigh; l++) {
2517 cosnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n-m));
2518 sinnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n-m));
2519 cosnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n+m));
2520 sinnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n+m));
2521 cos2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(2*n));
2522 sin2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(2*n));
2523 mult2 += fCumuNUARef->GetBinContent(l, cBin, 0);
2525 if (mult1 == 0 || mult2 == 0) {
2526 if (fDebug > 0) AliWarning("mult1 or mult2 == 0 in matrix elements, aborting NUA");
2529 cosnMmPhi1 /= mult1;
2530 sinnMmPhi1 /= mult1;
2531 cosnPmPhi1 /= mult1;
2532 sinnPmPhi1 /= mult1;
2535 cosnMmPhi2 /= mult2;
2536 sinnMmPhi2 /= mult2;
2537 cosnPmPhi2 /= mult2;
2538 sinnPmPhi2 /= mult2;
2543 // Actual calculation
2544 Double_t e = cosnMmPhi1*cosnMmPhi2 + sinnMmPhi1*sinnMmPhi2 + cosnPmPhi1*cosnPmPhi2 + sinnPmPhi1*sinnPmPhi2;
2545 Double_t den = 1 + cos2nPhi1*cos2nPhi2 + sin2nPhi1*sin2nPhi2;
2546 if (den != 0) e /= den;
2551 //_____________________________________________________________________
2552 void AliForwardFlowTaskQC::VertexBin::AddVertexBins(CumuHistos& cumu, TList* list, UInt_t nNUA) const
2555 // Add up vertex bins with flow results
2558 // cumu: CumuHistos object with vtxbin results
2559 // list: Outout list with added results
2560 // nNUA: # of NUA histograms to loop over
2563 TProfile2D* avgProf = 0;
2565 Int_t nT = ((fFlags & k3Cor) ? 3 : 2);
2567 for (UInt_t nua = 0; nua <= nNUA; nua++) { // NUA loop
2568 for (Int_t n = 2; n <= fMaxMoment; n++) { // moment loop
2569 for (Int_t t = 0; t < nT; t++) { // type loop (r/d/a/b)
2572 case 0: ct = 'r'; break;
2573 case 1: ct = ((fFlags & k3Cor) ? 'a' : 'd'); break;
2574 case 2: ct = 'b'; break;
2575 default: ct = '\0'; break;
2577 vtxHist = static_cast<TH2D*>(cumu.Get(ct,n,nua));
2579 AliWarning("VertexBin::AddVertexBins: vtxHist not found!");
2582 name = vtxHist->GetName();
2583 // Strip name of vtx info
2584 Ssiz_t l = name.Last('x')-3;
2586 avgProf = (TProfile2D*)list->FindObject(name.Data());
2587 // if no output profile yet, make one
2589 avgProf = new TProfile2D(name.Data(), name.Data(),
2590 vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXmin(), vtxHist->GetXaxis()->GetXmax(),
2591 vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXmin(), vtxHist->GetYaxis()->GetXmax());
2592 if (vtxHist->GetXaxis()->IsVariableBinSize())
2593 avgProf->GetXaxis()->Set(vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXbins()->GetArray());
2594 if (vtxHist->GetYaxis()->IsVariableBinSize())
2595 avgProf->GetYaxis()->Set(vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXbins()->GetArray());
2598 // Fill in, cannot be done with Add function.
2599 for (Int_t e = 1; e <= vtxHist->GetNbinsX(); e++) { // eta loop
2600 Double_t eta = vtxHist->GetXaxis()->GetBinCenter(e);
2601 for (Int_t c = 1; c <= vtxHist->GetNbinsY(); c++) { // cent loop
2602 Double_t cent = vtxHist->GetYaxis()->GetBinCenter(c);
2603 Double_t cont = vtxHist->GetBinContent(e, c);
2604 if (cont == 0) continue;
2605 avgProf->Fill(eta, cent, cont);
2606 } // End of cent loop
2607 } // End of eta loop
2608 } // End of type loop
2609 } // End of moment loop
2610 } // End of nua loop
2612 //_____________________________________________________________________
2613 Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberCos(Int_t n) const
2616 // Get the bin number of <<cos(nphi)>>
2621 // Return: bin number
2626 if (n == 0) bin = fMaxMoment*4-1;
2631 //_____________________________________________________________________
2632 Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberSin(Int_t n) const
2635 // Get the bin number of <<sin(nphi)>>
2640 // Return: bin number
2645 if (n == 0) bin = fMaxMoment*4;
2650 //_____________________________________________________________________
2651 void AliForwardFlowTaskQC::VertexBin::SetupNUALabels(TAxis* a) const
2654 // Setup NUA labels on axis
2657 // a: Axis to set up
2659 if (a->GetNbins() != GetBinNumberSin()) AliFatal("SetupNUALabels: Wrong number of bins on axis");
2662 while (i <= a->GetNbins()) {
2663 a->SetBinLabel(i++, Form("<<cos(%d#varphi)>>", j));
2664 a->SetBinLabel(i++, Form("<<sin(%d#varphi)>>", j++));
2669 //_____________________________________________________________________
2670 TH2I* AliForwardFlowTaskQC::VertexBin::MakeQualityHist(const Char_t* name) const
2673 // Add a histogram for checking the analysis quality
2676 // const char*: name of data type
2678 // Return: histogram for tracking successful calculations
2680 Int_t nBins = ((fFlags & kStdQC) ? 8 : 4);
2681 TH2I* quality = new TH2I(name, name, (fMaxMoment-1)*nBins, 1, (fMaxMoment-1)*nBins+1, fCumuNUARef->GetNbinsY(),
2682 fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
2683 quality->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
2684 for (Int_t i = 2, j = 1; i <= fMaxMoment; i++) {
2685 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} > 0", i));
2686 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} <= 0", i));
2687 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} > 0", i));
2688 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} <= 0", i));
2689 if ((fFlags & kStdQC)) {
2690 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} < 0", i));
2691 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} >= 0", i));
2692 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} < 0", i));
2693 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} >= 0", i));
2699 //_____________________________________________________________________
2700 TH2D* AliForwardFlowTaskQC::VertexBin::MakeOutputHist(Int_t qc, Int_t n, const Char_t* ctype, UInt_t nua) const
2703 // Setup a TH2D for the output
2706 // qc # of particle correlations
2708 // ref Type: r/d/a/b
2709 // nua For nua corrected hists?
2711 // Return: 2D hist for results
2713 Bool_t ref = ((ctype[0] == 'R') || (ctype[0] == 'r'));
2714 TAxis* xAxis = (ref ? fCumuNUARef->GetXaxis() : fCumuNUADiff->GetXaxis());
2715 TAxis* yAxis = (ref ? fCumuNUARef->GetYaxis() : fCumuNUADiff->GetYaxis());
2718 case CumuHistos::kNoNUA: ntype = "Un"; break;
2719 case CumuHistos::kNUAOld: ntype = "NUAOld"; break;
2720 case CumuHistos::kNUA: ntype = "NUA"; break;
2723 TH2D* h = new TH2D(Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2724 fType.Data(), qc, n, ctype, ntype.Data(),
2725 GetQCType(fFlags), fVzMin, fVzMax),
2726 Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2727 fType.Data(), qc, n, ctype, ntype.Data(),
2728 GetQCType(fFlags), fVzMin, fVzMax),
2729 xAxis->GetNbins(), xAxis->GetXmin(), xAxis->GetXmax(),
2730 yAxis->GetNbins(), yAxis->GetXmin(), yAxis->GetXmax());
2731 if (xAxis->IsVariableBinSize()) h->GetXaxis()->Set(xAxis->GetNbins(), xAxis->GetXbins()->GetArray());
2732 h->GetYaxis()->Set(yAxis->GetNbins(), yAxis->GetXbins()->GetArray());
2736 //_____________________________________________________________________
2737 void AliForwardFlowTaskQC::PrintFlowSetup() const
2740 // Print the setup of the flow task
2742 Printf("=======================================================");
2743 Printf("%s::Print", this->IsA()->GetName());
2744 Printf("Forward detector: :\t%s", ((fFlowFlags & kFMD) ? "FMD" : "VZERO"));
2745 Printf("Number of bins in vertex axis :\t%d", fVtxAxis->GetNbins());
2746 Printf("Range of vertex axis :\t[%3.1f,%3.1f]",
2747 fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
2748 Printf("Number of bins in centrality axis :\t%d", fCentAxis->GetNbins());
2749 printf("Centrality binning :\t");
2750 for (Int_t cBin = 1; cBin <= fCentAxis->GetNbins(); cBin++) {
2751 printf("%02d-%02d%% ", Int_t(fCentAxis->GetBinLowEdge(cBin)), Int_t(fCentAxis->GetBinUpEdge(cBin)));
2752 if (cBin == fCentAxis->GetNbins()) printf("\n");
2753 else if (cBin % 4 == 0) printf("\n\t\t\t\t\t");
2755 printf("Doing flow analysis for :\t");
2756 for (Int_t n = 2; n <= fMaxMoment; n++) printf("v%d ", n);
2758 TString type = "Standard QC{2} and QC{4} calculations.";
2759 if ((fFlowFlags & kTPC)) type.ReplaceAll(".", " with TPC tracks for reference.");
2760 if ((fFlowFlags & kEtaGap)) type = "QC{2} with a rapidity gap.";
2761 if ((fFlowFlags & k3Cor)) type = "QC{2} with 3 correlators.";
2762 Printf("QC calculation type :\t%s", type.Data());
2763 Printf("Symmetrize ref. flow wrt. eta = 0 :\t%s", ((fFlowFlags & kSymEta) ? "true" : "false"));
2764 Printf("Apply NUA correction terms :\t%s", ((fFlowFlags & kNUAcorr) ? "true" : "false"));
2765 Printf("Satellite vertex flag :\t%s", ((fFlowFlags & kSatVtx) ? "true" : "false"));
2766 Printf("FMD sigma cut: :\t%f", fFMDCut);
2767 Printf("SPD sigma cut: :\t%f", fSPDCut);
2768 if ((fFlowFlags & kEtaGap))
2769 Printf("Eta gap: :\t%f", fEtaGap);
2770 Printf("=======================================================");
2772 //_____________________________________________________________________
2773 const Char_t* AliForwardFlowTaskQC::GetQCType(UShort_t flags, Bool_t prependUS)
2776 // Get the type of the QC calculations
2777 // Used for naming of objects in the VertexBin class,
2778 // important to avoid memory problems when running multiple
2779 // initializations of the class with different setups
2782 // flags: Flow flags for type determination
2783 // prependUS: Prepend an underscore (_) to the name
2785 // Return: QC calculation type
2788 if ((flags & kStdQC)) type = "StdQC";
2789 else if ((flags & kEtaGap)) type = "EtaGap";
2790 else if ((flags & k3Cor)) type = "3Cor";
2791 else type = "UNKNOWN";
2792 if (prependUS) type.Prepend("_");
2793 if ((flags & kTPC)) type.Append("TPCTr");
2796 //_____________________________________________________________________
2797 TH1* AliForwardFlowTaskQC::CumuHistos::Get(const Char_t t, Int_t n, UInt_t nua) const
2800 // Get histogram/profile for type t and moment n
2803 // t: type = 'r'/'d'
2808 if (n < 0) AliFatal(Form("CumuHistos out of range: (%c,%d)", t, n));
2812 if (t == 'r' || t == 'R') pos = n;
2813 else if (t == 'd' || t == 'D') pos = n;
2814 else if (t == 'a' || t == 'A') pos = 2*n;
2815 else if (t == 'b' || t == 'B') pos = 2*n+1;
2816 else AliFatal(Form("CumuHistos wrong type: %c", t));
2818 if (t == 'r' || t == 'R') {
2819 if (pos < fRefHists->GetEntries()) {
2820 h = (TH1*)fRefHists->At(pos);
2822 } else if (pos < fDiffHists->GetEntries()) {
2823 h = (TH1*)fDiffHists->At(pos);
2825 if (!h) AliFatal(Form("No hist found in list %c at pos %d", t, pos));
2829 //_____________________________________________________________________
2830 void AliForwardFlowTaskQC::CumuHistos::ConnectList(TString name, TList* l)
2833 // Connect an output list with this object
2837 // l: list to keep outputs in
2840 ref.ReplaceAll("Cumu","CumuRef");
2841 fRefHists = (TList*)l->FindObject(ref.Data());
2843 fRefHists = new TList();
2844 fRefHists->SetName(ref.Data());
2847 // Check that the list correspond to fMaxMoments
2848 if (fRefHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1))
2849 AliError("CumuHistos::ConnectList Wrong number of hists in ref list,"
2850 "you are doing something wrong!");
2852 TString diff = name;
2853 diff.ReplaceAll("Cumu","CumuDiff");
2854 fDiffHists = (TList*)l->FindObject(diff.Data());
2856 fDiffHists = new TList();
2857 fDiffHists->SetName(diff.Data());
2860 // Check that the list correspond to fMaxMoment
2861 if ((fDiffHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1)) &&
2862 (fDiffHists->GetEntries() != 2*(fMaxMoment-1.)*(fNUA+1)))
2863 AliError(Form("CumuHistos::ConnectList Wrong number of hists in diff list,"
2864 "you are doing something wrong! (%s)",name.Data()));
2868 //_____________________________________________________________________
2869 void AliForwardFlowTaskQC::CumuHistos::Add(TH1* h) const
2872 // Add a histogram to this objects lists
2875 // h: histogram/profile to add
2877 TString name = h->GetName();
2878 if (name.Contains("Ref")) {
2879 if (fRefHists) fRefHists->Add(h);
2880 // Check that the list correspond to fMaxMoments
2881 if (fRefHists->GetEntries() > (fNUA+1)*(fMaxMoment-1.))
2882 AliError("CumuHistos::Add wrong number of hists in ref list, "
2883 "you are doing something wrong!");
2885 else if (name.Contains("Diff")) {
2886 if (fDiffHists) fDiffHists->Add(h);
2887 // Check that the list correspond to fMaxMoment
2888 if (fDiffHists->GetEntries() > 2*(fNUA+1)*(fMaxMoment-1.))
2889 AliError("CumuHistos::Add wrong number of hists in diff list, "
2890 "you are doing something wrong!");
2894 //_____________________________________________________________________
2895 Int_t AliForwardFlowTaskQC::CumuHistos::GetPos(Int_t n, UInt_t nua) const
2898 // Get position in list of moment n objects
2899 // To take care of different numbering schemes
2903 // nua: # of nua corrections applied
2905 // Return: position #
2907 if (n > fMaxMoment) return -1;
2908 else return (n-2)+nua*(fMaxMoment-1);
2910 //_____________________________________________________________________