3 // Calculate flow in the forward and central regions using the Q cumulants method.
9 // - AnalysisResults.root
12 * @file AliForwardFlowTaskQC.cxx
13 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
14 * @date Thu Feb 7 01:09:00 2013
19 * @ingroup pwglf_forward_flow
23 #include <TInterpreter.h>
30 #include <TProfile2D.h>
31 #include <TParameter.h>
34 #include "AliForwardFlowTaskQC.h"
35 #include "AliAnalysisManager.h"
36 #include "AliAODHandler.h"
37 #include "AliAODInputHandler.h"
38 #include "AliAODForwardMult.h"
39 #include "AliAODCentralMult.h"
40 #include "AliAODEvent.h"
41 #include "AliForwardUtil.h"
43 ClassImp(AliForwardFlowTaskQC)
48 AliForwardFlowTaskQC::AliForwardFlowTaskQC()
49 : AliAnalysisTaskSE(),
50 fVtxAxis(), // Axis to contorl vertex binning
51 fFMDCut(-1), // FMD sigma cut
52 fSPDCut(-1), // SPD sigma cut
53 fFlowFlags(kSymEta),// Flow flags
54 fEtaGap(2.), // Eta gap value
55 fBinsFMD(), // List with FMD flow histos
56 fBinsSPD(), // List with SPD flow histos
57 fSumList(0), // Event sum list
58 fOutputList(0), // Result output list
59 fAOD(0), // AOD input event
61 fVtx(1111), // Z vertex coordinate
62 fCent(-1), // Centrality
63 fHistCent(), // Histo for centrality
64 fHistVertexSel() // Histo for selected vertices
67 // Default constructor
70 //_____________________________________________________________________
71 AliForwardFlowTaskQC::AliForwardFlowTaskQC(const char* name)
72 : AliAnalysisTaskSE(name),
73 fVtxAxis(), // Axis to contorl vertex binning
74 fFMDCut(-1), // FMD sigma cut
75 fSPDCut(-1), // SPD sigma cut
76 fFlowFlags(kSymEta),// Flow flags
77 fEtaGap(2.), // Eta gap value
78 fBinsFMD(), // List with FMD flow histos
79 fBinsSPD(), // List with SPD flow histos
80 fSumList(0), // Event sum list
81 fOutputList(0), // Result output list
82 fAOD(0), // AOD input event
84 fVtx(1111), // Z vertex coordinate
85 fCent(-1), // Centrality
86 fHistCent(), // Histo for centrality
87 fHistVertexSel() // Histo for selected vertices
95 DefineOutput(1, TList::Class());
96 DefineOutput(2, TList::Class());
98 //_____________________________________________________________________
99 AliForwardFlowTaskQC::AliForwardFlowTaskQC(const AliForwardFlowTaskQC& o)
100 : AliAnalysisTaskSE(o),
101 fVtxAxis(o.fVtxAxis), // Axis to contorl vertex binning
102 fFMDCut(o.fFMDCut), // FMD sigma cut
103 fSPDCut(o.fSPDCut), // SPD sigma cut
104 fFlowFlags(o.fFlowFlags), // Flow flags
105 fEtaGap(o.fEtaGap), // Eta gap value
106 fBinsFMD(), // List with FMD flow histos
107 fBinsSPD(), // List with SPD flow histos
108 fSumList(o.fSumList), // Event sum list
109 fOutputList(o.fOutputList), // Result output list
110 fAOD(o.fAOD), // AOD input event
111 fV(o.fV), // Flow moments
112 fVtx(o.fVtx), // Z vertex coordinate
113 fCent(o.fCent), // Centrality
114 fHistCent(o.fHistCent), // Histo for centrality
115 fHistVertexSel(o.fHistVertexSel) // Histo for selected vertices
121 // o Object to copy from
124 //_____________________________________________________________________
125 AliForwardFlowTaskQC&
126 AliForwardFlowTaskQC::operator=(const AliForwardFlowTaskQC& o)
129 // Assignment operator
131 if (&o == this) return *this;
132 fVtxAxis = o.fVtxAxis;
135 fFlowFlags = o.fFlowFlags;
137 fSumList = o.fSumList;
138 fOutputList = o.fOutputList;
143 fHistCent = o.fHistCent;
144 fHistVertexSel = o.fHistVertexSel;
148 //_____________________________________________________________________
149 void AliForwardFlowTaskQC::UserCreateOutputObjects()
152 // Create output objects
158 PostData(1, fSumList);
159 PostData(2, fOutputList);
162 //_____________________________________________________________________
163 void AliForwardFlowTaskQC::InitVertexBins()
166 // Init vertexbin objects for FMD and SPD, and add them to the lists
169 for(UShort_t n = 0; n < fV.GetSize(); n++) {
171 for (Int_t v = 1; v <= fVtxAxis->GetNbins(); v++) {
172 Int_t vL = Int_t(fVtxAxis->GetBinLowEdge(v));
173 Int_t vH = Int_t(fVtxAxis->GetBinUpEdge(v));
174 fBinsFMD.Add(new VertexBin(vL, vH, moment, "FMD", fFlowFlags, fFMDCut, fEtaGap));
175 fBinsSPD.Add(new VertexBin(vL, vH, moment, "SPD", fFlowFlags, fSPDCut, fEtaGap));
179 //_____________________________________________________________________
180 void AliForwardFlowTaskQC::InitHists()
183 // Init histograms and add vertex bin histograms to the sum list
187 fSumList = new TList();
188 fSumList->SetName("Sums");
189 fSumList->SetOwner();
191 if (!fVtxAxis) fVtxAxis = new TAxis(20, -10, 10);
192 fVtxAxis->SetName("VtxAxis");
193 fHistCent = new TH1D("hCent", "Centralities", 100, 0, 100);
194 fHistVertexSel = new TH1D("hVertexSel", "Selected vertices", fVtxAxis->GetNbins(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
196 TList* dList = new TList();
197 dList->SetName("Diagnostics");
198 // dList->Add(fVtxAxis);
199 dList->Add(fHistCent);
200 dList->Add(fHistVertexSel);
201 fSumList->Add(dList);
203 TIter nextFMD(&fBinsFMD);
205 while ((bin = static_cast<VertexBin*>(nextFMD()))) {
206 bin->AddOutput(fSumList);
208 TIter nextSPD(&fBinsSPD);
209 while ((bin = static_cast<VertexBin*>(nextSPD()))) {
210 bin->AddOutput(fSumList);
213 //_____________________________________________________________________
214 void AliForwardFlowTaskQC::UserExec(Option_t */*option*/)
217 // Calls the analyze function - called every event
225 PostData(1, fSumList);
229 //_____________________________________________________________________
230 Bool_t AliForwardFlowTaskQC::Analyze()
233 // Load FMD and SPD objects from aod tree and call the cumulants
234 // calculation for the correct vertexbin
237 // Reset data members
242 // fAOD = dynamic_cast<AliAODEvent*>(InputEvent());
243 fAOD = dynamic_cast<AliAODEvent*>(AliForwardUtil::GetAODEvent(this));
244 if (!fAOD) return kFALSE;
246 const AliAODForwardMult* aodfmult = static_cast<AliAODForwardMult*>(fAOD->FindListObject("Forward"));
247 const AliAODCentralMult* aodcmult = static_cast<AliAODCentralMult*>(fAOD->FindListObject("CentralClusters"));
248 if (!aodfmult) return kFALSE;
250 // Check event for triggers, get centrality, vtx etc.
251 if (!CheckEvent(aodfmult)) return kFALSE;
252 Int_t vtx = fVtxAxis->FindBin(fVtx)-1;
254 // If everything is OK: get histos and run analysis
255 const TH2D& fmddNdetadphi = aodfmult->GetHistogram();
256 if ((fFlowFlags & kEtaGap)) {
257 FillVtxBinListEtaGap(fBinsFMD, fmddNdetadphi, fmddNdetadphi, vtx);
259 FillVtxBinList(fBinsFMD, fmddNdetadphi, vtx);
263 const TH2D& spddNdetadphi = aodcmult->GetHistogram();
264 if ((fFlowFlags & kEtaGap)) {
265 FillVtxBinListEtaGap(fBinsSPD, fmddNdetadphi, spddNdetadphi, vtx);
267 FillVtxBinList(fBinsSPD, spddNdetadphi, vtx);
273 //_____________________________________________________________________
274 Bool_t AliForwardFlowTaskQC::FillVtxBinList(const TList& list, const TH2D& h, Int_t vtx) const
277 // Loops over list of VtxBins, fills hists of bins for current vertex
278 // and runs analysis on those bins
281 // list: list of VtxBins
282 // h: dN/detadphi histogram
283 // vBin: current vertex bin
285 // return true on success
289 Int_t nVtxBins = fVtxAxis->GetNbins();
291 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
292 Bool_t skipFourP = !bin->FillHists(h, fCent, kFillBoth);
293 bin->CumulantsAccumulate(fCent, skipFourP);
299 //_____________________________________________________________________
300 Bool_t AliForwardFlowTaskQC::FillVtxBinListEtaGap(const TList& list, const TH2D& href,
301 const TH2D& hdiff, Int_t vtx) const
304 // Loops over list of VtxBins, fills hists of bins for current vertex
305 // and runs analysis on those bins
308 // list: list of VtxBins
309 // h: dN/detadphi histogram
310 // vBin: current vertex bin
312 // return true on success
316 Int_t nVtxBins = fVtxAxis->GetNbins();
318 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
319 bin->FillHists(href, fCent, kFillRef);
320 bin->FillHists(hdiff, fCent, kFillDiff);
321 bin->CumulantsAccumulate(fCent);
327 //_____________________________________________________________________
328 void AliForwardFlowTaskQC::Terminate(Option_t */*option*/)
331 // Calls the finalize function, done at the end of the analysis
337 // Make sure pointers are set to the correct lists
338 fSumList = dynamic_cast<TList*> (GetOutputData(1));
340 AliError("Could not retrieve TList fSumList");
344 fOutputList = new TList();
345 fOutputList->SetName("Results");
346 fOutputList->SetOwner();
348 if ((fFlowFlags & kEtaGap)) {
349 TParameter<Double_t>* etaGap = new TParameter<Double_t>("EtaGap", fEtaGap);
350 fOutputList->Add(etaGap);
353 // We make summary histograms of accepted events.
358 for (Int_t i = 1; i < fSumList->GetEntries(); i++) {
359 list = dynamic_cast<TList*>(fSumList->At(i));
361 hist = dynamic_cast<TH3D*>(list->At(0));
363 const char* histname = hist->GetName();
365 for (Int_t j = 0; ; j++) {
366 if (histname[j] == 'v') break;
369 if ((fFlowFlags & kEtaGap)) name += "_etaGap";
370 cent = (TH1D*)fOutputList->FindObject(name.Data());
372 cent = new TH1D(name.Data(), name.Data(), hist->GetNbinsY(), hist->GetYaxis()->GetXmin(), hist->GetYaxis()->GetXmax());
373 cent->GetXaxis()->Set(hist->GetNbinsY(), hist->GetYaxis()->GetXbins()->GetArray());
374 fOutputList->Add(cent);
376 for (Int_t k = 1; k <= hist->GetNbinsY(); k++) {
377 Double_t centrality = hist->GetYaxis()->GetBinCenter(k);
378 Double_t events = hist->GetBinContent(0, k, 0);
379 cent->Fill(centrality, events);
381 o = fOutputList->FindObject(Form("hQCQuality%s", name.Data()));
382 if (!o) MakeQualityHist(name);
385 // Run finalize on VertexBins
388 // Collect centralities
389 MakeCentralityHists(fOutputList);
390 TList* vtxList = (TList*)fOutputList->FindObject("vtxList");
391 if (vtxList) MakeCentralityHists(vtxList);
392 TList* nuaList = (TList*)fOutputList->FindObject("NUATerms");
393 if (nuaList) MakeCentralityHists(nuaList);
395 PostData(2, fOutputList);
399 //_____________________________________________________________________
400 void AliForwardFlowTaskQC::AddFlowMoment(Short_t n)
403 // Add a flow moment to be calculated
405 if (n > 10) AliFatal(Form("Too big moment added: %d (bug)", n));
406 Int_t size = fV.GetSize();
410 //_____________________________________________________________________
411 void AliForwardFlowTaskQC::Finalize()
414 // Finalize command, called by Terminate()
417 // Reinitiate vertex bins if Terminate is called separately!
418 if (fBinsFMD.GetEntries() == 0) InitVertexBins();
420 // Iterate over all vertex bins objects and finalize cumulants
422 EndVtxBinList(fBinsFMD);
423 EndVtxBinList(fBinsSPD);
427 //_____________________________________________________________________
428 void AliForwardFlowTaskQC::EndVtxBinList(const TList& list) const
431 // Loop over VertexBin list and call terminate on each
434 // list VertexBin list
438 while ((bin = static_cast<VertexBin*>(next()))) {
439 bin->CumulantsTerminate(fSumList, fOutputList);
443 // _____________________________________________________________________
444 void AliForwardFlowTaskQC::MakeCentralityHists(TList* list)
447 // Loop over a list containing a TProfile2D with flow results and project
448 // and project to TH1's in specific centrality bins
451 // list Flow results list
453 TProfile2D* hist2D = 0;
457 TIter nextProfile(list);
458 while ((helper = dynamic_cast<TObject*>(nextProfile()))) {
459 if (!(hist2D = dynamic_cast<TProfile2D*>(helper))) continue;
460 for (Int_t cBin = 1; cBin <= hist2D->GetNbinsY(); cBin++) {
461 Int_t cMin = Int_t(hist2D->GetYaxis()->GetBinLowEdge(cBin));
462 Int_t cMax = Int_t(hist2D->GetYaxis()->GetBinUpEdge(cBin));
463 TString name = Form("cent_%d-%d", cMin, cMax);
464 centList = (TList*)list->FindObject(name.Data());
466 centList = new TList();
467 centList->SetName(name.Data());
470 hist1D = hist2D->ProjectionX(Form("%s_%s", hist2D->GetName(), name.Data()),
472 hist1D->SetTitle(hist1D->GetName());
473 centList->Add(hist1D);
477 // _____________________________________________________________________
478 Bool_t AliForwardFlowTaskQC::CheckEvent(const AliAODForwardMult* aodfm)
481 // Function to check that and AOD event meets the cuts
484 // AliAODForwardMult: forward mult object with trigger and vertex info
486 // Returns false if there is no trigger or if the centrality or vertex
487 // is out of range. Otherwise true.
490 // First check for trigger
491 if (!CheckTrigger(aodfm)) return kFALSE;
493 // Then check for centrality
494 if (!GetCentrality(aodfm)) return kFALSE;
496 // And finally check for vertex
497 if (!GetVertex(aodfm)) return kFALSE;
499 // Ev. accepted - filling diag. hists
500 fHistCent->Fill(fCent);
501 fHistVertexSel->Fill(fVtx);
505 // _____________________________________________________________________
506 Bool_t AliForwardFlowTaskQC::CheckTrigger(const AliAODForwardMult* aodfm) const
509 // Function to look for a trigger string in the event.
512 // AliAODForwardMult: forward mult object with trigger and vertex info
514 // Returns true if offline trigger is present
516 return aodfm->IsTriggerBits(AliAODForwardMult::kOffline);
518 // _____________________________________________________________________
519 Bool_t AliForwardFlowTaskQC::GetCentrality(const AliAODForwardMult* aodfm)
522 // Function to look get centrality of the event.
525 // AliAODForwardMult: forward mult object with trigger and vertex info
527 // Returns true if centrality determination is present
529 if (aodfm->HasCentrality()) {
530 fCent = (Double_t)aodfm->GetCentrality();
531 if (0. >= fCent || fCent >= 100.) return kFALSE;
537 // _____________________________________________________________________
538 Bool_t AliForwardFlowTaskQC::GetVertex(const AliAODForwardMult* aodfm)
541 // Function to look for vertex determination in the event.
544 // AliAODForwardMult: forward mult object with trigger and vertex info
546 // Returns true if vertex is determined
548 fVtx = aodfm->GetIpZ();
549 if (fVtx < fVtxAxis->GetXmin() || fVtx > fVtxAxis->GetXmax()) return kFALSE;
553 //_____________________________________________________________________
554 void AliForwardFlowTaskQC::MakeQualityHist(const Char_t* name) const {
556 TH1I* quality = new TH1I(Form("hQCQuality%s", name),
557 Form("hQCQuality%s", name),
558 fV.GetSize()*8, 1, fV.GetSize()*8+1);
559 for (Int_t i = 0, j = 1; i < fV.GetSize(); i++) {
560 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} > 0", fV.At(i)));
561 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} <= 0", fV.At(i)));
562 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} > 0", fV.At(i)));
563 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} <= 0", fV.At(i)));
564 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} < 0", fV.At(i)));
565 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} >= 0", fV.At(i)));
566 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} < 0", fV.At(i)));
567 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} >= 0", fV.At(i)));
570 fOutputList->Add(quality);
572 //_____________________________________________________________________
573 AliForwardFlowTaskQC::VertexBin::VertexBin()
575 fMoment(0), // Flow moment for this vertexbin
576 fVzMin(0), // Vertex z-coordinate min
577 fVzMax(0), // Vertex z-coordinate max
578 fType(), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
579 fFlags(0), // Use forward-backward symmetry, if detector allows it
580 fSigmaCut(-1), // Sigma cut to remove outlier events
581 fEtaGap(2.), // Eta gap value
582 fCumuRef(), // Histogram for reference flow
583 fCumuDiff(), // Histogram for differential flow
584 fCumuHist(), // Sum histogram for cumulants
585 fdNdedpAcc(), // Diagnostics histogram to make acc. maps
586 fOutliers(), // Histogram for sigma distribution
587 fDebug() // Debug level
590 // Default constructor
593 //_____________________________________________________________________
594 AliForwardFlowTaskQC::VertexBin::VertexBin(Int_t vLow, Int_t vHigh,
595 UShort_t moment, TString name,
596 UShort_t flags, Double_t cut,
599 fMoment(moment), // Flow moment for this vertexbin
600 fVzMin(vLow), // Vertex z-coordinate min
601 fVzMax(vHigh), // Vertex z-coordinate max
602 fType(name), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
603 fFlags(flags), // Use forward-backward symmetry, if detector allows it
604 fSigmaCut(cut), // Sigma cut to remove outlier events
605 fEtaGap(etaGap), // Eta gap value
606 fCumuRef(), // Histogram for reference flow
607 fCumuDiff(), // Histogram for differential flow
608 fCumuHist(), // Sum histogram for cumulants
609 fdNdedpAcc(), // Diagnostics histogram to make acc. maps
610 fOutliers(), // Histogram for sigma distribution
611 fDebug(0) // Debug level
617 // vLow: min z-coordinate
618 // vHigh: max z-coordinate
619 // moment: flow moment
620 // name: data type name (FMD/SPD/FMDTR/SPDTR/MC)
621 // sym: data is symmetric in eta
625 SetName(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, ((fFlags & kEtaGap) ? "_etaGap" : "")));
626 SetTitle(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, ((fFlags & kEtaGap) ? "_etaGap" : "")));
628 fDebug = AliAnalysisManager::GetAnalysisManager()->GetDebugLevel();
629 if (fDebug > 0) Printf("AliForwardFlowTaskQC::VertexBin()\tDebugMode: %d", fDebug);
631 //_____________________________________________________________________
632 AliForwardFlowTaskQC::VertexBin&
633 AliForwardFlowTaskQC::VertexBin::operator=(const AliForwardFlowTaskQC::VertexBin& o)
636 // Assignment operator
639 // o: AliForwardFlowTaskQC::VertexBin
641 if (&o == this) return *this;
643 fCumuRef = o.fCumuRef;
644 fCumuDiff = o.fCumuDiff;
645 fCumuHist = o.fCumuHist;
646 fdNdedpAcc = o.fdNdedpAcc;
647 fOutliers = o.fOutliers;
652 //_____________________________________________________________________
653 void AliForwardFlowTaskQC::VertexBin::AddOutput(TList* outputlist)
656 // Add histograms to outputlist
659 // outputlist: list of histograms
662 // First we try to find an outputlist for this vertexbin
663 TList* list = (TList*)outputlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")));
665 // If it doesn't exist we make one
668 list->SetName(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")));
669 outputlist->Add(list);
672 // We initiate the reference histogram
673 fCumuRef = new TH2D(Form("%s_v%d_%d_%d%s_ref", fType.Data(), fMoment, fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
674 Form("%s_v%d_%d_%d%s_ref", fType.Data(), fMoment, fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
675 2, -6., 6., 8, 0.5, 8.5);
677 //list->Add(fCumuRef);
679 // We initiate the differential histogram
680 fCumuDiff = new TH2D(Form("%s_v%d_%d_%d%s_diff", fType.Data(), fMoment, fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
681 Form("%s_v%d_%d_%d%s_diff", fType.Data(), fMoment, fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
682 48, -6., 6., 8, 0.5, 8.5);
684 //list->Add(fCumuDiff);
686 // Initiate the cumulant sum histogram
687 fCumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumu", fType.Data(), fMoment, fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
688 Form("%sv%d_vertex_%d_%d%s_cumu", fType.Data(), fMoment, fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
689 48, -6., 6., 20, 0., 100., 29, 0.5, 29.5);
691 SetupCentAxis(fCumuHist->GetYaxis());
693 list->Add(fCumuHist);
695 // We check for diagnostics histograms (only done per type and moment, not vertexbin)
696 // If they are not found we create them.
697 TList* dList = (TList*)outputlist->FindObject("Diagnostics");
698 if (!dList) AliFatal("No diagnostics list found, what kind of game are you running here?!?!");
700 // Acceptance hists are shared over all moments
701 fdNdedpAcc = (TH2F*)dList->FindObject(Form("h%sdNdedpAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")));
703 fdNdedpAcc = new TH2F(Form("h%sdNdedpAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")),
704 Form("%s acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
705 48, -6, 6, 20, 0, TMath::TwoPi());
707 dList->Add(fdNdedpAcc);
710 if (!(fFlags & kEtaGap)) {
711 fOutliers = new TH2F(Form("hOutliers_%s_v%d_%d_%d", fType.Data(), fMoment, fVzMin, fVzMax),
712 Form("Maximum #sigma from mean N_{ch} pr. bin - %s v_{%d}, %d < v_{z} < %d",
713 fType.Data(), fMoment, fVzMin, fVzMax),
714 20, 0., 100., 500, 0., (fType.Contains("MC") ? 15. : 5.));
715 dList->Add(fOutliers);
719 //_____________________________________________________________________
720 Bool_t AliForwardFlowTaskQC::VertexBin::FillHists(const TH2D& dNdetadphi, Double_t cent, EFillFlow mode)
723 // Fill reference and differential eta-histograms
726 // dNdetadphi: 2D histogram with input data
729 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
731 Bool_t useEvent = kTRUE;
733 // Fist we reset histograms
734 if ((mode & kFillRef)) fCumuRef->Reset();
737 // Numbers to cut away bad events and acceptance.
742 Int_t nBins = (dNdetadphi.GetNbinsX() * 6) / (fCumuDiff->GetNbinsX() * 5);
744 Int_t nCurBin = 0, nPrevBin = 0;
745 Int_t nCurRefBin = 0, nPrevRefBin = 0;
747 Bool_t firstBin = kFALSE;
748 Double_t limit = 9999.;
749 Bool_t mc = fType.Contains("MC");
751 // Then we loop over the input and calculate sum cos(k*n*phi)
752 // and fill it in the reference and differential histograms
753 Double_t eta, phi, weight;
754 Double_t dQnRe = 0, dQ2nRe = 0, dQnIm = 0, dQ2nIm = 0;
756 for (Int_t etaBin = 1; etaBin <= dNdetadphi.GetNbinsX(); etaBin++) {
757 eta = dNdetadphi.GetXaxis()->GetBinCenter(etaBin);
758 nCurBin = fCumuDiff->GetXaxis()->FindBin(eta);
759 nCurRefBin = fCumuRef->GetXaxis()->FindBin(eta);
760 // If we have moved to a new bin in the flow hist, and less than half the eta
761 // region has been covered by it we cut it away.
762 if (nPrevBin == 0) nPrevBin = nCurBin;
763 if (nPrevRefBin == 0) nPrevRefBin = nCurRefBin;
764 if (nCurBin != nPrevBin) {
765 if (nInBin <= nBins/2) {
766 for (Int_t qBin = 1; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
767 Double_t removeContent = fCumuDiff->GetBinContent(nPrevBin, qBin);
768 Double_t removeEta = fCumuDiff->GetXaxis()->GetBinCenter(nPrevBin);
769 if (nCurRefBin != nPrevRefBin) {
770 if (!(fFlags & kEtaGap)) {
771 fCumuRef->Fill(removeEta, qBin, -removeContent);
772 if ((fFlags & kSymEta)) {
773 fCumuRef->Fill(-1.*removeEta, qBin, -removeContent);
776 if ((fFlags & kEtaGap)) {
778 case kHmultA: fCumuRef->Fill(removeEta, qBin, removeContent); break;
779 case kHQnReA: fCumuRef->Fill(removeEta, qBin, removeContent); break;
780 case kHQnImA: fCumuRef->Fill(removeEta, qBin, removeContent); break;
781 case kHmultB: fCumuRef->Fill(-removeEta, qBin, removeContent); break;
782 case kHQnReB: fCumuRef->Fill(-removeEta, qBin, removeContent); break;
783 case kHQnImB: fCumuRef->Fill(-removeEta, qBin, removeContent); break;
788 fCumuDiff->SetBinContent(nPrevBin, qBin, 0);
789 fCumuDiff->SetBinError(nPrevBin, qBin, 0);
794 if (nCurRefBin != nPrevRefBin) nPrevRefBin = nCurRefBin;
797 Bool_t data = kFALSE;
798 for (Int_t phiBin = 0; phiBin <= dNdetadphi.GetNbinsY(); phiBin++) {
800 if (dNdetadphi.GetBinContent(etaBin, phiBin) == 0) break;
802 if ((fFlags & kEtaGap) && (mode & kFillRef) && TMath::Abs(eta) < fEtaGap) break;
803 if ((fFlags & kEtaGap) && (mode & kFillRef) && TMath::Abs(eta) > TMath::Abs(limit)) break;
804 if (data && !firstBin) {
805 limit = dNdetadphi.GetXaxis()->GetBinLowEdge(etaBin);
810 phi = dNdetadphi.GetYaxis()->GetBinCenter(phiBin);
811 if ((fFlags & kEtaGap) && !mc && (phiBin == 7 || phiBin == 14 || phiBin == 15 || phiBin == 20)) continue;
812 weight = dNdetadphi.GetBinContent(etaBin, phiBin);
814 // We calculate the average Nch per. bin
815 avgSqr += weight*weight;
818 if (weight == 0) continue;
819 if (weight > max) max = weight;
821 dQnRe = weight*TMath::Cos(fMoment*phi);
822 dQnIm = weight*TMath::Sin(fMoment*phi);
823 dQ2nRe = weight*TMath::Cos(2.*fMoment*phi);
824 dQ2nIm = weight*TMath::Sin(2.*fMoment*phi);
826 // if we do not have an eta gap we fill the ref sums in eta
827 if (!(fFlags & kEtaGap)) {
828 if ((mode & kFillRef)){
829 fCumuRef->Fill(eta, kHmultA, weight);
830 fCumuRef->Fill(eta, kHQnReA, dQnRe);
831 fCumuRef->Fill(eta, kHQnImA, dQnIm);
832 fCumuRef->Fill(eta, kHmultB, weight);
833 fCumuRef->Fill(eta, kHQnReB, dQnRe);
834 fCumuRef->Fill(eta, kHQnImB, dQnIm);
836 fCumuRef->Fill(eta, kHQ2nRe, dQ2nRe);
837 fCumuRef->Fill(eta, kHQ2nIm, dQ2nIm);
840 // if we have an eta gap or we symmetrize around eta = 0
842 if ((fFlags & kEtaGap)){
843 if ((mode & kFillRef)){
844 fCumuRef->Fill(eta, kHmultA, weight);
845 fCumuRef->Fill(eta, kHQnReA, dQnRe);
846 fCumuRef->Fill(eta, kHQnImA, dQnIm);
848 fCumuRef->Fill(-eta, kHmultB, weight);
849 fCumuRef->Fill(-eta, kHQnReB, dQnRe);
850 fCumuRef->Fill(-eta, kHQnImB, dQnIm);
854 if ((fFlags & kSymEta)){
855 if ((mode & kFillRef)){
856 fCumuRef->Fill(-eta, kHmultA, weight);
857 fCumuRef->Fill(-eta, kHQnReA, dQnRe);
858 fCumuRef->Fill(-eta, kHQnImA, dQnIm);
859 fCumuRef->Fill(-eta, kHmultB, weight);
860 fCumuRef->Fill(-eta, kHQnReB, dQnRe);
861 fCumuRef->Fill(-eta, kHQnImB, dQnIm);
863 fCumuRef->Fill(-eta, kHQ2nRe, dQ2nRe);
864 fCumuRef->Fill(-eta, kHQ2nIm, dQ2nIm);
868 // If we fill diff flow, we always fill it in eta
869 // This is filled always, to be able to remove edge effects
870 // It is reset both for kFillRef and kFillDiff to make the eta
871 // gap analysis work.
872 fCumuDiff->Fill(eta, kHmultA, weight);
873 fCumuDiff->Fill(eta, kHQnReA, dQnRe);
874 fCumuDiff->Fill(eta, kHQnImA, dQnIm);
875 fCumuDiff->Fill(eta, kHQ2nRe, dQ2nRe);
876 fCumuDiff->Fill(eta, kHQ2nIm, dQ2nIm);
879 if ((mode & kFillDiff)) fdNdedpAcc->Fill(eta, phi, weight);
884 // Outlier cut calculations
885 if (nInAvg > 3 && !(fFlags & kEtaGap)) {
888 Double_t stdev = TMath::Sqrt(nInAvg/(nInAvg-1))*TMath::Sqrt(avgSqr - runAvg*runAvg);
889 Double_t nSigma = (stdev == 0 ? 0 : (max-runAvg)/stdev);
890 if (fSigmaCut > 0. && nSigma >= fSigmaCut && cent <= 60) nBadBins++;
892 fOutliers->Fill(cent, nSigma);
893 // We still finish the loop, for fOutliers to make sense,
894 // but we do no keep the event for analysis
895 if (nBadBins > 3) useEvent = kFALSE;
905 //_____________________________________________________________________
906 void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate(Double_t cent, Bool_t skipFourP)
909 // Calculate the Q cumulant of order fMoment
912 // cent: Centrality of event
915 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
917 // We create the objects needed for the analysis
918 Double_t dQnReA = 0, dQnImA = 0, multA;
919 Double_t dQnReB = 0, dQnImB = 0, multB;
920 Double_t dQ2nRe = 0, dQ2nIm = 0;
921 Double_t pnRe = 0, p2nRe = 0, qnRe = 0, q2nRe = 0, pnIm = 0, p2nIm = 0, qnIm = 0, q2nIm = 0;
922 Double_t two = 0, four = 0, twoPrime = 0, fourPrime = 0;
923 Double_t cosPhi1Phi2 = 0, cosPhi1Phi2Phi3m = 0;
924 Double_t sinPhi1Phi2 = 0, sinPhi1Phi2Phi3m = 0;
925 Double_t cosPsi1Phi2 = 0, cosPsi1Phi2Phi3m = 0, cosPsi1Phi2Phi3p = 0;
926 Double_t sinPsi1Phi2 = 0, sinPsi1Phi2Phi3m = 0, sinPsi1Phi2Phi3p = 0;
928 Double_t mp = 0, mq = 0;
929 Double_t w2 = 0, w4 = 0, w2p = 0, w4p = 0;
932 // We loop over the data 1 time!
933 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
934 eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
935 refEtaBin = fCumuRef->GetXaxis()->FindBin(eta);
936 // The values for each individual etaBin bins are reset
959 multA = fCumuRef->GetBinContent(refEtaBin, kHmultA);
960 multB = fCumuRef->GetBinContent(refEtaBin, kHmultB);
961 dQnReA = fCumuRef->GetBinContent(refEtaBin, kHQnReA);
962 dQnImA = fCumuRef->GetBinContent(refEtaBin, kHQnImA);
963 dQnReB = fCumuRef->GetBinContent(refEtaBin, kHQnReB);
964 dQnImB = fCumuRef->GetBinContent(refEtaBin, kHQnImB);
965 dQ2nRe = fCumuRef->GetBinContent(refEtaBin, kHQ2nRe);
966 dQ2nIm = fCumuRef->GetBinContent(refEtaBin, kHQ2nIm);
968 // For each etaBin bin the necessary values for differential flow
970 mp = fCumuDiff->GetBinContent(etaBin, kHmultA);
971 pnRe = fCumuDiff->GetBinContent(etaBin, kHQnReA);
972 pnIm = fCumuDiff->GetBinContent(etaBin, kHQnImA);
973 p2nRe = fCumuDiff->GetBinContent(etaBin, kHQ2nRe);
974 p2nIm = fCumuDiff->GetBinContent(etaBin, kHQ2nIm);
976 if (multA <= 3) continue;
977 if (mp == 0) continue;
979 // The reference flow is calculated
981 if (!(fFlags & kEtaGap)) {
982 w2 = multA * (multA - 1.);
983 two = dQnReA*dQnReA + dQnImA*dQnImA - multA;
986 two = dQnReA*dQnReB + dQnImA*dQnImB;
989 fCumuHist->Fill(eta, cent, kW2Two, two);
990 fCumuHist->Fill(eta, cent, kW2, w2);
992 fCumuHist->Fill(eta, cent, kQnReA, dQnReA);
993 fCumuHist->Fill(eta, cent, kQnImA, dQnImA);
994 fCumuHist->Fill(eta, cent, kMA, multA);
996 fCumuHist->Fill(eta, cent, kQnReB, dQnReB);
997 fCumuHist->Fill(eta, cent, kQnImB, dQnImB);
998 fCumuHist->Fill(eta, cent, kMB, multB);
1000 // Differential flow calculations for each eta bin is done:
1001 // 2-particle differential flow
1002 if (!(fFlags & kEtaGap)) {
1010 w2p = mp * multB - mq;
1011 twoPrime = pnRe*dQnReB + pnIm*dQnImB - mq;
1013 fCumuHist->Fill(eta, cent, kw2two, twoPrime);
1014 fCumuHist->Fill(eta, cent, kw2, w2p);
1016 fCumuHist->Fill(eta, cent, kpnRe, pnRe);
1017 fCumuHist->Fill(eta, cent, kpnIm, pnIm);
1018 fCumuHist->Fill(eta, cent, kmp, mp);
1020 if ((fFlags & kEtaGap) || skipFourP) continue;
1021 // The reference flow is calculated
1023 w4 = multA * (multA - 1.) * (multA - 2.) * (multA - 3.);
1025 four = 2.*multA*(multA-3.) + TMath::Power((TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.)),2.)
1026 -4.*(multA-2.)*(TMath::Power(dQnReA,2.) + TMath::Power(dQnImA,2.))
1027 -2.*(TMath::Power(dQnReA,2.)*dQ2nRe+2.*dQnReA*dQnImA*dQ2nIm-TMath::Power(dQnImA,2.)*dQ2nRe)
1028 +(TMath::Power(dQ2nRe,2.)+TMath::Power(dQ2nIm,2.));
1030 fCumuHist->Fill(eta, cent, kW4Four, four);
1031 fCumuHist->Fill(eta, cent, kW4, w4);
1033 cosPhi1Phi2 = dQnReA*dQnReA - dQnImA*dQnImA - dQ2nRe;
1034 sinPhi1Phi2 = 2.*dQnReA*dQnImA - dQ2nIm;
1036 cosPhi1Phi2Phi3m = dQnReA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))-dQnReA*dQ2nRe-dQnImA*dQ2nIm-2.*(multA-1)*dQnReA;
1038 sinPhi1Phi2Phi3m = -dQnImA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))+dQnReA*dQ2nIm-dQnImA*dQ2nRe+2.*(multA-1)*dQnImA;
1040 fCumuHist->Fill(eta, cent, kCosphi1phi2, cosPhi1Phi2);
1041 fCumuHist->Fill(eta, cent, kSinphi1phi2, sinPhi1Phi2);
1042 fCumuHist->Fill(eta, cent, kCosphi1phi2phi3m, cosPhi1Phi2Phi3m);
1043 fCumuHist->Fill(eta, cent, kSinphi1phi2phi3m, sinPhi1Phi2Phi3m);
1044 fCumuHist->Fill(eta, cent, kMm1m2, multA*(multA-1.)*(multA-2.));
1046 // Differential flow calculations for each eta bin bin is done:
1047 // 4-particle differential flow
1048 w4p = (mp * multA - 3.*mq)*(multA - 1.)*(multA - 2.);
1050 fourPrime = (TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*(pnRe*dQnReA+pnIm*dQnImA)
1051 - q2nRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))
1052 - 2.*q2nIm*dQnReA*dQnImA
1053 - pnRe*(dQnReA*dQ2nRe+dQnImA*dQ2nIm)
1054 + pnIm*(dQnImA*dQ2nRe-dQnReA*dQ2nIm)
1055 - 2.*multA*(pnRe*dQnReA+pnIm*dQnImA)
1056 - 2.*(TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*mq
1057 + 6.*(qnRe*dQnReA+qnIm*dQnImA)
1058 + 1.*(q2nRe*dQ2nRe+q2nIm*dQ2nIm)
1059 + 2.*(pnRe*dQnReA+pnIm*dQnImA)
1063 fCumuHist->Fill(eta, cent, kw4four, fourPrime);
1064 fCumuHist->Fill(eta, cent, kw4, w4p);
1066 cosPsi1Phi2 = pnRe*dQnReA - pnIm*dQnImA - q2nRe;
1067 sinPsi1Phi2 = pnRe*dQnImA + pnIm*dQnReA - q2nIm;
1069 cosPsi1Phi2Phi3p = pnRe*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1070 - 1.*(q2nRe*dQnReA+q2nIm*dQnImA)
1071 - mq*dQnReA+2.*qnRe;
1073 sinPsi1Phi2Phi3p = pnIm*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1074 - 1.*(q2nIm*dQnReA-q2nRe*dQnImA)
1075 - mq*dQnImA+2.*qnIm;
1077 cosPsi1Phi2Phi3m = pnRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))+2.*pnIm*dQnReA*dQnImA
1078 - 1.*(pnRe*dQ2nRe+pnIm*dQ2nIm)
1079 - 2.*mq*dQnReA+2.*qnRe;
1081 sinPsi1Phi2Phi3m = pnIm*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))-2.*pnRe*dQnReA*dQnImA
1082 - 1.*(pnIm*dQ2nRe-pnRe*dQ2nIm)
1083 + 2.*mq*dQnImA-2.*qnIm;
1085 fCumuHist->Fill(eta, cent, kCospsi1phi2, cosPsi1Phi2);
1086 fCumuHist->Fill(eta, cent, kSinpsi1phi2, sinPsi1Phi2);
1087 fCumuHist->Fill(eta, cent, kCospsi1phi2phi3m, cosPsi1Phi2Phi3m);
1088 fCumuHist->Fill(eta, cent, kSinpsi1phi2phi3m, sinPsi1Phi2Phi3m);
1089 fCumuHist->Fill(eta, cent, kmpmq, (mp*multA-2.*mq)*(multA-1.));
1090 fCumuHist->Fill(eta, cent, kCospsi1phi2phi3p, cosPsi1Phi2Phi3p);
1091 fCumuHist->Fill(eta, cent, kSinpsi1phi2phi3p, sinPsi1Phi2Phi3p);
1094 fCumuHist->Fill(-7., cent, -0.5, 1.);
1097 //_____________________________________________________________________
1098 void AliForwardFlowTaskQC::VertexBin::CumulantsTerminate(TList* inlist, TList* outlist)
1101 // Finalizes the Q cumulant calculations
1104 // inlist: input sumlist
1105 // outlist: output result list
1108 // Re-find cumulants hist if Terminate is called separately
1110 TList* list = (TList*)inlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")));
1111 fCumuHist = (TH3D*)list->FindObject(Form("%sv%d_vertex_%d_%d%s_cumu", fType.Data(), fMoment,
1112 fVzMin, fVzMax, ((fFlags & kEtaGap) ? "_etaGap" : "")));
1116 TList* vtxList = (TList*)outlist->FindObject("vtxList");
1118 vtxList = new TList();
1119 vtxList->SetName("vtxList");
1120 outlist->Add(vtxList);
1122 TList* nualist = (TList*)outlist->FindObject("NUATerms");
1124 nualist = new TList();
1125 nualist->SetName("NUATerms");
1126 outlist->Add(nualist);
1129 TH1I* quality = (TH1I*)outlist->FindObject(Form("hQCQuality%s%s", fType.Data(), ((fFlags & kEtaGap) ? "_etaGap" : "")));
1131 // Differential flow
1132 TProfile2D* cumu2Sum = (TProfile2D*)outlist->FindObject(Form("%sQC2_v%d_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")));
1133 TProfile2D* cumu4Sum = (TProfile2D*)outlist->FindObject(Form("%sQC4_v%d_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")));
1135 cumu2Sum = new TProfile2D(Form("%sQC2_v%d_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1136 Form("%sQC2_v%d_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1137 fCumuHist->GetNbinsX(), fCumuHist->GetXaxis()->GetXmin(), fCumuHist->GetXaxis()->GetXmax(),
1138 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1139 SetupCentAxis(cumu2Sum->GetYaxis());
1140 outlist->Add(cumu2Sum);
1142 if (!cumu4Sum && !(fFlags & kEtaGap)) {
1143 cumu4Sum = new TProfile2D(Form("%sQC4_v%d_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1144 Form("%sQC4_v%d_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1145 fCumuHist->GetNbinsX(), fCumuHist->GetXaxis()->GetXmin(), fCumuHist->GetXaxis()->GetXmax(),
1146 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1147 SetupCentAxis(cumu4Sum->GetYaxis());
1148 outlist->Add(cumu4Sum);
1151 TProfile2D* cumu2 = new TProfile2D(Form("%sQC2_v%d_unCorr%s_vtx%3.1f", fType.Data(), fMoment,
1152 ((fFlags & kEtaGap) ? "_etaGap" : ""), (fVzMin+fVzMax)/2.),
1153 Form("%sQC2_v%d_unCorr%s_vtx%3.1f", fType.Data(), fMoment,
1154 ((fFlags & kEtaGap) ? "_etaGap" : ""), (fVzMin+fVzMax)/2.),
1155 fCumuHist->GetNbinsX(), fCumuHist->GetXaxis()->GetXmin(), fCumuHist->GetXaxis()->GetXmax(),
1156 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1157 SetupCentAxis(cumu2->GetYaxis());
1158 vtxList->Add(cumu2);
1159 TProfile2D* cumu4 = 0;
1160 if (!(fFlags & kEtaGap)) {
1161 cumu4 = new TProfile2D(Form("%sQC4_v%d_unCorr%s_vtx%3.1f", fType.Data(), fMoment,
1162 ((fFlags & kEtaGap) ? "_etaGap" : ""), (fVzMin+fVzMax)/2.),
1163 Form("%sQC4_v%d_unCorr%s_vtx%3.1f", fType.Data(), fMoment,
1164 ((fFlags & kEtaGap) ? "_etaGap" : ""), (fVzMin+fVzMax)/2.),
1165 fCumuHist->GetNbinsX(), fCumuHist->GetXaxis()->GetXmin(), fCumuHist->GetXaxis()->GetXmax(),
1166 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1167 SetupCentAxis(cumu4->GetYaxis());
1168 vtxList->Add(cumu4);
1172 TProfile2D* cumu2Ref = (TProfile2D*)outlist->FindObject(Form("%sQC2_v%d_ref_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")));
1173 TProfile2D* cumu4Ref = (TProfile2D*)outlist->FindObject(Form("%sQC4_v%d_ref_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")));
1175 cumu2Ref = new TProfile2D(Form("%sQC2_v%d_ref_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1176 Form("%sQC2_v%d_ref_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1177 fCumuHist->GetNbinsX(), fCumuHist->GetXaxis()->GetXmin(), fCumuHist->GetXaxis()->GetXmax(),
1178 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1179 SetupCentAxis(cumu2Ref->GetYaxis());
1180 outlist->Add(cumu2Ref);
1182 if (!cumu4Ref && !(fFlags & kEtaGap)) {
1183 cumu4Ref = new TProfile2D(Form("%sQC4_v%d_ref_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1184 Form("%sQC4_v%d_ref_unCorr%s", fType.Data(), fMoment, ((fFlags & kEtaGap) ? "_etaGap" : "")),
1185 fCumuHist->GetNbinsX(), fCumuHist->GetXaxis()->GetXmin(), fCumuHist->GetXaxis()->GetXmax(),
1186 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1187 SetupCentAxis(cumu4Ref->GetYaxis());
1188 outlist->Add(cumu4Ref);
1192 TProfile2D* cosPhi = (TProfile2D*)nualist->FindObject(Form("%sCosPhi_v%d_unCorr%s", fType.Data(), fMoment,
1193 ((fFlags & kEtaGap) ? "_etaGap" : "")));
1195 cosPhi = new TProfile2D(Form("%sCosPhi_v%d_unCorr%s", fType.Data(), fMoment,
1196 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1197 Form("%sCosPhi_v%d_unCorr%s", fType.Data(), fMoment,
1198 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1200 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1201 SetupCentAxis(cosPhi->GetYaxis());
1202 nualist->Add(cosPhi);
1205 TProfile2D* cosPsi = (TProfile2D*)nualist->FindObject(Form("%sCosPsi_v%d_unCorr%s", fType.Data(), fMoment,
1206 ((fFlags & kEtaGap) ? "_etaGap" : "")));
1208 cosPsi = new TProfile2D(Form("%sCosPsi_v%d_unCorr%s", fType.Data(), fMoment,
1209 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1210 Form("%sCosPsi_v%d_unCorr%s", fType.Data(), fMoment,
1211 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1213 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1214 SetupCentAxis(cosPsi->GetYaxis());
1215 nualist->Add(cosPsi);
1218 TProfile2D* sinPhi = (TProfile2D*)nualist->FindObject(Form("%sSinPhi_v%d_unCorr%s", fType.Data(), fMoment,
1219 ((fFlags & kEtaGap) ? "_etaGap" : "")));
1221 sinPhi = new TProfile2D(Form("%sSinPhi_v%d_unCorr%s", fType.Data(), fMoment,
1222 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1223 Form("%sSinPhi_v%d_unCorr%s", fType.Data(), fMoment,
1224 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1226 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1227 SetupCentAxis(sinPhi->GetYaxis());
1228 nualist->Add(sinPhi);
1231 TProfile2D* sinPsi = (TProfile2D*)nualist->FindObject(Form("%sSinPsi_v%d_unCorr%s", fType.Data(), fMoment,
1232 ((fFlags & kEtaGap) ? "_etaGap" : "")));
1234 sinPsi = new TProfile2D(Form("%sSinPsi_v%d_unCorr%s", fType.Data(), fMoment,
1235 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1236 Form("%sSinPsi_v%d_unCorr%s", fType.Data(), fMoment,
1237 ((fFlags & kEtaGap) ? "_etaGap" : "")),
1239 fCumuHist->GetNbinsY(), fCumuHist->GetYaxis()->GetXmin(), fCumuHist->GetYaxis()->GetXmax());
1240 SetupCentAxis(sinPsi->GetYaxis());
1241 nualist->Add(sinPsi);
1244 // For flow calculations
1245 Double_t two = 0, qc2 = 0, vnTwo = 0, four = 0, qc4 = 0, vnFour = 0;
1246 Double_t twoPrime = 0, qc2Prime = 0, vnTwoDiff = 0, fourPrime = 0, qc4Prime = 0, vnFourDiff = 0;
1247 Double_t w2 = 0, w4 = 0, w2p = 0, w4p = 0;
1248 Double_t w2Two = 0, w2pTwoPrime = 0, w4Four = 0, w4pFourPrime = 0;
1249 Double_t cosP1nPhiA = 0, sinP1nPhiA = 0, multA = 0;
1250 Double_t cosP1nPhiB = 0, sinP1nPhiB = 0, multB = 0;
1251 Double_t cosP1nPhi1P1nPhi2 = 0, sinP1nPhi1P1nPhi2 = 0;
1252 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = 0, sinP1nPhi1M1nPhi2M1nPhi3 = 0, multm1m2 = 0;
1253 Double_t cosP1nPsi = 0, sinP1nPsi = 0, mp = 0, cosP1nPsi1P1nPhi2 = 0, sinP1nPsi1P1nPhi2 = 0;
1254 Double_t cosP1nPsi1M1nPhi2M1nPhi3 = 0, sinP1nPsi1M1nPhi2M1nPhi3 = 0, mpqMult = 0;
1255 Double_t cosP1nPsi1P1nPhi2M1nPhi3 = 0, sinP1nPsi1P1nPhi2M1nPhi3 = 0;
1257 // Loop over cumulant histogram for final calculations
1259 for (Int_t cBin = 1; cBin <= fCumuHist->GetNbinsY(); cBin++) {
1260 // for weighted avg.
1261 Double_t cent = fCumuHist->GetYaxis()->GetBinCenter(cBin);
1262 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), fMoment, cent));
1264 for (Int_t etaBin = 1; etaBin <= fCumuHist->GetNbinsX(); etaBin++) {
1265 Double_t eta = fCumuHist->GetXaxis()->GetBinCenter(etaBin);
1266 // 2-particle reference flow
1267 w2Two = fCumuHist->GetBinContent(etaBin, cBin, kW2Two);
1268 w2 = fCumuHist->GetBinContent(etaBin, cBin, kW2);
1269 multA = fCumuHist->GetBinContent(etaBin, cBin, kMA);
1270 multB = fCumuHist->GetBinContent(etaBin, cBin, kMB);
1271 if (w2 == 0 || multA == 0 || multB == 0) continue;
1272 cosP1nPhiA = fCumuHist->GetBinContent(etaBin, cBin, kQnReA);
1273 sinP1nPhiA = fCumuHist->GetBinContent(etaBin, cBin, kQnImA);
1274 cosP1nPhiB = fCumuHist->GetBinContent(etaBin, cBin, kQnReB);
1275 sinP1nPhiB = fCumuHist->GetBinContent(etaBin, cBin, kQnImB);
1277 cosP1nPhiA /= multA;
1278 sinP1nPhiA /= multA;
1279 cosP1nPhiB /= multB;
1280 sinP1nPhiB /= multB;
1282 // With no eta gap the last two terms are <<cos(phi)>>^2 and <<sin(phi)>>^2,
1283 // with eta gap the different coverage is taken into account.
1284 // The next line covers both cases.
1285 qc2 = two - cosP1nPhiA*cosP1nPhiB - sinP1nPhiA*sinP1nPhiB;
1287 if (fDebug > 0) AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping", fType.Data(), fMoment, qc2, eta, cent));
1288 quality->Fill((fMoment-2)*8+2);
1291 vnTwo = TMath::Sqrt(qc2);
1292 if (!TMath::IsNaN(vnTwo*multA)) {
1293 quality->Fill((fMoment-2)*8+1);
1294 cumu2Ref->Fill(eta, cent, vnTwo);
1297 // 2-particle differential flow
1298 w2pTwoPrime = fCumuHist->GetBinContent(etaBin, cBin, kw2two);
1299 w2p = fCumuHist->GetBinContent(etaBin, cBin, kw2);
1300 mp = fCumuHist->GetBinContent(etaBin, cBin, kmp);
1301 if (w2p == 0 || mp == 0) continue;
1302 cosP1nPsi = fCumuHist->GetBinContent(etaBin, cBin, kpnRe);
1303 sinP1nPsi = fCumuHist->GetBinContent(etaBin, cBin, kpnIm);
1307 twoPrime = w2pTwoPrime / w2p;
1308 qc2Prime = twoPrime - sinP1nPsi*sinP1nPhiB - cosP1nPsi*cosP1nPhiB;
1310 cosPhi->Fill(eta, cent, cosP1nPhiB);
1311 cosPsi->Fill(eta, cent, cosP1nPsi);
1312 sinPhi->Fill(eta, cent, sinP1nPhiB);
1313 sinPsi->Fill(eta, cent, sinP1nPsi);
1315 vnTwoDiff = qc2Prime / TMath::Sqrt(qc2);
1316 if (!TMath::IsNaN(vnTwoDiff*mp)) {
1317 cumu2->Fill(eta, cent, vnTwoDiff);
1318 quality->Fill((fMoment-2)*8+3);
1321 quality->Fill((fMoment-2)*8+4);
1323 if (fDebug > 1) AliInfo(Form("%s: v_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f", fType.Data(), fMoment, vnTwoDiff, eta, cent));
1324 if ((fFlags & kEtaGap)) continue;
1326 // 4-particle reference flow
1327 w4Four = fCumuHist->GetBinContent(etaBin, cBin, kW4Four);
1328 w4 = fCumuHist->GetBinContent(etaBin, cBin, kW4);
1329 multm1m2 = fCumuHist->GetBinContent(etaBin, cBin, kMm1m2);
1330 if (w4 == 0 || multm1m2 == 0) continue;
1331 cosP1nPhi1P1nPhi2 = fCumuHist->GetBinContent(etaBin, cBin, kCosphi1phi2);
1332 sinP1nPhi1P1nPhi2 = fCumuHist->GetBinContent(etaBin, cBin, kSinphi1phi2);
1333 cosP1nPhi1M1nPhi2M1nPhi3 = fCumuHist->GetBinContent(etaBin, cBin, kCosphi1phi2phi3m);
1334 sinP1nPhi1M1nPhi2M1nPhi3 = fCumuHist->GetBinContent(etaBin, cBin, kSinphi1phi2phi3m);
1336 cosP1nPhi1P1nPhi2 /= w2;
1337 sinP1nPhi1P1nPhi2 /= w2;
1338 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
1339 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
1341 qc4 = four-2.*TMath::Power(two,2.)
1342 - 4.*cosP1nPhiA*cosP1nPhi1M1nPhi2M1nPhi3
1343 + 4.*sinP1nPhiA*sinP1nPhi1M1nPhi2M1nPhi3-TMath::Power(cosP1nPhi1P1nPhi2,2.)-TMath::Power(sinP1nPhi1P1nPhi2,2.)
1344 + 4.*cosP1nPhi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
1345 + 8.*sinP1nPhi1P1nPhi2*sinP1nPhiA*cosP1nPhiA
1346 + 8.*two*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
1347 - 6.*TMath::Power((TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.)),2.);
1350 if (fDebug > 0) AliInfo(Form("%s: QC_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f - skipping", fType.Data(), fMoment, qc2, eta, cent));
1351 quality->Fill((fMoment-2)*8+6);
1354 vnFour = TMath::Power(-qc4, 0.25);
1355 if (!TMath::IsNaN(vnFour*multm1m2)) {
1356 quality->Fill((fMoment-2)*8+5);
1357 cumu4Ref->Fill(eta, cent, vnFour);
1360 // 4-particle differential flow
1361 w4pFourPrime = fCumuHist->GetBinContent(etaBin, cBin, kw4four);
1362 w4p = fCumuHist->GetBinContent(etaBin, cBin, kw4);
1363 mpqMult = fCumuHist->GetBinContent(etaBin, cBin, kmpmq);
1364 if (w4p == 0 || mpqMult == 0) continue;
1365 cosP1nPsi1P1nPhi2 = fCumuHist->GetBinContent(etaBin, cBin, kCospsi1phi2);
1366 sinP1nPsi1P1nPhi2 = fCumuHist->GetBinContent(etaBin, cBin, kSinpsi1phi2);
1367 cosP1nPsi1M1nPhi2M1nPhi3 = fCumuHist->GetBinContent(etaBin, cBin, kCospsi1phi2phi3m);
1368 sinP1nPsi1M1nPhi2M1nPhi3 = fCumuHist->GetBinContent(etaBin, cBin, kSinpsi1phi2phi3m);
1369 cosP1nPsi1P1nPhi2M1nPhi3 = fCumuHist->GetBinContent(etaBin, cBin, kCospsi1phi2phi3p);
1370 sinP1nPsi1P1nPhi2M1nPhi3 = fCumuHist->GetBinContent(etaBin, cBin, kSinpsi1phi2phi3p);
1372 cosP1nPsi1P1nPhi2 /= w2p;
1373 sinP1nPsi1P1nPhi2 /= w2p;
1374 cosP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
1375 sinP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
1376 cosP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
1377 sinP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
1379 fourPrime = w4pFourPrime / w4p;
1381 qc4Prime = fourPrime-2.*twoPrime*two
1382 - cosP1nPsi*cosP1nPhi1M1nPhi2M1nPhi3
1383 + sinP1nPsi*sinP1nPhi1M1nPhi2M1nPhi3
1384 - cosP1nPhiA*cosP1nPsi1M1nPhi2M1nPhi3
1385 + sinP1nPhiA*sinP1nPsi1M1nPhi2M1nPhi3
1386 - 2.*cosP1nPhiA*cosP1nPsi1P1nPhi2M1nPhi3
1387 - 2.*sinP1nPhiA*sinP1nPsi1P1nPhi2M1nPhi3
1388 - cosP1nPsi1P1nPhi2*cosP1nPhi1P1nPhi2
1389 - sinP1nPsi1P1nPhi2*sinP1nPhi1P1nPhi2
1390 + 2.*cosP1nPhi1P1nPhi2*(cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
1391 + 2.*sinP1nPhi1P1nPhi2*(cosP1nPsi*sinP1nPhiA+sinP1nPsi*cosP1nPhiA)
1392 + 4.*two*(cosP1nPsi*cosP1nPhiA+sinP1nPsi*sinP1nPhiA)
1393 + 2.*cosP1nPsi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
1394 + 4.*sinP1nPsi1P1nPhi2*cosP1nPhiA*sinP1nPhiA
1395 + 4.*twoPrime*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
1396 - 6.*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
1397 * (cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
1398 - 12.*cosP1nPhiA*sinP1nPhiA
1399 * (sinP1nPsi*cosP1nPhiA+cosP1nPsi*sinP1nPhiA);
1401 vnFourDiff = - qc4Prime / TMath::Power(-qc4, 0.75);
1402 if (!TMath::IsNaN(vnFourDiff*mpqMult) && vnFourDiff > 0) {
1403 cumu4->Fill(eta, cent, vnFourDiff);
1404 quality->Fill((fMoment-2)*8+7);
1407 quality->Fill((fMoment-2)*8+8);
1409 if (fDebug > 1) AliInfo(Form("%s: v_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f", fType.Data(), fMoment, vnFourDiff, eta, cent));
1410 } // End of eta loop
1411 } // End of centrality loop
1413 cumu2Sum->Add(cumu2);
1414 if (!(fFlags & kEtaGap)) cumu4Sum->Add(cumu4);
1418 //_____________________________________________________________________
1419 void AliForwardFlowTaskQC::VertexBin::SetupCentAxis(TAxis* axis)
1422 // Setup centrality axis for histogram
1425 // axis: centrality axis
1428 AliError("Null pointer passed for axis");
1432 if ((fFlags & kSatVtx)) {
1433 Double_t cent[3] = {0, 40, 100};
1436 Double_t cent[13] = {0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 100 };
1437 // Double_t cent[13] = {0, 2.5, 15, 25, 50, 60, 70, 80, 90, 100, 110, 115, 120 };
1438 axis->Set(12, cent);
1443 //_____________________________________________________________________
1444 void AliForwardFlowTaskQC::PrintFlowSetup() const
1447 // Print the setup of the flow task
1449 Printf("AliForwardFlowTaskQC::Print");
1450 Printf("Number of bins in vertex axis :\t%d", fVtxAxis->GetNbins());
1451 Printf("Range of vertex axis :\t[%3.1f,%3.1f]",
1452 fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
1453 printf("Doing flow analysis for :\t");
1454 for (Int_t n = 0; n < fV.GetSize(); n++) printf("v%d ", fV.At(n));
1456 Printf("Satellite vertex flag :\t%s", ((fFlowFlags & kSatVtx) ? "true" : "false"));
1457 Printf("Symmetrize ref. flow wrt eta = 0:\t%s", ((fFlowFlags & kSymEta) ? "true" : "false"));
1458 Printf("Use an eta-gap for ref. flow :\t%s", ((fFlowFlags & kEtaGap) ? "true" : "false"));
1459 Printf("FMD sigma cut: :\t%f", fFMDCut);
1460 Printf("SPD sigma cut: :\t%f", fSPDCut);
1461 if ((fFlowFlags & kEtaGap))
1462 Printf("Eta gap: :\t%f", fEtaGap);
1465 //_____________________________________________________________________