]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/analysis2/AliForwardFlowTaskQC.cxx
Merge branch 'feature-movesplit'
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / AliForwardFlowTaskQC.cxx
CommitLineData
33438b4c 1
d2bea14e 2//
d226802c 3// Calculate flow in the forward and central regions using the Q cumulants method.
d2bea14e 4//
5// Inputs:
6// - AliAODEvent
7//
8// Outputs:
87f694ab 9// - AnalysisResults.root or forward_flow.root
d2bea14e 10//
d2bea14e 11#include <TROOT.h>
12#include <TSystem.h>
13#include <TInterpreter.h>
14#include <TChain.h>
15#include <TFile.h>
16#include <TList.h>
d2bea14e 17#include <TMath.h>
68589651 18#include <TH3D.h>
19#include <TProfile2D.h>
20#include <TParameter.h>
87f694ab
AH
21#include <TMatrixD.h>
22#include <TVectorD.h>
68589651 23#include <TGraph.h>
d2bea14e 24#include "AliLog.h"
25#include "AliForwardFlowTaskQC.h"
26#include "AliAnalysisManager.h"
27#include "AliAODHandler.h"
28#include "AliAODInputHandler.h"
d2bea14e 29#include "AliAODForwardMult.h"
2b556440 30#include "AliAODCentralMult.h"
58f5fae2 31#include "AliAODEvent.h"
68589651 32#include "AliForwardUtil.h"
f5908250 33#include "AliVVZERO.h"
87f694ab
AH
34#include "AliAODVertex.h"
35#include "AliCentrality.h"
36#include "AliESDEvent.h"
37#include "AliVTrack.h"
bdd49110 38#include "AliESDtrack.h"
87f694ab 39#include "AliAODTrack.h"
bdd49110 40#include "AliAnalysisFilter.h"
58f5fae2 41
d2bea14e 42ClassImp(AliForwardFlowTaskQC)
9d05ffeb 43#if 0
44; // For emacs
45#endif
d2bea14e 46
47AliForwardFlowTaskQC::AliForwardFlowTaskQC()
2b556440 48 : AliAnalysisTaskSE(),
87f694ab
AH
49 fVtxAxis(), // Axis to control vertex binning
50 fCentAxis(), // Axis to control centrality/multiplicity binning
51 fFMDCut(-1), // FMD sigma cut
52 fSPDCut(-1), // SPD sigma cut
53 fFlowFlags(0), // Flow flags
68cb52e7 54 fEtaGap(0.), // Eta gap value
87f694ab
AH
55 fBinsForward(), // List with forward flow hists
56 fBinsCentral(), // List with central flow hists
57 fSumList(0), // Event sum list
58 fOutputList(0), // Result output list
59 fAOD(0), // AOD input event
bdd49110 60 fTrackCuts(0), // ESD track cuts
87f694ab
AH
61 fMaxMoment(0), // Max flow moment
62 fVtx(1111), // Z vertex coordinate
63 fCent(-1), // Centrality
64 fHistdNdedpV0(), // Hist for v0
65 fHistdNdedp3Cor(), // Hist for combining detectors
66 fHistFMDSPDCorr(), // FMD SPD correlation
67 fHistCent(), // Hist for centrality
68 fHistVertexSel(), // Hist for selected vertices
69 fHistEventSel() // Hist for event selection
d2bea14e 70{
71 //
87f694ab 72 // Default constructor
d2bea14e 73 //
74}
75//_____________________________________________________________________
2b556440 76AliForwardFlowTaskQC::AliForwardFlowTaskQC(const char* name)
77 : AliAnalysisTaskSE(name),
87f694ab
AH
78 fVtxAxis(), // Axis to control vertex binning
79 fCentAxis(), // Axis to control centrality/multiplicity binning
d420e249 80 fFMDCut(-1), // FMD sigma cut
81 fSPDCut(-1), // SPD sigma cut
68cb52e7 82 fFlowFlags(0x0), // Flow flags
83 fEtaGap(0.), // Eta gap value
87f694ab
AH
84 fBinsForward(), // List with forward flow hists
85 fBinsCentral(), // List with central flow hists
2b556440 86 fSumList(0), // Event sum list
87 fOutputList(0), // Result output list
88 fAOD(0), // AOD input event
bdd49110 89 fTrackCuts(0), // ESD track cuts
87f694ab 90 fMaxMoment(4), // Max flow moment
d420e249 91 fVtx(1111), // Z vertex coordinate
2b556440 92 fCent(-1), // Centrality
87f694ab
AH
93 fHistdNdedpV0(), // Histo for v0
94 fHistdNdedp3Cor(), // Histo for combining detectors
95 fHistFMDSPDCorr(), // FMD SPD correlation
96 fHistCent(), // Hist for centrality
97 fHistVertexSel(), // Hist for selected vertices
98 fHistEventSel() // Hist for event selection
d2bea14e 99{
100 //
87f694ab 101 // Constructor
d2bea14e 102 //
87f694ab
AH
103 // Parameters:
104 // name: Name of task
d2bea14e 105 //
d2bea14e 106 DefineOutput(1, TList::Class());
2b556440 107 DefineOutput(2, TList::Class());
d2bea14e 108}
109//_____________________________________________________________________
2b556440 110AliForwardFlowTaskQC::AliForwardFlowTaskQC(const AliForwardFlowTaskQC& o)
111 : AliAnalysisTaskSE(o),
87f694ab
AH
112 fVtxAxis(o.fVtxAxis), // Axis to control vertex binning
113 fCentAxis(o.fCentAxis), // Array to control centrality/multiplicity binning
d420e249 114 fFMDCut(o.fFMDCut), // FMD sigma cut
115 fSPDCut(o.fSPDCut), // SPD sigma cut
68589651 116 fFlowFlags(o.fFlowFlags), // Flow flags
117 fEtaGap(o.fEtaGap), // Eta gap value
87f694ab
AH
118 fBinsForward(), // List with forward flow hists
119 fBinsCentral(), // List with central flow hists
2b556440 120 fSumList(o.fSumList), // Event sum list
121 fOutputList(o.fOutputList), // Result output list
122 fAOD(o.fAOD), // AOD input event
bdd49110 123 fTrackCuts(o.fTrackCuts), // ESD track cuts
87f694ab 124 fMaxMoment(o.fMaxMoment), // Flow moments
d420e249 125 fVtx(o.fVtx), // Z vertex coordinate
126 fCent(o.fCent), // Centrality
87f694ab
AH
127 fHistdNdedpV0(o.fHistdNdedpV0), // Histo for v0
128 fHistdNdedp3Cor(o.fHistdNdedp3Cor),// Histo for combining detectors
129 fHistFMDSPDCorr(o.fHistFMDSPDCorr),// FMD SPD correlation
130 fHistCent(o.fHistCent), // Hist for centrality
131 fHistVertexSel(o.fHistVertexSel), // Hist for selected vertices
132 fHistEventSel(o.fHistEventSel) // Hist for event selection
d2bea14e 133{
134 //
87f694ab 135 // Copy constructor
d2bea14e 136 //
87f694ab
AH
137 // Parameters:
138 // o: Object to copy from
d2bea14e 139 //
2b556440 140}
141//_____________________________________________________________________
142AliForwardFlowTaskQC&
143AliForwardFlowTaskQC::operator=(const AliForwardFlowTaskQC& o)
144{
145 //
87f694ab 146 // Assignment operator
2b556440 147 //
eeb6c967 148 if (&o == this) return *this;
87f694ab
AH
149 fVtxAxis = o.fVtxAxis;
150 fCentAxis = o.fCentAxis;
151 fFMDCut = o.fFMDCut;
152 fSPDCut = o.fSPDCut;
153 fFlowFlags = o.fFlowFlags;
154 fEtaGap = o.fEtaGap;
155 fSumList = o.fSumList;
156 fOutputList = o.fOutputList;
157 fAOD = o.fAOD;
bdd49110 158 fTrackCuts = o.fTrackCuts;
87f694ab
AH
159 fMaxMoment = o.fMaxMoment;
160 fVtx = o.fVtx;
161 fCent = o.fCent;
162 fHistdNdedpV0 = o.fHistdNdedpV0;
163 fHistdNdedp3Cor = o.fHistdNdedp3Cor;
164 fHistFMDSPDCorr = o.fHistFMDSPDCorr;
165 fHistCent = o.fHistCent;
166 fHistVertexSel = o.fHistVertexSel;
167 fHistEventSel = o.fHistEventSel;
2b556440 168
2b556440 169 return *this;
d2bea14e 170}
171//_____________________________________________________________________
87f694ab
AH
172void AliForwardFlowTaskQC::SetFlowFlags(UShort_t flags)
173{
174 //
175 // Set flow flags, making sure the detector setup is right
176 //
177 // Parameters:
178 // flags: Flow flags
179 //
180 if ((flags & kFMD) && (flags & kVZERO))
181 AliFatal("Cannot do analysis on more than one forward detector!");
182 else if (!(flags & kFMD) && !(flags & kVZERO))
183 AliFatal("You need to add a forward detector!");
184 else fFlowFlags = flags;
185}
186//_____________________________________________________________________
9453b19e 187void AliForwardFlowTaskQC::UserCreateOutputObjects()
d2bea14e 188{
189 //
87f694ab 190 // Create output objects
2b556440 191 //
192 InitVertexBins();
193 InitHists();
bdd49110 194 if ((fFlowFlags & kTracks) && !fTrackCuts) AliFatal("No track cuts set!");
d420e249 195 PrintFlowSetup();
2f9be372 196
2b556440 197 PostData(1, fSumList);
2b556440 198}
199//_____________________________________________________________________
200void AliForwardFlowTaskQC::InitVertexBins()
201{
202 //
87f694ab
AH
203 // Init vertexbin objects for forward and central detectors, and add them to the lists
204 //
205 for (Int_t v = 1; v <= fVtxAxis->GetNbins(); v++) {
206 Int_t vL = Int_t(fVtxAxis->GetBinLowEdge(v));
207 Int_t vH = Int_t(fVtxAxis->GetBinUpEdge(v));
208 if ((fFlowFlags & kFMD)) {
209 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "FMD", fFlowFlags, fFMDCut, fEtaGap));
1237bf7a 210 if (!(fFlowFlags & k3Cor))
211 fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-FMD", fFlowFlags|kNUAcorr|kSPD, fSPDCut, fEtaGap));
87f694ab
AH
212 }
213 else if ((fFlowFlags & kVZERO)) {
214 fBinsForward.Add(new VertexBin(vL, vH, fMaxMoment, "VZERO", fFlowFlags, 0, fEtaGap));
bdd49110 215 if ((fFlowFlags & kEtaGap) && !(fFlowFlags & kTracks))
1237bf7a 216 fBinsCentral.Add(new VertexBin(vL, vH, fMaxMoment, "SPD-VZERO", fFlowFlags|kNUAcorr|kSPD, fSPDCut, fEtaGap));
d226802c 217 }
218 }
2b556440 219}
220//_____________________________________________________________________
221void AliForwardFlowTaskQC::InitHists()
222{
223 //
87f694ab 224 // Init histograms and add vertex bin histograms to the sum list
2b556440 225 //
226 if (!fSumList)
227 fSumList = new TList();
228 fSumList->SetName("Sums");
229 fSumList->SetOwner();
230
d420e249 231 if (!fVtxAxis) fVtxAxis = new TAxis(20, -10, 10);
232 fVtxAxis->SetName("VtxAxis");
87f694ab
AH
233 if (!fCentAxis) fCentAxis = new TAxis(20, 0, 100);
234 fVtxAxis->SetName("CentAxis");
235
d420e249 236 fHistCent = new TH1D("hCent", "Centralities", 100, 0, 100);
237 fHistVertexSel = new TH1D("hVertexSel", "Selected vertices", fVtxAxis->GetNbins(), fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
87f694ab
AH
238 fHistEventSel = new TH1I("hEventSel", "Event Selection", kOK, 0.5, kOK+0.5);
239 fHistEventSel->GetXaxis()->SetBinLabel(kNoEvent, "No AOD event");
240 fHistEventSel->GetXaxis()->SetBinLabel(kNoForward, "No forward det");
241 fHistEventSel->GetXaxis()->SetBinLabel(kNoCentral, "No central det");
242 fHistEventSel->GetXaxis()->SetBinLabel(kNoTrigger, "Not triggered");
243 fHistEventSel->GetXaxis()->SetBinLabel(kNoCent, "No centrality");
244 fHistEventSel->GetXaxis()->SetBinLabel(kInvCent, "Centrality outside range");
245 fHistEventSel->GetXaxis()->SetBinLabel(kNoVtx, "No vertex");
246 fHistEventSel->GetXaxis()->SetBinLabel(kInvVtx, "Vtx outside range");
247 fHistEventSel->GetXaxis()->SetBinLabel(kOK, "OK!");
248
249 fHistFMDSPDCorr = new TH2D("hFMDSPDCorr", "hFMDSPCCorr", 200, 0., 20000., 200, 0, 7500);
d420e249 250
2b556440 251 TList* dList = new TList();
252 dList->SetName("Diagnostics");
253 dList->Add(fHistCent);
254 dList->Add(fHistVertexSel);
87f694ab
AH
255 dList->Add(fHistEventSel);
256 dList->Add(fHistFMDSPDCorr);
2b556440 257 fSumList->Add(dList);
258
87f694ab
AH
259 fHistdNdedp3Cor = TH2D(Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)), Form("hdNdedpCombined_%s", GetQCType(fFlowFlags)),
260 200, -4., 6., 20, 0., TMath::TwoPi());
261 if ((fFlowFlags & kVZERO)) {
262 Double_t bins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
263 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
264 fHistdNdedpV0 = TH2D(Form("hdNdedpv0%s", GetQCType(fFlowFlags)), Form("hdNdedpv0%s", GetQCType(fFlowFlags)),
265 11, -6, 6, 8, 0, TMath::TwoPi());
266 fHistdNdedpV0.GetXaxis()->Set(11, bins);
267 if ((fFlowFlags & k3Cor)) {
268 Double_t bins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
269 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
270 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
271 fHistdNdedp3Cor.GetXaxis()->Set(19, bins2);
272 fHistdNdedp3Cor.GetYaxis()->Set(8, 0., TMath::TwoPi());
273 }
274 }
275
276 TIter nextForward(&fBinsForward);
2b556440 277 VertexBin* bin = 0;
87f694ab
AH
278 while ((bin = static_cast<VertexBin*>(nextForward()))) {
279 bin->AddOutput(fSumList, fCentAxis);
d226802c 280 }
87f694ab
AH
281 TIter nextCentral(&fBinsCentral);
282 while ((bin = static_cast<VertexBin*>(nextCentral()))) {
283 bin->AddOutput(fSumList, fCentAxis);
d226802c 284 }
d2bea14e 285}
286//_____________________________________________________________________
287void AliForwardFlowTaskQC::UserExec(Option_t */*option*/)
288{
2b556440 289 //
87f694ab 290 // Calls the analyze function - called every event
d2bea14e 291 //
87f694ab
AH
292 // Parameters:
293 // option: Not used
d2bea14e 294 //
4b5b52b7 295
87f694ab
AH
296 // Reset data members
297 fCent = -1;
298 fVtx = 1111;
299
2b556440 300 Analyze();
301
302 PostData(1, fSumList);
303
4b5b52b7 304 return;
2b556440 305}
306//_____________________________________________________________________
307Bool_t AliForwardFlowTaskQC::Analyze()
308{
309 //
87f694ab
AH
310 // Load forward and central detector objects from aod tree and call the
311 // cumulants calculation for the correct vertex bin
312 //
313 // Return: true on success
2b556440 314 //
d226802c 315
d2bea14e 316 // Get input event
68589651 317 fAOD = dynamic_cast<AliAODEvent*>(AliForwardUtil::GetAODEvent(this));
87f694ab
AH
318 if (!fAOD) {
319 fHistEventSel->Fill(kNoEvent);
320 return kFALSE;
321 }
d2bea14e 322
87f694ab
AH
323 // Get detector objects
324 AliAODForwardMult* aodfmult = static_cast<AliAODForwardMult*>(fAOD->FindListObject("Forward"));
325 AliAODCentralMult* aodcmult = static_cast<AliAODCentralMult*>(fAOD->FindListObject("CentralClusters"));
f5908250 326 AliVVZERO* vzero = GetVZERO();
87f694ab 327 if ((fFlowFlags & kVZERO)) {
f5908250 328 if (vzero) {
87f694ab 329 fHistdNdedpV0.Reset();
f5908250 330 FillVZEROHist(vzero);
87f694ab
AH
331 }
332 }
d226802c 333
87f694ab
AH
334 // We make sure that the necessary forward object is there
335 if ((fFlowFlags & kFMD) && !aodfmult) {
336 fHistEventSel->Fill(kNoForward);
337 return kFALSE;
338 }
f5908250 339 else if ((fFlowFlags & kVZERO) && !vzero) {
87f694ab 340 fHistEventSel->Fill(kNoForward);
5d8a14bf 341 return kFALSE;
68589651 342 }
87f694ab 343 if (!aodcmult) fHistEventSel->Fill(kNoCentral);
2f9be372 344
87f694ab
AH
345 // Check event for triggers, get centrality, vtx etc.
346 if (!CheckEvent(aodfmult)) return kFALSE;
347 Int_t vtx = fVtxAxis->FindBin(fVtx)-1;
348
349 // Then we assign a reference to the forward histogram of interest
350 TH2D& forwarddNdedp = ((fFlowFlags & kFMD) ? aodfmult->GetHistogram() : fHistdNdedpV0);
351 TH2D& spddNdedp = aodcmult->GetHistogram();
352 if ((fFlowFlags & kStdQC)) {
353 FillVtxBinList(fBinsForward, forwarddNdedp, vtx);
354 } else if ((fFlowFlags & kEtaGap)) {
355 FillVtxBinListEtaGap(fBinsForward, forwarddNdedp, forwarddNdedp, vtx);
356 }
357 // At the moment only clusters are supported for the central region (some day add tracks?)
358 // So no extra checks necessary
d420e249 359 if (aodcmult) {
87f694ab
AH
360 if ((fFlowFlags & kStdQC)) {
361 FillVtxBinList(fBinsCentral, spddNdedp, vtx);
362 } else if ((fFlowFlags & kEtaGap)) {
363 FillVtxBinListEtaGap(fBinsCentral, forwarddNdedp, spddNdedp, vtx);
364 } else if ((fFlowFlags & k3Cor)) {
365 FillVtxBinList3Cor(fBinsForward, spddNdedp, forwarddNdedp, vtx);
366 }
367 // Diagnostics
368 if (aodfmult) {
369 Double_t totForward = forwarddNdedp.Integral(1, forwarddNdedp.GetNbinsX(), 1, forwarddNdedp.GetNbinsY());
370 Double_t totSPD = spddNdedp.Integral(1, spddNdedp.GetNbinsX(), 1, spddNdedp.GetNbinsY());
371 fHistFMDSPDCorr->Fill(totForward, totSPD);
68589651 372 }
d420e249 373 }
4b5b52b7 374
375 return kTRUE;
376}
377//_____________________________________________________________________
87f694ab 378void AliForwardFlowTaskQC::FillVtxBinList(const TList& list, TH2D& h, Int_t vtx, UShort_t flags) const
4b5b52b7 379{
380 //
87f694ab
AH
381 // Loops over list of VtxBins, fills hists of bins for current vertex
382 // and runs analysis on those bins
4b5b52b7 383 //
87f694ab
AH
384 // Parameters:
385 // list: list of VtxBins
386 // h: dN/detadphi histogram
387 // vtx: current vertex bin
388 // flags: extra flags to handle calculations.
389 //
390 // Note: The while loop is used in this function and the next 2 for historical reasons,
391 // as originally each moment had it's own VertexBin object.
392 VertexBin* bin = 0;
393 Int_t i = 0;
394 Int_t nVtxBins = fVtxAxis->GetNbins();
395
396 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
610fbb44 397 i++;
87f694ab 398 // If no tracks do things normally
610fbb44 399 if (!(fFlowFlags & kTracks) || (flags & kMC)) {
400 if (!bin->FillHists(h, fCent, kFillBoth|flags|kReset)) continue;
401 }
87f694ab 402 // if tracks things are more complicated
bdd49110 403 else if ((fFlowFlags & kTracks)) {
610fbb44 404 if (!FillTracks(bin, kFillRef|kReset|flags)) continue;
405 if (!bin->FillHists(h, fCent, kFillDiff|kReset|flags)) continue;
87f694ab
AH
406 }
407 bin->CumulantsAccumulate(fCent);
87f694ab
AH
408 }
409
410 return;
411}
412//_____________________________________________________________________
413void AliForwardFlowTaskQC::FillVtxBinListEtaGap(const TList& list, TH2D& href,
414 TH2D& hdiff, Int_t vtx, UShort_t flags) const
415{
416 //
417 // Loops over list of VtxBins, fills hists of bins for current vertex
418 // and runs analysis on those bins
4b5b52b7 419 //
87f694ab
AH
420 // Parameters:
421 // list: list of VtxBins
422 // href: dN/detadphi histogram for ref. flow
423 // hdiff: dN/detadphi histogram for diff. flow
424 // vBin: current vertex bin
425 // flags: extra flags to handle calculations.
4b5b52b7 426 //
2b556440 427 VertexBin* bin = 0;
4b5b52b7 428 Int_t i = 0;
429 Int_t nVtxBins = fVtxAxis->GetNbins();
d226802c 430
4b5b52b7 431 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
610fbb44 432 i++;
433 if (!(fFlowFlags & kTracks) || (flags & kMC)) {
434 if(!bin->FillHists(href, fCent, kFillRef|flags|kReset)) continue;
435 }
bdd49110 436 else if ((fFlowFlags & kTracks)) {
610fbb44 437 if (!FillTracks(bin, kFillRef|kReset|flags)) continue;
1237bf7a 438 }
610fbb44 439 if (!bin->FillHists(hdiff, fCent, kFillDiff|kReset|flags)) continue;
87f694ab 440 bin->CumulantsAccumulate(fCent);
68589651 441 }
442
87f694ab 443 return;
68589651 444}
445//_____________________________________________________________________
87f694ab
AH
446void AliForwardFlowTaskQC::FillVtxBinList3Cor(const TList& list, TH2D& hcent,
447 TH2D& hfwd, Int_t vtx, UShort_t flags)
68589651 448{
449 //
87f694ab
AH
450 // Loops over list of VtxBins, fills hists of bins for current vertex
451 // and runs analysis on those bins
68589651 452 //
87f694ab
AH
453 // Parameters:
454 // list: list of VtxBins
455 // hcent: dN/detadphi histogram for central coverage
456 // hfwd: dN/detadphi histogram for forward coverage
457 // vBin: current vertex bin
458 // flags: extra flags to handle calculations.
68589651 459 //
460 VertexBin* bin = 0;
461 Int_t i = 0;
462 Int_t nVtxBins = fVtxAxis->GetNbins();
463
87f694ab
AH
464 TH2D& h = CombineHists(hcent, hfwd);
465
68589651 466 while ((bin = static_cast<VertexBin*>(list.At(vtx+(nVtxBins*i))))) {
4b5b52b7 467 i++;
610fbb44 468 if (!bin->FillHists(h, fCent, kFillBoth|flags|kReset)) continue;
469 bin->CumulantsAccumulate3Cor(fCent);
d226802c 470 }
d2bea14e 471
87f694ab
AH
472 return;
473}
474//_____________________________________________________________________
475TH2D& AliForwardFlowTaskQC::CombineHists(TH2D& hcent, TH2D& hfwd)
476{
477 //
478 // Combines a forward and central d^2N/detadphi histogram.
479 // At some point it might need a flag to choose which histogram gets
480 // priority when there is an overlap, at the moment the average is chosen
481 //
482 // Parameters:
483 // hcent: Central barrel detector
484 // hfwd: Forward detector
485 //
486 // Return: reference to combined hist
487 //
488
489 // If hists are the same (MC input) don't do anything
490 if (&hcent == &hfwd) return hcent;
491
492 fHistdNdedp3Cor.Reset();
493 // FMD, SPD input
494 if ((fFlowFlags & kFMD)) {
495 for (Int_t e = 1; e <= fHistdNdedp3Cor.GetNbinsX(); e++) {
496 Double_t eta = fHistdNdedp3Cor.GetXaxis()->GetBinCenter(e);
497 Bool_t fwdCov = (hfwd.GetBinContent(e, 0) != 0);
498 Bool_t centCov = (hcent.GetBinContent(e, 0) != 0);
499 if (!fwdCov && !centCov) continue;
500 else fHistdNdedp3Cor.SetBinContent(e, 0, 1);
501 for (Int_t p = 1; p <= fHistdNdedp3Cor.GetNbinsY(); p++) {
502 Double_t phi = fHistdNdedp3Cor.GetYaxis()->GetBinCenter(p);
503 Int_t n = 0;
504 Double_t cont = 0.;
505 if (fwdCov) {
506 cont += hfwd.GetBinContent(e, p);
507 n++;
508 }
509 if (centCov) {
510 cont += hcent.GetBinContent(e, p);
511 n++;
512 }
513 if (cont == 0 || n == 0) continue;
514 cont /= n;
515 fHistdNdedp3Cor.Fill(eta, phi, cont);
516 }
517 }
518 // VZERO, SPD input, here we do not average but cut to avoid
519 // (too much) overlap.
520 } else if ((fFlowFlags & kVZERO)) {
521 // VZERO loop
522 for (Int_t eV = 1; eV <= hfwd.GetNbinsX(); eV++) {
523 Double_t eta = hfwd.GetXaxis()->GetBinLowEdge(eV)+0.1;
524 if (hfwd.GetBinContent(eV, 0) == 0) continue;
525 else {
526 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
527 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
528 }
529 for (Int_t p = 1; p <= hfwd.GetNbinsY(); p++) {
530 Double_t phi = hfwd.GetYaxis()->GetBinCenter(p);
531 Double_t cont = hfwd.GetBinContent(eV, p);
532 fHistdNdedp3Cor.Fill(eta, phi, cont);
533 }
534 }
535 // SPD loop
536 Int_t eSs = hcent.GetXaxis()->FindBin(-1.99);
537 Int_t eSe = hcent.GetXaxis()->FindBin(1.99);
538 for (Int_t eS = eSs; eS <= eSe; eS++) {
539 Double_t eta = hcent.GetXaxis()->GetBinCenter(eS);
540 if (hcent.GetBinContent(eS, 0) == 0) continue;
541 else {
542 Int_t he = fHistdNdedp3Cor.GetXaxis()->FindBin(eta);
543 fHistdNdedp3Cor.SetBinContent(he, 0, 1);
544 }
545 for (Int_t p = 1; p <= hcent.GetNbinsY(); p++) {
546 Double_t phi = hcent.GetYaxis()->GetBinCenter(p);
547 Double_t cont = hcent.GetBinContent(eS, p);
548 fHistdNdedp3Cor.Fill(eta, phi, cont);
549 }
550 }
551 }
552 return fHistdNdedp3Cor;
553}
554//_____________________________________________________________________
bdd49110 555Bool_t AliForwardFlowTaskQC::FillTracks(VertexBin* bin, UShort_t mode) const
87f694ab
AH
556{
557 //
558 // Get TPC tracks to use for reference flow.
559 //
560 // Return: TObjArray with tracks
561 //
562 TObjArray* trList = 0;
bdd49110 563 AliESDEvent* esdEv = 0;
564 if (AliForwardUtil::CheckForAOD() == 1) // AOD tracks
565 trList = static_cast<TObjArray*>(fAOD->GetTracks());
566 else
567 esdEv = dynamic_cast<AliESDEvent*>(InputEvent());
568
569 Bool_t useEvent = bin->FillTracks(trList, esdEv, fTrackCuts, mode);
570 return useEvent;
d2bea14e 571}
572//_____________________________________________________________________
2b556440 573void AliForwardFlowTaskQC::Terminate(Option_t */*option*/)
d2bea14e 574{
2b556440 575 //
87f694ab 576 // Calls the finalize function, done at the end of the analysis
d2bea14e 577 //
87f694ab
AH
578 // Parameters:
579 // option: Not used
d2bea14e 580 //
2b556440 581
582 // Make sure pointers are set to the correct lists
583 fSumList = dynamic_cast<TList*> (GetOutputData(1));
584 if(!fSumList) {
585 AliError("Could not retrieve TList fSumList");
586 return;
587 }
68589651 588 if (!fOutputList)
2b556440 589 fOutputList = new TList();
590 fOutputList->SetName("Results");
591 fOutputList->SetOwner();
592
bdd49110 593 if ((fFlowFlags & kEtaGap) || (fFlowFlags & kTracks)) {
68589651 594 TParameter<Double_t>* etaGap = new TParameter<Double_t>("EtaGap", fEtaGap);
595 fOutputList->Add(etaGap);
596 }
87f694ab
AH
597 // We only add axes in terminate, as TAxis object do not merge well,
598 // and so we get a mess when running on the grid if we put them in the sum list...
599 fVtxAxis->SetName("VtxAxis");
600 fOutputList->Add(fVtxAxis);
601 fCentAxis->SetName("CentAxis");
602 fOutputList->Add(fCentAxis);
d420e249 603
2b556440 604 // Run finalize on VertexBins
605 Finalize();
606
87f694ab
AH
607 // Loop over output to get dN/deta hists - used for diagnostics
608 TIter next(fOutputList);
609 TObject* o = 0;
610 TString name;
611 TH2D* dNdeta = 0;
612 TH1D* cent = 0;
613 while ((o = next())) {
614 name = o->GetName();
615 if (name.Contains("dNdeta")) {
616 dNdeta = dynamic_cast<TH2D*>(o);
617 name.ReplaceAll("dNdeta", "cent");
618 name.ReplaceAll("Ref", "");
619 name.ReplaceAll("Diff", "");
620 cent = dynamic_cast<TH1D*>(fOutputList->FindObject(name.Data()));
621 if (!dNdeta || !cent) continue;
622 for (Int_t cBin = 1; cBin <= dNdeta->GetNbinsY(); cBin++) {
623 Double_t nEvents = cent->GetBinContent(cBin);
624 if (nEvents == 0) continue;
625 for (Int_t eBin = 1; eBin <= dNdeta->GetNbinsX(); eBin++) {
626 dNdeta->SetBinContent(eBin, cBin, dNdeta->GetBinContent(eBin, cBin)/nEvents);
627 dNdeta->SetBinError(eBin, cBin, dNdeta->GetBinError(eBin, cBin)/nEvents);
628 }
629 }
630 }
631 }
632
633 // Loop over output and make 1D projections for fast look at results
d420e249 634 MakeCentralityHists(fOutputList);
635 TList* vtxList = (TList*)fOutputList->FindObject("vtxList");
636 if (vtxList) MakeCentralityHists(vtxList);
008eda2b 637 TList* nuaList = (TList*)fOutputList->FindObject("NUATerms");
87f694ab
AH
638 TIter nextNua(nuaList);
639 o = 0;
640 TH2D* h = 0;
641 while ((o = nextNua())) {
642 if (!(h = dynamic_cast<TH2D*>(o))) continue;
643 Double_t evts = h->GetBinContent(0, 0);
644 if (evts != 0) h->Scale(1./evts);
645 }
008eda2b 646 if (nuaList) MakeCentralityHists(nuaList);
2b556440 647
648 PostData(2, fOutputList);
649
4b5b52b7 650 return;
2b556440 651}
652//_____________________________________________________________________
653void AliForwardFlowTaskQC::Finalize()
654{
655 //
87f694ab 656 // Finalize command, called by Terminate()
2b556440 657 //
658
2b556440 659 // Reinitiate vertex bins if Terminate is called separately!
87f694ab 660 if (fBinsForward.GetEntries() == 0) InitVertexBins();
2b556440 661
662 // Iterate over all vertex bins objects and finalize cumulants
663 // calculations
87f694ab
AH
664 EndVtxBinList(fBinsForward);
665 EndVtxBinList(fBinsCentral);
4b5b52b7 666
667 return;
668}
669//_____________________________________________________________________
670void AliForwardFlowTaskQC::EndVtxBinList(const TList& list) const
671{
672 //
87f694ab 673 // Loop over VertexBin list and call terminate on each
4b5b52b7 674 //
87f694ab
AH
675 // Parameters:
676 // list: VertexBin list
4b5b52b7 677 //
678 TIter next(&list);
2b556440 679 VertexBin* bin = 0;
4b5b52b7 680 while ((bin = static_cast<VertexBin*>(next()))) {
2b556440 681 bin->CumulantsTerminate(fSumList, fOutputList);
682 }
4b5b52b7 683 return;
684}
2b556440 685// _____________________________________________________________________
87f694ab 686void AliForwardFlowTaskQC::MakeCentralityHists(TList* list) const
d420e249 687{
688 //
87f694ab 689 // Loop over a list containing a TH2D with flow results
d420e249 690 // and project to TH1's in specific centrality bins
691 //
692 // Parameters:
87f694ab 693 // list: Flow results list
d420e249 694 //
87f694ab 695 TH2D* hist2D = 0;
d420e249 696 TList* centList = 0;
697 TH1D* hist1D = 0;
698 TObject* helper = 0;
87f694ab
AH
699 TIter nextHist(list);
700 while ((helper = dynamic_cast<TObject*>(nextHist()))) {
701 if (!(hist2D = dynamic_cast<TH2D*>(helper))) continue;
d420e249 702 for (Int_t cBin = 1; cBin <= hist2D->GetNbinsY(); cBin++) {
68589651 703 Int_t cMin = Int_t(hist2D->GetYaxis()->GetBinLowEdge(cBin));
704 Int_t cMax = Int_t(hist2D->GetYaxis()->GetBinUpEdge(cBin));
705 TString name = Form("cent_%d-%d", cMin, cMax);
d420e249 706 centList = (TList*)list->FindObject(name.Data());
707 if (!centList) {
708 centList = new TList();
709 centList->SetName(name.Data());
710 list->Add(centList);
711 }
68589651 712 hist1D = hist2D->ProjectionX(Form("%s_%s", hist2D->GetName(), name.Data()),
d420e249 713 cBin, cBin, "E");
714 hist1D->SetTitle(hist1D->GetName());
d420e249 715 centList->Add(hist1D);
d420e249 716 }
717 }
718}
719// _____________________________________________________________________
4b5b52b7 720Bool_t AliForwardFlowTaskQC::CheckEvent(const AliAODForwardMult* aodfm)
2b556440 721{
722 //
87f694ab 723 // Function to check that an AOD event meets the cuts
2b556440 724 //
87f694ab
AH
725 // Parameters:
726 // AliAODForwardMult: forward mult object with trigger and vertex info
2b556440 727 //
87f694ab
AH
728 // Return: false if there is no trigger or if the centrality or vertex
729 // is out of range. Otherwise true.
2b556440 730 //
731
732 // First check for trigger
87f694ab
AH
733 if (!CheckTrigger(aodfm)) {
734 fHistEventSel->Fill(kNoTrigger);
735 return kFALSE;
736 }
2b556440 737
738 // Then check for centrality
87f694ab
AH
739 if (!GetCentrality(aodfm)) {
740 return kFALSE;
741 }
4b5b52b7 742
743 // And finally check for vertex
87f694ab
AH
744 if (!GetVertex(aodfm)) {
745 return kFALSE;
746 }
4b5b52b7 747
d420e249 748 // Ev. accepted - filling diag. hists
749 fHistCent->Fill(fCent);
750 fHistVertexSel->Fill(fVtx);
87f694ab 751 fHistEventSel->Fill(kOK);
d420e249 752
4b5b52b7 753 return kTRUE;
754}
755// _____________________________________________________________________
756Bool_t AliForwardFlowTaskQC::CheckTrigger(const AliAODForwardMult* aodfm) const
757{
758 //
87f694ab
AH
759 // Function to look for a trigger string in the event.
760 // First check for info in forward mult object, if not there, use the AOD header
4b5b52b7 761 //
87f694ab
AH
762 // Parameters:
763 // AliAODForwardMult: forward mult object with trigger and vertex info
4b5b52b7 764 //
87f694ab 765 // Return: true if offline trigger is present
4b5b52b7 766 //
87f694ab
AH
767 if (aodfm) return aodfm->IsTriggerBits(AliAODForwardMult::kOffline);
768 // this may need to be changed for 2011 data to handle kCentral and so on...
769 else return (((AliInputEventHandler*)(AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler()))
770 ->IsEventSelected() & AliVEvent::kMB);
4b5b52b7 771}
772// _____________________________________________________________________
773Bool_t AliForwardFlowTaskQC::GetCentrality(const AliAODForwardMult* aodfm)
774{
775 //
87f694ab
AH
776 // Function to look get centrality of the event.
777 // First check for info in forward mult object, if not there, use the AOD header
4b5b52b7 778 //
87f694ab
AH
779 // Parameters:
780 // AliAODForwardMult: forward mult object with trigger and vertex info
4b5b52b7 781 //
87f694ab 782 // Return: true if centrality determination is present
4b5b52b7 783 //
87f694ab
AH
784 if (aodfm) {
785 if (aodfm->HasCentrality()) {
786 fCent = (Double_t)aodfm->GetCentrality();
787 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
788 fHistEventSel->Fill(kInvCent);
789 return kFALSE;
790 }
791 }
792 else {
793 fCent = 97.5;
794 fHistEventSel->Fill(kNoCent);
795 }
796 return kTRUE;
797 } else {
798 AliCentrality* aodCent = fAOD->GetCentrality();
799 if (aodCent) {
800 fCent = (Double_t)aodCent->GetCentralityPercentile("V0M");
801 if (fCentAxis->GetXmin() > fCent || fCent >= fCentAxis->GetXmax()) {
802 fHistEventSel->Fill(kInvCent);
803 return kFALSE;
804 }
805 }
806 else {
807 fCent = 97.5;
808 fHistEventSel->Fill(kNoCent);
809 }
810 return kTRUE;
811 }
4b5b52b7 812}
87f694ab 813//_____________________________________________________________________
4b5b52b7 814Bool_t AliForwardFlowTaskQC::GetVertex(const AliAODForwardMult* aodfm)
815{
816 //
87f694ab
AH
817 // Function to look for vertex determination in the event.
818 // First check for info in forward mult object, if not there, use the AOD header
4b5b52b7 819 //
87f694ab
AH
820 // Parameters:
821 // AliAODForwardMult: forward mult object with trigger and vertex info
4b5b52b7 822 //
87f694ab 823 // Return: true if vertex is determined
4b5b52b7 824 //
87f694ab
AH
825 if (aodfm) {
826 if (aodfm->HasIpZ()) {
827 fVtx = aodfm->GetIpZ();
828 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
829 fHistEventSel->Fill(kInvVtx);
830 return kFALSE;
831 }
832 } else {
833 fVtx = 9999;
834 fHistEventSel->Fill(kNoVtx);
835 return kFALSE;
836 }
837 return kTRUE;
838 } else {
839 AliAODVertex* aodVtx = fAOD->GetPrimaryVertex();
840 if (aodVtx) {
841 fVtx = aodVtx->GetZ();
842 if (fVtx < fVtxAxis->GetXmin() || fVtx >= fVtxAxis->GetXmax()) {
843 fHistEventSel->Fill(kInvVtx);
844 return kFALSE;
845 }
846 } else {
847 fVtx = 9999;
848 fHistEventSel->Fill(kNoVtx);
849 return kFALSE;
850 }
851 return kTRUE;
852 }
2b556440 853}
87f694ab 854// _____________________________________________________________________
f5908250 855AliVVZERO* AliForwardFlowTaskQC::GetVZERO() const
856{
1237bf7a 857 //
858 // Get VZERO object from ESD or AOD
859 //
860 // Return: VZERO data object
861 //
f5908250 862 AliVVZERO* vzero = 0;
863 // Get input type
864 UShort_t input = AliForwardUtil::CheckForAOD();
865 switch (input) {
866 // If AOD input, simply get the track array from the event
867 case 1: vzero = (AliVVZERO*)fAOD->GetVZEROData();
868 break;
869 case 2: {
870 // If ESD input get event, apply track cuts
871 AliESDEvent* esd = dynamic_cast<AliESDEvent*>(InputEvent());
872 if (!esd) return 0;
873 vzero = (AliVVZERO*)esd->GetVZEROData();
874 break;
875 }
876 default: AliFatal("Neither ESD or AOD input. This should never happen");
877 break;
878 }
879 return vzero;
880}
881// _____________________________________________________________________
882void AliForwardFlowTaskQC::FillVZEROHist(AliVVZERO* vzero)
87f694ab
AH
883{
884 //
885 // Loops over VZERO data object and fill up d^2N/detadphi histogram for flow analysis
886 //
887 // Parameters:
f5908250 888 // vzero: VZERO AOD data object
87f694ab
AH
889 //
890 Int_t ring = 0;
891 Int_t bin = 0;
892 Double_t eta = 0;
893 // Sort of right for 2010 data, do not use for 2011!
894 Double_t eq[64] = { 1.43536, 1.45727, 1.44993, 1.30051, 1.17425, 1.2335, 1.22247, 1.14362,
895 1.14647, 1.25208, 1.17681, 1.21642, 1.16604, 1.05532, 1.03212, 1.1032,
896 1.22941, 1.36986, 1.14652, 1.20056, 0.927086, 1.10809, 1.03343, 1.29472,
897 1.21204, 1.29217, 1.2003, 2.10382, 1.28513, 1.40558, 1.25784, 1.21848,
898 0.475162, 0.50421, 0.503617, 0.512471, 0.515276, 0.39831, 0.415199, 0.444664,
899 0.521922, 0.785915, 0.703658, 0.832479, 0.77461, 0.73129, 0.778697, 0.710265,
900 0.89686, 0.967688, 0.974225, 0.873445, 0.811096, 0.828493, 0.889609, 0.586056,
901 1.15877, 0.954656, 0.914557, 0.979028, 1.04907, 0.748518, 0.928043, 0.98175 };
5d8a14bf 902
87f694ab
AH
903 for (Int_t i = 0; i < 64; i++) {
904 if (i % 8 == 0) {
905 ring++;
5d8a14bf 906 bin = (ring < 5 ? 11-ring : ring-3);
87f694ab
AH
907 eta = fHistdNdedpV0.GetXaxis()->GetBinCenter(bin);
908 fHistdNdedpV0.SetBinContent(bin, 0, 1);
909 }
f5908250 910 Float_t amp = vzero->GetMultiplicity(i);
87f694ab
AH
911 amp /= eq[i];
912 Double_t phi = TMath::Pi()/8.+TMath::TwoPi()*i/8.;
913 while (phi > TMath::TwoPi()) phi -= TMath::TwoPi();
914 fHistdNdedpV0.Fill(eta, phi, amp);
915 }
008eda2b 916}
917//_____________________________________________________________________
2b556440 918AliForwardFlowTaskQC::VertexBin::VertexBin()
919 : TNamed(),
87f694ab
AH
920 fMaxMoment(0), // Max flow moment for this vertexbin
921 fVzMin(0), // Vertex z-coordinate min [cm]
922 fVzMax(0), // Vertex z-coordinate max [cm]
4b5b52b7 923 fType(), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
87f694ab 924 fFlags(0), // Flow flags
d420e249 925 fSigmaCut(-1), // Sigma cut to remove outlier events
87f694ab
AH
926 fEtaGap(-1), // Eta gap value
927 fEtaLims(), // Limits for binning in 3Cor method
2b556440 928 fCumuRef(), // Histogram for reference flow
929 fCumuDiff(), // Histogram for differential flow
87f694ab
AH
930 fCumuHists(0,0), // CumuHists object for keeping track of results
931 fCumuNUARef(), // Histogram for ref NUA terms
932 fCumuNUADiff(), // Histogram for diff NUA terms
933 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
934 fdNdedpDiffAcc(),// Diagnostics histogram for acc. maps
d420e249 935 fOutliers(), // Histogram for sigma distribution
4b5b52b7 936 fDebug() // Debug level
2b556440 937{
938 //
87f694ab 939 // Default constructor
2b556440 940 //
941}
942//_____________________________________________________________________
4b5b52b7 943AliForwardFlowTaskQC::VertexBin::VertexBin(Int_t vLow, Int_t vHigh,
944 UShort_t moment, TString name,
68589651 945 UShort_t flags, Double_t cut,
946 Double_t etaGap)
2b556440 947 : TNamed("", ""),
87f694ab
AH
948 fMaxMoment(moment), // Max flow moment for this vertexbin
949 fVzMin(vLow), // Vertex z-coordinate min [cm]
950 fVzMax(vHigh), // Vertex z-coordinate max [cm]
951 fType(name), // Data type name e.g., FMD/SPD/FMDTR/SPDTR/MC
952 fFlags(flags), // Flow flags
953 fSigmaCut(cut), // Sigma cut to remove outlier events
954 fEtaGap(etaGap), // Eta gap value
955 fEtaLims(), // Limits for binning in 3Cor method
956 fCumuRef(), // Histogram for reference flow
957 fCumuDiff(), // Histogram for differential flow
958 fCumuHists(moment,0),// CumuHists object for keeping track of results
959 fCumuNUARef(), // Histogram for ref NUA terms
960 fCumuNUADiff(), // Histogram for diff NUA terms
961 fdNdedpRefAcc(), // Diagnostics histogram for acc. maps
962 fdNdedpDiffAcc(), // Diagnostics histogram for acc. maps
963 fOutliers(), // Histogram for sigma distribution
964 fDebug(0) // Debug level
2b556440 965{
966 //
87f694ab 967 // Constructor
2b556440 968 //
87f694ab
AH
969 // Parameters
970 // vLow: min z-coordinate
971 // vHigh: max z-coordinate
972 // moment: max flow moment
973 // name: data type name (FMD/SPD/FMDTR/SPDTR/MC)
974 // flags: flow flags
975 // cut: sigma cut
976 // etaGap: eta-gap value
2b556440 977 //
4b5b52b7 978 fType.ToUpper();
979
87f694ab
AH
980 SetName(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
981 SetTitle(Form("%svertexBin%d_%d_%d%s", fType.Data(), moment, vLow, vHigh, GetQCType(fFlags)));
982
4b5b52b7 983 fDebug = AliAnalysisManager::GetAnalysisManager()->GetDebugLevel();
008eda2b 984 if (fDebug > 0) Printf("AliForwardFlowTaskQC::VertexBin()\tDebugMode: %d", fDebug);
87f694ab
AH
985
986 // Set limits for 3 correlator method
987 if ((fFlags & kFMD)) {
988 fEtaLims[0] = -6.;
989 fEtaLims[1] = -1.5;
990 fEtaLims[2] = -0.5;
991 fEtaLims[3] = 2.;
992 fEtaLims[4] = 3.;
993 fEtaLims[5] = 6.;
994 } else if ((fFlags & kVZERO)) {
995 fEtaLims[0] = -6;
996 fEtaLims[1] = -2.7;
997 fEtaLims[2] = -2.0;
998 fEtaLims[3] = 2.0;
999 fEtaLims[4] = 3.9;
1000 fEtaLims[5] = 6;
1001 }
2b556440 1002}
1003//_____________________________________________________________________
1004AliForwardFlowTaskQC::VertexBin&
1005AliForwardFlowTaskQC::VertexBin::operator=(const AliForwardFlowTaskQC::VertexBin& o)
1006{
1007 //
87f694ab 1008 // Assignment operator
2b556440 1009 //
87f694ab
AH
1010 // Parameters
1011 // o: AliForwardFlowTaskQC::VertexBin
2b556440 1012 //
eeb6c967 1013 if (&o == this) return *this;
87f694ab
AH
1014 fMaxMoment = o.fMaxMoment;
1015 fVzMin = o.fVzMin;
1016 fVzMax = o.fVzMax;
1017 fType = o.fType;
1018 fFlags = o.fFlags;
1019 fSigmaCut = o.fSigmaCut;
1020 fEtaGap = o.fEtaGap;
1021 fCumuRef = o.fCumuRef;
1022 fCumuDiff = o.fCumuDiff;
1023 fCumuHists = o.fCumuHists;
1024 fCumuNUARef = o.fCumuNUARef;
1025 fCumuNUADiff = o.fCumuNUADiff;
1026 fdNdedpRefAcc = o.fdNdedpRefAcc;
1027 fdNdedpDiffAcc = o.fdNdedpDiffAcc;
1028 fOutliers = o.fOutliers;
1029 fDebug = o.fDebug;
fdd86891 1030 for (UInt_t i = 0; i < sizeof(fEtaLims)/sizeof(Double_t); i++) fEtaLims[i] = o.fEtaLims[i];
2b556440 1031
1032 return *this;
1033}
1034//_____________________________________________________________________
87f694ab 1035void AliForwardFlowTaskQC::VertexBin::AddOutput(TList* outputlist, TAxis* centAxis)
2b556440 1036{
1037 //
87f694ab 1038 // Add histograms to outputlist
2b556440 1039 //
87f694ab
AH
1040 // Parameters
1041 // outputlist: list of histograms
1042 // centAxis: centrality axis
2b556440 1043 //
1044
1045 // First we try to find an outputlist for this vertexbin
87f694ab 1046 TList* list = (TList*)outputlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
2b556440 1047 // If it doesn't exist we make one
1048 if (!list) {
1049 list = new TList();
87f694ab 1050 list->SetName(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
2b556440 1051 outputlist->Add(list);
1052 }
1053
87f694ab
AH
1054 // Get bin numbers and binning defined
1055 Int_t nHBins = GetBinNumberSin();
5d8a14bf 1056 Int_t nEtaBins = 24;
87f694ab
AH
1057 if ((fFlags & k3Cor)) {
1058 if ((fFlags & kFMD)) nEtaBins = 24;
1059 else if ((fFlags & kVZERO)) nEtaBins = 19;
1060 }
02738f97 1061 else if ((fFlags & kVZERO) && (fFlags & kEtaGap)) nEtaBins = 19;
1062 else if ((fFlags & kVZERO)) nEtaBins = 11;
1063
87f694ab
AH
1064 Double_t vzeroBins[12] = { -6, -3.7, -3.2, -2.7, -2.2, -1.7,
1065 2.8, 3.4, 3.9, 4.5, 5.1, 6 };
1066 Double_t vzeroBins2[20] = { -6, -3.7, -3.2, -2.7, -2.2, // VZERO
1067 -2.0, -1.5, -1.0, -0.5 , 0., 0.5, 1.0, 1.5, 2.0, // SPD
1068 2.8, 3.4, 3.9, 4.5, 5.1, 6 }; // VZERO
02738f97 1069
1070 Int_t nRefBins = nEtaBins; // needs to be something as default
1071 if ((fFlags & kStdQC)) {
bdd49110 1072 if ((fFlags & kSymEta) && !((fFlags & kTracks) && (fFlags & kSPD))) nRefBins = 1;
02738f97 1073 else nRefBins = 2;
1074 } else if ((fFlags & kEtaGap )) {
1075 nRefBins = 2;
1076 } else if ((fFlags & k3Cor)) {
1077 nRefBins = 24;
1078 }
1079
68589651 1080 // We initiate the reference histogram
87f694ab
AH
1081 fCumuRef = new TH2D(Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1082 Form("%s_%d_%d%s_ref", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
02738f97 1083 nRefBins, -6., 6.,
87f694ab
AH
1084 nHBins, 0.5, nHBins+0.5);
1085 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuRef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1086 SetupNUALabels(fCumuRef->GetYaxis());
1087 list->Add(fCumuRef);
2b556440 1088 // We initiate the differential histogram
87f694ab
AH
1089 fCumuDiff = new TH2D(Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1090 Form("%s_%d_%d%s_diff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1091 nEtaBins, -6., 6., nHBins, 0.5, nHBins+0.5);
1092 if ((fFlags & kVZERO)) {
02738f97 1093 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1094 fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1095 else fCumuDiff->GetXaxis()->Set(nEtaBins, vzeroBins);
87f694ab
AH
1096 }
1097 SetupNUALabels(fCumuDiff->GetYaxis());
1098 list->Add(fCumuDiff);
1099
1100 // Cumulants sum hists
1101 Int_t cBins = centAxis->GetNbins();
1102 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1103 TH3D* cumuHist = 0;
1104 Int_t nC2Bins = ((fFlags & kEtaGap) || (fFlags & k3Cor) ? kW2 : k3pWeight);
1105 Int_t nC4Bins = ((fFlags & kEtaGap) ? kW2 : ((fFlags & k3Cor) ? kW4 : kSinphi1phi2phi3p));
1106 for (Int_t n = 2; n <= fMaxMoment; n++) {
1107 // Initiate the ref cumulant sum histogram
1108 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1109 Form("%sv%d_vertex_%d_%d%s_cumuRef", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
02738f97 1110 nRefBins, -6., 6.,
87f694ab
AH
1111 cBins, 0., 100., nC2Bins, 0.5, nC2Bins+0.5);
1112 if ((fFlags & kVZERO) && (fFlags & k3Cor)) cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1113 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1114 fCumuHists.Add(cumuHist);
1115 // Initiate the diff cumulant sum histogram
1116 cumuHist = new TH3D(Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1117 Form("%sv%d_vertex_%d_%d%s_cumuDiff", fType.Data(), n, fVzMin, fVzMax, GetQCType(fFlags)),
1118 nEtaBins, -6., 6., cBins, 0., 100., nC4Bins, 0.5, nC4Bins+0.5);
1119 if ((fFlags & kVZERO)) {
02738f97 1120 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1121 cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins2);
1122 else cumuHist->GetXaxis()->Set(nEtaBins, vzeroBins);
87f694ab
AH
1123 }
1124 cumuHist->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1125 fCumuHists.Add(cumuHist);
2b556440 1126 }
1127
87f694ab
AH
1128 // Common NUA histograms
1129 fCumuNUARef = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1130 Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
02738f97 1131 nRefBins, -6., 6.,
87f694ab
AH
1132 cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1133 if ((fFlags & kVZERO) && (fFlags & k3Cor)) fCumuNUARef->GetXaxis()->Set(nEtaBins, vzeroBins2);
1134 fCumuNUARef->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1135 SetupNUALabels(fCumuNUARef->GetZaxis());
1136 fCumuNUARef->Sumw2();
1137 list->Add(fCumuNUARef);
1138
1139 fCumuNUADiff = new TH3D(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1140 Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1141 nEtaBins, -6., 6., cBins, 0., 100., nHBins, 0.5, nHBins+0.5);
1142 if ((fFlags & kVZERO)) {
02738f97 1143 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1144 fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins2);
1145 else fCumuNUADiff->GetXaxis()->Set(nEtaBins, vzeroBins);
68589651 1146 }
87f694ab
AH
1147 fCumuNUADiff->GetYaxis()->Set(cBins, centAxis->GetXbins()->GetArray());
1148 SetupNUALabels(fCumuNUADiff->GetZaxis());
1149 fCumuNUADiff->Sumw2();
1150 list->Add(fCumuNUADiff);
d420e249 1151
87f694ab
AH
1152 // We create diagnostic histograms.
1153 TList* dList = (TList*)outputlist->FindObject("Diagnostics");
1154 if (!dList) AliFatal("No diagnostics list found");
1155
1156 // Acceptance hist
02738f97 1157 Int_t nPhiBins = ((fFlags & kFMD) ? 20 : 8);
87f694ab
AH
1158 fdNdedpRefAcc = new TH2F(Form("h%sdNdedpRefAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1159 Form("%s reference flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
02738f97 1160 nEtaBins, -6., 6., nPhiBins, 0, TMath::TwoPi());
87f694ab 1161 if ((fFlags & kVZERO)) {
02738f97 1162 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1163 fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1164 else fdNdedpRefAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
87f694ab
AH
1165 }
1166 dList->Add(fdNdedpRefAcc);
1167
1168 fdNdedpDiffAcc = new TH2F(Form("h%sdNdedpDiffAcc_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1169 Form("%s differential flow acceptance map for %d cm < v_{z} < %d cm", fType.Data(), fVzMin, fVzMax),
02738f97 1170 nEtaBins, -6., 6., nPhiBins, 0, TMath::TwoPi());
87f694ab 1171 if ((fFlags & kVZERO)) {
02738f97 1172 if ((fFlags & kSPD) || (fFlags & k3Cor) || (fFlags & kEtaGap))
1173 fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins2);
1174 else fdNdedpDiffAcc->GetXaxis()->Set(nEtaBins, vzeroBins);
87f694ab
AH
1175 }
1176 dList->Add(fdNdedpDiffAcc);
1177
1178 fOutliers = new TH2F(Form("hOutliers_%s_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)),
1179 Form("Maximum #sigma from mean N_{ch} pr. bin - %s, %d < v_{z} < %d",
1180 fType.Data(), fVzMin, fVzMax),
02738f97 1181 20, 0., 100., 500, 0., ((fFlags & kMC) ? 15. : 5.));
87f694ab
AH
1182 dList->Add(fOutliers);
1183
1184 return;
2b556440 1185}
1186//_____________________________________________________________________
87f694ab 1187Bool_t AliForwardFlowTaskQC::VertexBin::FillHists(TH2D& dNdetadphi, Double_t cent, UShort_t mode)
2b556440 1188{
1189 //
87f694ab 1190 // Fill reference and differential eta-histograms
2b556440 1191 //
87f694ab
AH
1192 // Parameters:
1193 // dNdetadphi: 2D histogram with input data
1194 // cent: centrality
1195 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
2b556440 1196 //
2b556440 1197 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
68589651 1198 Bool_t useEvent = kTRUE;
1199
2b556440 1200 // Fist we reset histograms
87f694ab
AH
1201 if ((mode & kReset)) {
1202 if ((mode & kFillRef)) fCumuRef->Reset();
1203 if ((mode & kFillDiff)) fCumuDiff->Reset();
1204 }
2b556440 1205 // Then we loop over the input and calculate sum cos(k*n*phi)
1206 // and fill it in the reference and differential histograms
87f694ab
AH
1207 Int_t nBadBins = 0;
1208 Double_t limit = 9999.;
4b5b52b7 1209 for (Int_t etaBin = 1; etaBin <= dNdetadphi.GetNbinsX(); etaBin++) {
87f694ab
AH
1210 Double_t eta = dNdetadphi.GetXaxis()->GetBinCenter(etaBin);
1211 // Numbers to cut away bad events
1212 Double_t runAvg = 0;
1213 Double_t max = 0;
1214 Int_t nInAvg = 0;
1215 Double_t avgSqr = 0;
d420e249 1216 for (Int_t phiBin = 0; phiBin <= dNdetadphi.GetNbinsY(); phiBin++) {
87f694ab 1217 // Check for acceptance
d420e249 1218 if (phiBin == 0) {
87f694ab
AH
1219 if (dNdetadphi.GetBinContent(etaBin, 0) == 0) break;
1220 // Central limit for eta gap break for reference flow
1221 if ((fFlags & kEtaGap) && (mode & kFillRef) &&
1222 TMath::Abs(eta) < fEtaGap) break;
1223 // Backward and forward eta gap break for reference flow
008eda2b 1224 if ((fFlags & kEtaGap) && (mode & kFillRef) && TMath::Abs(eta) > TMath::Abs(limit)) break;
610fbb44 1225 if ((fFlags & kStdQC) && (fFlags & kMC) && !(fFlags & kTracks)) {
02738f97 1226 if (!(fFlags & kSPD) && TMath::Abs(eta) < 1.75) break;
1227 if ((fFlags & kSPD) && TMath::Abs(eta) > 2.00) break;
1228 }
87f694ab 1229 if (limit > 1e3) limit = dNdetadphi.GetXaxis()->GetBinLowEdge(etaBin);
d420e249 1230 continue;
87f694ab
AH
1231 } // End of phiBin == 0
1232 Double_t phi = dNdetadphi.GetYaxis()->GetBinCenter(phiBin);
1233 Double_t weight = dNdetadphi.GetBinContent(etaBin, phiBin);
1234
d420e249 1235 // We calculate the average Nch per. bin
1236 avgSqr += weight*weight;
2b556440 1237 runAvg += weight;
1238 nInAvg++;
d420e249 1239 if (weight == 0) continue;
2b556440 1240 if (weight > max) max = weight;
87f694ab 1241 // Fill into Cos() and Sin() hists
610fbb44 1242 if ((mode & kFillRef) && !((fFlags & kTracks) && (fFlags & kMC) && TMath::Abs(eta) > 0.75)) {
87f694ab
AH
1243 fCumuRef->Fill(eta, 0., weight);// mult goes in underflowbin - no visual, but not needed?
1244 fdNdedpRefAcc->Fill(eta, phi, weight);
68589651 1245 }
87f694ab
AH
1246 if ((mode & kFillDiff)) {
1247 fCumuDiff->Fill(eta, 0., weight);
1248 fdNdedpDiffAcc->Fill(eta, phi, weight);
008eda2b 1249 }
87f694ab
AH
1250 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1251 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1252 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
1253 Double_t cosnPhi = weight*TMath::Cos(n*phi);
1254 Double_t sinnPhi = weight*TMath::Sin(n*phi);
1255 // fill ref
610fbb44 1256 if ((mode & kFillRef) && !((fFlags & kTracks) && (fFlags & kMC) && TMath::Abs(eta) > 0.75)) {
87f694ab
AH
1257 fCumuRef->Fill(eta, cosBin, cosnPhi);
1258 fCumuRef->Fill(eta, sinBin, sinnPhi);
68589651 1259 }
87f694ab
AH
1260 // fill diff
1261 if ((mode & kFillDiff)) {
1262 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1263 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1264 }
1265 } // End of NUA loop
1266 } // End of phi loop
68589651 1267 // Outlier cut calculations
87f694ab 1268 if (nInAvg > 0) {
d420e249 1269 runAvg /= nInAvg;
1270 avgSqr /= nInAvg;
87f694ab 1271 Double_t stdev = (nInAvg > 1 ? TMath::Sqrt(nInAvg/(nInAvg-1))*TMath::Sqrt(avgSqr - runAvg*runAvg) : 0);
d420e249 1272 Double_t nSigma = (stdev == 0 ? 0 : (max-runAvg)/stdev);
87f694ab 1273 if (fSigmaCut > 0. && nSigma >= fSigmaCut && cent < 60) nBadBins++;
3112bd03 1274 else nBadBins = 0;
d420e249 1275 fOutliers->Fill(cent, nSigma);
68589651 1276 // We still finish the loop, for fOutliers to make sense,
87f694ab 1277 // but we do no keep the event for analysis
68589651 1278 if (nBadBins > 3) useEvent = kFALSE;
d420e249 1279 }
87f694ab 1280 } // End of eta bin
d420e249 1281
68589651 1282 return useEvent;
2b556440 1283}
1284//_____________________________________________________________________
bdd49110 1285Bool_t AliForwardFlowTaskQC::VertexBin::FillTracks(TObjArray* trList, AliESDEvent* esd,
1286 AliAnalysisFilter* trFilter, UShort_t mode)
2b556440 1287{
1288 //
87f694ab 1289 // Fill reference and differential eta-histograms
2b556440 1290 //
87f694ab
AH
1291 // Parameters:
1292 // trList: list of tracks
1293 // mode: filling mode: kFillRef/kFillDiff/kFillBoth
2b556440 1294 //
2b556440 1295 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
bdd49110 1296 if (!trList && !esd) {
1297 AliError("FillTracks: No AOD track list or ESD event - something might be wrong!");
1298 return kFALSE;
1299 }
2b556440 1300
87f694ab
AH
1301 // Fist we reset histograms
1302 if ((mode & kReset)) {
1303 if ((mode & kFillRef)) fCumuRef->Reset();
1304 if ((mode & kFillDiff)) fCumuDiff->Reset();
1305 }
4b5b52b7 1306
87f694ab
AH
1307 // Then we loop over the input and calculate sum cos(k*n*phi)
1308 // and fill it in the reference and differential histograms
bdd49110 1309 Int_t nTr = 0;
1310 if (trList) nTr = trList->GetEntries();
1311 if (esd) nTr = esd->GetNumberOfTracks();
87f694ab
AH
1312 if (nTr == 0) return kFALSE;
1313 AliVTrack* tr = 0;
1237bf7a 1314 // Cuts for AOD tracks (have already been applied to ESD tracks) - except dEdx
bdd49110 1315// const tpcdEdx = 10;
87f694ab 1316 for (Int_t i = 0; i < nTr; i++) { // track loop
bdd49110 1317 tr = (trList ? (AliVTrack*)trList->At(i) : (AliVTrack*)esd->GetTrack(i));
87f694ab 1318 if (!tr) continue;
bdd49110 1319 if (esd) {
1320 AliESDtrack* esdTr = (AliESDtrack*)tr;
1321 if (!trFilter->IsSelected(esdTr)) continue;
1322 }
1323 else if (trList) { // If AOD input
981baec7 1324 Double_t pTMin = 0, pTMax = 0, etaMin = 0, etaMax = 0, minNCl = 0;
1325 UInt_t bit = 0;
bdd49110 1326 if ((fFlags & kTPC) == kTPC) pTMin = 0.2, pTMax = 5., etaMin = -0.8, etaMax = 0.8, minNCl = 70, bit = 128;
1327 if ((fFlags & kHybrid) == kHybrid) pTMin = 0.2, pTMax = 5., etaMin = -0.8, etaMax = 0.8, minNCl = 70, bit = 272;
1328
1329 AliAODTrack* aodTr = (AliAODTrack*)tr;
87f694ab 1330 if (aodTr->GetID() > -1) continue;
610fbb44 1331 if (!aodTr->TestFilterBit(bit) || aodTr->Pt() > pTMax || aodTr->Pt() < pTMin ||
87f694ab 1332 aodTr->Eta() > etaMax || aodTr->Eta() < etaMin || aodTr->GetTPCNcls() < minNCl) continue;
008eda2b 1333 }
bdd49110 1334
1335// if (tr->GetTPCsignal() < tpcdEdx) continue;
87f694ab
AH
1336 // Track accepted
1337 Double_t eta = tr->Eta();
1237bf7a 1338 if (((fFlags & kSPD) || (fFlags & kEtaGap)) && TMath::Abs(eta) < fEtaGap) continue;
87f694ab 1339 Double_t phi = tr->Phi();
5d8a14bf 1340 Double_t weight = 1.;
610fbb44 1341
87f694ab 1342 if ((mode & kFillRef)) {
610fbb44 1343 fCumuRef->Fill(eta, 0., weight);// mult goes in underflowbin - no visual, but not needed?
1344 fdNdedpRefAcc->Fill(eta, phi, weight);
68589651 1345 }
87f694ab 1346 if ((mode & kFillDiff)) {
610fbb44 1347 fCumuDiff->Fill(eta, 0., weight);
1348 fdNdedpDiffAcc->Fill(eta, phi, weight);
87f694ab
AH
1349 }
1350 for (Int_t n = 1; n <= 2*fMaxMoment; n++) {
1351 Double_t cosBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberCos(n));
1352 Double_t sinBin = fCumuDiff->GetYaxis()->GetBinCenter(GetBinNumberSin(n));
610fbb44 1353 Double_t cosnPhi = weight*TMath::Cos(n*phi);
1354 Double_t sinnPhi = weight*TMath::Sin(n*phi);
87f694ab
AH
1355 // fill ref
1356 if ((mode & kFillRef)) {
1357 fCumuRef->Fill(eta, cosBin, cosnPhi);
1358 fCumuRef->Fill(eta, sinBin, sinnPhi);
1359 }
1360 // fill diff
1361 if ((mode & kFillDiff)) {
1362 fCumuDiff->Fill(eta, cosBin, cosnPhi);
1363 fCumuDiff->Fill(eta, sinBin, sinnPhi);
1364 }
1365 } // End of NUA loop
1366 } // End of track loop
1367 return kTRUE;
1368}
1369//_____________________________________________________________________
1370void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate(Double_t cent)
1371{
1372 //
1373 // Calculate the Q cumulant up to order fMaxMoment
1374 //
1375 // Parameters:
1376 // cent: centrality of event
1377 //
1378 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
68589651 1379
87f694ab
AH
1380 // Fill out NUA hists
1381 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1382 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
5d8a14bf 1383 if (fCumuRef->GetBinContent(etaBin, 0) <= 3) continue;
bdd49110 1384 if ((fFlags & kTracks) && (fFlags && kSPD) && !(fFlags & kEtaGap)) eta = -eta;
87f694ab
AH
1385 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1386 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1387 }
1388 }
1389 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1390 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
5d8a14bf 1391 Double_t refetaBin = fCumuRef->GetXaxis()->FindBin(eta);
1392 if (fCumuRef->GetBinContent(refetaBin, 0) <= 3) continue;
87f694ab
AH
1393 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1394 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1395 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1396 }
1397 }
2f9be372 1398
87f694ab
AH
1399 // We create the objects needed for the analysis
1400 TH3D* cumuRef = 0;
1401 TH3D* cumuDiff = 0;
1402 // For each n we loop over the hists
1403 for (Int_t n = 2; n <= fMaxMoment; n++) {
1404 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1405 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1406 Int_t prevRefEtaBin = 0;
1407
1408 // Per mom. quantities
1409 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1410 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1411 Double_t dQ2nReA = 0, dQ2nImA = 0;
1412 Double_t two = 0, w2 = 0, four = 0, w4 = 0;
1413 Double_t cosPhi1Phi2 = 0, cosPhi1Phi2Phi3m = 0;
1414 Double_t sinPhi1Phi2 = 0, sinPhi1Phi2Phi3m = 0;
1415 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1416 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
02738f97 1417 Double_t refEta = eta;
bdd49110 1418 if ((fFlags & kTracks) && (fFlags && kSPD) && !(fFlags & kEtaGap)) refEta = -eta;
02738f97 1419 Int_t refEtaBinA = fCumuRef->GetXaxis()->FindBin(refEta);
1420 if ((fFlags & kEtaGap)) refEta = -eta;
1421 Int_t refEtaBinB = fCumuRef->GetXaxis()->FindBin(refEta);
87f694ab 1422 if (refEtaBinA != prevRefEtaBin) {
87f694ab
AH
1423 // Reference flow
1424 multA = fCumuRef->GetBinContent(refEtaBinA, 0);
1425 dQnReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n));
1426 dQnImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n));
1427 dQ2nReA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberCos(n*2));
1428 dQ2nImA = fCumuRef->GetBinContent(refEtaBinA, GetBinNumberSin(n*2));
1429
1430 multB = fCumuRef->GetBinContent(refEtaBinB, 0);
1431 dQnReB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberCos(n));
1432 dQnImB = fCumuRef->GetBinContent(refEtaBinB, GetBinNumberSin(n));
1433
5d8a14bf 1434 if (multA <= 3 || multB <= 3) continue;
87f694ab
AH
1435 // The reference flow is calculated
1436 // 2-particle
a6952e36 1437 if ((fFlags & kStdQC)) {
87f694ab
AH
1438 w2 = multA * (multA - 1.);
1439 two = dQnReA*dQnReA + dQnImA*dQnImA - multA;
1440 } else {
1441 w2 = multA * multB;
1442 two = dQnReA*dQnReB + dQnImA*dQnImB;
1443 }
1444 cumuRef->Fill(eta, cent, kW2Two, two);
1445 cumuRef->Fill(eta, cent, kW2, w2);
1446
1447 // The reference flow is calculated
1448 // 4-particle
1449 if ((fFlags & kStdQC)) {
1450 w4 = multA * (multA - 1.) * (multA - 2.) * (multA - 3.);
1451
1452 four = 2.*multA*(multA-3.) + TMath::Power((TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.)),2.)
1453 -4.*(multA-2.)*(TMath::Power(dQnReA,2.) + TMath::Power(dQnImA,2.))
1454 -2.*(TMath::Power(dQnReA,2.)*dQ2nReA+2.*dQnReA*dQnImA*dQ2nImA-TMath::Power(dQnImA,2.)*dQ2nReA)
1455 +(TMath::Power(dQ2nReA,2.)+TMath::Power(dQ2nImA,2.));
1456
1457 cumuRef->Fill(eta, cent, kW4Four, four);
1458 cumuRef->Fill(eta, cent, kW4, w4);
1459
1460 // NUA
1461 cosPhi1Phi2 = dQnReA*dQnReA - dQnImA*dQnImA - dQ2nReA;
1462 sinPhi1Phi2 = 2.*dQnReA*dQnImA - dQ2nImA;
1463
1464 cosPhi1Phi2Phi3m = dQnReA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1465 -dQnReA*dQ2nReA-dQnImA*dQ2nImA-2.*(multA-1)*dQnReA;
1466
1467 sinPhi1Phi2Phi3m = -dQnImA*(TMath::Power(dQnReA,2)+TMath::Power(dQnImA,2))
1468 +dQnReA*dQ2nImA-dQnImA*dQ2nReA+2.*(multA-1)*dQnImA;
1469
1470 cumuRef->Fill(eta, cent, kCosphi1phi2, cosPhi1Phi2);
1471 cumuRef->Fill(eta, cent, kSinphi1phi2, sinPhi1Phi2);
1472 cumuRef->Fill(eta, cent, kCosphi1phi2phi3m, cosPhi1Phi2Phi3m);
1473 cumuRef->Fill(eta, cent, kSinphi1phi2phi3m, sinPhi1Phi2Phi3m);
1474 cumuRef->Fill(eta, cent, k3pWeight, multA*(multA-1.)*(multA-2.));
1475 } // End of QC{4}
5d8a14bf 1476 prevRefEtaBin = refEtaBinA;
87f694ab
AH
1477 } // End of reference flow
1478 // For each etaBin bin the necessary values for differential flow is calculated
1479 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1480 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1481 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1482 Double_t p2nRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n*2));
1483 Double_t p2nIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n*2));
1484 if (mp == 0) continue;
1485 Double_t mq = 0;
1486 Double_t qnRe = 0;
1487 Double_t qnIm = 0;
1488 Double_t q2nRe = 0;
1489 Double_t q2nIm = 0;
1490
1491 // Differential flow calculations for each eta bin is done:
1492 // 2-particle differential flow
610fbb44 1493 if ((fFlags & kStdQC) && (!(fFlags & kTracks) || ((fFlags & kTracks) && (fFlags & kMC) && !(fFlags & kSPD) && TMath::Abs(eta) < 0.75))) {
87f694ab
AH
1494 mq = mp;
1495 qnRe = pnRe;
1496 qnIm = pnIm;
1497 q2nRe = p2nRe;
1498 q2nIm = p2nIm;
1499 }
2f9be372 1500
87f694ab
AH
1501 Double_t w2p = mp * multB - mq;
1502 Double_t twoPrime = pnRe*dQnReB + pnIm*dQnImB - mq;
d2bea14e 1503
87f694ab
AH
1504 cumuDiff->Fill(eta, cent, kW2Two, twoPrime);
1505 cumuDiff->Fill(eta, cent, kW2, w2p);
58f5fae2 1506
87f694ab
AH
1507 if ((fFlags & kEtaGap)) continue;
1508 // Differential flow calculations for each eta bin bin is done:
1509 // 4-particle differential flow
1510 Double_t w4p = (mp * multA - 3.*mq)*(multA - 1.)*(multA - 2.);
1511
1512 Double_t fourPrime = (TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*(pnRe*dQnReA+pnIm*dQnImA)
1513 - q2nRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))
1514 - 2.*q2nIm*dQnReA*dQnImA
1515 - pnRe*(dQnReA*dQ2nReA+dQnImA*dQ2nImA)
1516 + pnIm*(dQnImA*dQ2nReA-dQnReA*dQ2nImA)
1517 - 2.*multA*(pnRe*dQnReA+pnIm*dQnImA)
1518 - 2.*(TMath::Power(dQnReA,2.)+TMath::Power(dQnImA,2.))*mq
1519 + 6.*(qnRe*dQnReA+qnIm*dQnImA)
1520 + 1.*(q2nRe*dQ2nReA+q2nIm*dQ2nImA)
1521 + 2.*(pnRe*dQnReA+pnIm*dQnImA)
1522 + 2.*mq*multA
1523 - 6.*mq;
1524
1525 cumuDiff->Fill(eta, cent, kW4Four, fourPrime);
1526 cumuDiff->Fill(eta, cent, kW4, w4p);
1527
1528 // NUA
1529 Double_t cosPsi1Phi2 = pnRe*dQnReA - pnIm*dQnImA - q2nRe;
1530 Double_t sinPsi1Phi2 = pnRe*dQnImA + pnIm*dQnReA - q2nIm;
1531
1532 Double_t cosPsi1Phi2Phi3p = pnRe*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1533 - 1.*(q2nRe*dQnReA+q2nIm*dQnImA)
1534 - mq*dQnReA+2.*qnRe;
1535
1536 Double_t sinPsi1Phi2Phi3p = pnIm*(TMath::Power(dQnImA,2.)+TMath::Power(dQnReA,2.)-multA)
1537 - 1.*(q2nIm*dQnReA-q2nRe*dQnImA)
1538 - mq*dQnImA+2.*qnIm;
1539
1540 Double_t cosPsi1Phi2Phi3m = pnRe*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))+2.*pnIm*dQnReA*dQnImA
1541 - 1.*(pnRe*dQ2nReA+pnIm*dQ2nImA)
1542 - 2.*mq*dQnReA+2.*qnRe;
1543
1544 Double_t sinPsi1Phi2Phi3m = pnIm*(TMath::Power(dQnReA,2.)-TMath::Power(dQnImA,2.))-2.*pnRe*dQnReA*dQnImA
1545 - 1.*(pnIm*dQ2nReA-pnRe*dQ2nImA)
1546 + 2.*mq*dQnImA-2.*qnIm;
1547
1548 cumuDiff->Fill(eta, cent, kCosphi1phi2, cosPsi1Phi2);
1549 cumuDiff->Fill(eta, cent, kSinphi1phi2, sinPsi1Phi2);
1550 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3m, cosPsi1Phi2Phi3m);
1551 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3m, sinPsi1Phi2Phi3m);
1552 cumuDiff->Fill(eta, cent, k3pWeight, (mp*multA-2.*mq)*(multA-1.));
1553 cumuDiff->Fill(eta, cent, kCosphi1phi2phi3p, cosPsi1Phi2Phi3p);
1554 cumuDiff->Fill(eta, cent, kSinphi1phi2phi3p, sinPsi1Phi2Phi3p);
1555 } // End of eta loop
1556 // Event count
1557 cumuRef->Fill(-7., cent, -0.5, 1.);
1558 } // End of moment loop
1559 return;
1560}
1561//_____________________________________________________________________
1562void AliForwardFlowTaskQC::VertexBin::GetLimits(Int_t bin, Int_t& aLow, Int_t& aHigh,
1563 Int_t& bLow, Int_t& bHigh) const
1564{
1565 //
1566 // Get the limits for the 3 correlator method
1567 //
1568 // Parameters:
1569 // bin : reference bin #
1570 // aLow : Lowest bin to be included in v_A calculations
1571 // aHigh: Highest bin to be included in v_A calculations
1572 // bLow : Lowest bin to be included in v_B calculations
1573 // bHigh: Highest bin to be included in v_B calculations
1574 //
1575 if ((fFlags & kFMD)) {
1576 switch(bin) {
1577 case 0:
1578 aLow = 14; aHigh = 15;
1579 bLow = 20; bHigh = 22;
1580 break;
1581 case 1:
1582 aLow = 16; aHigh = 16;
1583 bLow = 21; bHigh = 22;
1584 break;
1585 case 2:
1586 aLow = 6; aHigh = 7;
1587 bLow = 21; bHigh = 22;
1588 break;
1589 case 3:
1590 aLow = 6; aHigh = 7;
1591 bLow = 12; bHigh = 12;
1592 break;
1593 case 4:
1594 aLow = 6; aHigh = 8;
1595 bLow = 13; bHigh = 14;
1596 break;
1597 default:
1598 AliFatal(Form("No limits for this eta region! (%d)", bin));
1599 }
1600 }
1601 else if ((fFlags & kVZERO)) {
1602 switch(bin) {
1603 case 0:
1604 aLow = 6; aHigh = 13;
1605 bLow = 17; bHigh = 18;
1606 break;
1607 case 1:
1608 aLow = 6; aHigh = 9;
1609 bLow = 17; bHigh = 18;
1610 break;
1611 case 2:
1612 aLow = 2; aHigh = 3;
1613 bLow = 17; bHigh = 18;
1614 break;
1615 case 3:
1616 aLow = 2; aHigh = 3;
1617 bLow = 6; bHigh = 9;
1618 break;
1619 case 4:
1620 aLow = 2; aHigh = 3;
1621 bLow = 6; bHigh = 13;
1622 break;
1623 default:
1624 AliFatal(Form("No limits for this eta region! (%d)", bin));
1625 }
1626 }
1627 // Try to catch cases where fEtaLimits and these values do not correspond to each other
1628 if (aHigh > fCumuNUARef->GetNbinsX() || bHigh > fCumuNUARef->GetNbinsX())
a6952e36
AH
1629 AliFatal(Form("Limits outside vtx range! (%d) - aHigh = %d, bHigh = %d, Nbins = %d",
1630 bin, aHigh, bHigh, fCumuNUARef->GetNbinsX()));
87f694ab
AH
1631}
1632//_____________________________________________________________________
1633void AliForwardFlowTaskQC::VertexBin::CumulantsAccumulate3Cor(Double_t cent)
1634{
1635 //
1636 // Calculate the Q cumulant up to order fMaxMoment
1637 //
1638 // Parameters:
1639 // cent: centrality of event
1640 //
1641 if (!fCumuRef) AliFatal("You have not called AddOutput() - Terminating!");
d226802c 1642
87f694ab
AH
1643 // Fill out NUA hists
1644 for (Int_t etaBin = 1; etaBin <= fCumuRef->GetNbinsX(); etaBin++) {
1645 Double_t eta = fCumuRef->GetXaxis()->GetBinCenter(etaBin);
1646 if (fCumuRef->GetBinContent(etaBin, 0) == 0) continue;
1647 for (Int_t qBin = 0; qBin <= fCumuRef->GetNbinsY(); qBin++) {
1648 fCumuNUARef->Fill(eta, cent, Double_t(qBin), fCumuRef->GetBinContent(etaBin, qBin));
1649 }
1650 }
1651 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1652 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1653 if (fCumuDiff->GetBinContent(etaBin, 0) == 0) continue;
1654 for (Int_t qBin = 0; qBin <= fCumuDiff->GetNbinsY(); qBin++) {
1655 fCumuNUADiff->Fill(eta, cent, Double_t(qBin), fCumuDiff->GetBinContent(etaBin, qBin));
1656 }
d2bea14e 1657 }
87f694ab
AH
1658
1659 // We create the objects needed for the analysis
1660 TH3D* cumuRef = 0;
1661 TH3D* cumuDiff = 0;
1662 // For each n we loop over the hists
1663 for (Int_t n = 2; n <= fMaxMoment; n++) {
1664 cumuRef = (TH3D*)fCumuHists.Get('r',n);
1665 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
1666
1667 // Per mom. quantities
1668 Int_t prevLim = 0;
1669 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
1670 Double_t dQnReA = 0, dQnImA = 0, multA = 0;
1671 Double_t dQnReB = 0, dQnImB = 0, multB = 0;
1672 Double_t two = 0, w2 = 0;
1673 for (Int_t etaBin = 1; etaBin <= fCumuDiff->GetNbinsX(); etaBin++) {
1674 Double_t eta = fCumuDiff->GetXaxis()->GetBinCenter(etaBin);
1675 if (fEtaLims[prevLim] < eta) {
1676 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
1677 prevLim++;
1678 multA = 0; dQnReA = 0; dQnImA = 0;
1679 multB = 0; dQnReB = 0; dQnImB = 0;
1680 // Reference flow
1681 for (Int_t a = aLow; a <= aHigh; a++) {
1682 multA += fCumuRef->GetBinContent(a, 0);
1683 dQnReA += fCumuRef->GetBinContent(a, GetBinNumberCos(n));
1684 dQnImA += fCumuRef->GetBinContent(a, GetBinNumberSin(n));
1685 }
1686 for (Int_t b = bLow; b <= bHigh; b++) {
1687 multB += fCumuRef->GetBinContent(b, 0);
1688 dQnReB += fCumuRef->GetBinContent(b, GetBinNumberCos(n));
1689 dQnImB += fCumuRef->GetBinContent(b, GetBinNumberSin(n));
1690 }
1691 // The reference flow is calculated
1692 // 2-particle
1693 w2 = multA * multB;
1694 two = dQnReA*dQnReB + dQnImA*dQnImB;
1695 } // End of reference flow
1696 cumuRef->Fill(eta, cent, kW2Two, two);
1697 cumuRef->Fill(eta, cent, kW2, w2);
1698
1699 // For each etaBin bin the necessary values for differential flow is calculated
1700 Double_t mp = fCumuDiff->GetBinContent(etaBin, 0);
1701 Double_t pnRe = fCumuDiff->GetBinContent(etaBin, GetBinNumberCos(n));
1702 Double_t pnIm = fCumuDiff->GetBinContent(etaBin, GetBinNumberSin(n));
1703 if (mp == 0) continue;
1704
1705 // Differential flow calculations for each eta bin is done:
1706 // 2-particle differential flow
1707 Double_t w2pA = mp * multA;
1708 Double_t twoPrimeA = pnRe*dQnReA + pnIm*dQnImA;
1709 cumuDiff->Fill(eta, cent, kW2Two, twoPrimeA);
1710 cumuDiff->Fill(eta, cent, kW2, w2pA);
1711
1712 Double_t w2pB = mp * multB;
1713 Double_t twoPrimeB = pnRe*dQnReB + pnIm*dQnImB;
1714 cumuDiff->Fill(eta, cent, kW4Four, twoPrimeB);
1715 cumuDiff->Fill(eta, cent, kW4, w2pB);
1716 } // End of eta loop
1717 // Event count
1718 cumuRef->Fill(-7., cent, -0.5, 1.);
1719 } // End of moment loop
1720 return;
d2bea14e 1721
1722}
1723//_____________________________________________________________________
2b556440 1724void AliForwardFlowTaskQC::VertexBin::CumulantsTerminate(TList* inlist, TList* outlist)
d2bea14e 1725{
1726 //
d2bea14e 1727 // Finalizes the Q cumulant calculations
1728 //
1729 // Parameters:
2b556440 1730 // inlist: input sumlist
1731 // outlist: output result list
d2bea14e 1732 //
87f694ab 1733
2b556440 1734 // Re-find cumulants hist if Terminate is called separately
87f694ab
AH
1735 if (!fCumuHists.IsConnected()) {
1736 TList* list = (TList*)inlist->FindObject(Form("%svertex_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1737 fCumuHists.ConnectList(Form("%sCumu_%d_%d%s", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)), list);
1738
1739 if (!fCumuNUARef)
1740 fCumuNUARef = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUARef", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1741 if (!fCumuNUADiff)
1742 fCumuNUADiff = (TH3D*)list->FindObject(Form("%s_vertex_%d_%d%s_cumuNUADiff", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
2b556440 1743 }
87f694ab
AH
1744 // Clone to avoid normalization problems when redoing terminate locally
1745 fCumuNUARef = (TH3D*)fCumuNUARef->Clone(Form("%s_vertex_%d_%d%s_cumuNUARefNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1746 fCumuNUADiff = (TH3D*)fCumuNUADiff->Clone(Form("%s_vertex_%d_%d%s_cumuNUADiffNorm", fType.Data(), fVzMin, fVzMax, GetQCType(fFlags)));
1747
1748 // Diagnostics histograms
1749 TH2I* quality = (TH2I*)outlist->FindObject(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1750 if (!quality) {
1751 quality = MakeQualityHist(Form("hQCQuality%s%s", fType.Data(), GetQCType(fFlags)));
1752 outlist->Add(quality);
1753 }
1754 TH1D* cent = (TH1D*)outlist->FindObject(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)));
1755 if (!cent) {
1756 cent = new TH1D(Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1757 Form("%s%s_cent", fType.Data(), GetQCType(fFlags)),
1758 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1759 cent->GetXaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1760 outlist->Add(cent);
1761 }
1762 TH2D* dNdetaRef = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)));
1763 if (!dNdetaRef) {
1764 dNdetaRef = new TH2D(Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1765 Form("%s%s_dNdetaRef", fType.Data(), GetQCType(fFlags)),
1766 fCumuNUARef->GetNbinsX(), fCumuNUARef->GetXaxis()->GetXmin(), fCumuNUARef->GetXaxis()->GetXmax(),
1767 fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
1768 dNdetaRef->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
1769 dNdetaRef->Sumw2();
1770 outlist->Add(dNdetaRef);
1771 }
1772 TH2D* dNdetaDiff = (TH2D*)outlist->FindObject(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)));
1773 if (!dNdetaDiff) {
1774 dNdetaDiff = new TH2D(Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1775 Form("%s%s_dNdetaDiff", fType.Data(), GetQCType(fFlags)),
1776 fCumuNUADiff->GetNbinsX(), fCumuNUADiff->GetXaxis()->GetXmin(), fCumuNUADiff->GetXaxis()->GetXmax(),
1777 fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXmin(), fCumuNUADiff->GetYaxis()->GetXmax());
1778 dNdetaDiff->GetYaxis()->Set(fCumuNUADiff->GetNbinsY(), fCumuNUADiff->GetYaxis()->GetXbins()->GetArray());
1779 dNdetaDiff->Sumw2();
1780 outlist->Add(dNdetaDiff);
1781 }
1782
1783 // Setting up outputs
1784 // Create output lists and diagnostics
d420e249 1785 TList* vtxList = (TList*)outlist->FindObject("vtxList");
1786 if (!vtxList) {
1787 vtxList = new TList();
1788 vtxList->SetName("vtxList");
1789 outlist->Add(vtxList);
1790 }
87f694ab
AH
1791 vtxList->Add(fCumuNUARef);
1792 vtxList->Add(fCumuNUADiff);
1793
1794 // Setup output profiles
1795 CumuHistos cumu2(fMaxMoment, ((fFlags & kNUAcorr) ? 2 : 0));
1796 CumuHistos cumu4(fMaxMoment, ((fFlags & kNUAcorr) ? 1 : 0));
1797
1798 cumu2.ConnectList(Form("%sQC2_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1799 if ((fFlags & kStdQC))
1800 cumu4.ConnectList(Form("%sQC4_Cumu%s_vtx_%d_%d", fType.Data(), GetQCType(fFlags), fVzMin, fVzMax), vtxList);
1801
1802 for (Int_t n = 2; n <= fMaxMoment; n++) {
1803 // 2-particle
1804 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNoNUA));
1805 if ((fFlags & k3Cor)){
1806 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNoNUA));
1807 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNoNUA));
1808 } else {
1809 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNoNUA));
1810 }
1811 // 4-particle
1812 if ((fFlags & kStdQC)) {
1813 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNoNUA));
1814 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNoNUA));
1815 }
1816 } // End of v_n result loop
1817 // NUA corrected
1818 if ((fFlags & kNUAcorr)) {
1819 for (Int_t n = 2; n <= fMaxMoment; n++) {
1820 // 2-particle
1821 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUAOld));
1822 if ((fFlags & k3Cor)) {
1823 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUAOld));
1824 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUAOld));
1825 } else {
1826 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUAOld));
1827 }
1828 // 4-particle
1829 if ((fFlags & kStdQC)) {
1830 cumu4.Add(MakeOutputHist(4, n, "Ref", CumuHistos::kNUAOld));
1831 cumu4.Add(MakeOutputHist(4, n, "Diff", CumuHistos::kNUAOld));
1832 }
1833 }
1834 for (Int_t n = 2; n <= fMaxMoment; n++) {
1835 // 2-particle
1836 cumu2.Add(MakeOutputHist(2, n, "Ref", CumuHistos::kNUA));
1837 if ((fFlags & k3Cor)) {
1838 cumu2.Add(MakeOutputHist(2, n, "DiffA", CumuHistos::kNUA));
1839 cumu2.Add(MakeOutputHist(2, n, "DiffB", CumuHistos::kNUA));
1840 } else {
1841 cumu2.Add(MakeOutputHist(2, n, "Diff", CumuHistos::kNUA));
1842 }
1843 }
1844 }
1845
1846 // Calculating the cumulants
1847 if ((fFlags & k3Cor)) {
1848 Calculate3CorFlow(cumu2, quality, cent, dNdetaRef, dNdetaDiff);
1849 } else {
1850 CalculateReferenceFlow(cumu2, cumu4, quality, cent, dNdetaRef);
1851 CalculateDifferentialFlow(cumu2, cumu4, quality, dNdetaDiff);
1852 }
1853 if ((fFlags & kNUAcorr)) {
1854 SolveCoupledFlowEquations(cumu2, 'r');
1855 if ((fFlags & k3Cor)) {
1856 SolveCoupledFlowEquations(cumu2, 'a');
1857 SolveCoupledFlowEquations(cumu2, 'b');
1858 } else {
1859 SolveCoupledFlowEquations(cumu2, 'd');
1860 }
1861 }
1862
1863 // Add to output for immediate viewing - individual vtx bins are used for final results
1864 AddVertexBins(cumu2, outlist, ((fFlags & kNUAcorr) ? 2 : 0));
1865 if ((fFlags & kStdQC)) AddVertexBins(cumu4, outlist, ((fFlags & kNUAcorr) ? 1 : 0));
1866
1867 // Setup NUA diagnoastics histograms
008eda2b 1868 TList* nualist = (TList*)outlist->FindObject("NUATerms");
1869 if (!nualist) {
1870 nualist = new TList();
1871 nualist->SetName("NUATerms");
1872 outlist->Add(nualist);
d420e249 1873 }
87f694ab
AH
1874 // Reference
1875 TH2D* nuaRef = (TH2D*)nualist->FindObject(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1876 TH2D* temp = 0;
1877 if (!nuaRef) {
1878 nuaRef = (TH2D*)fCumuNUARef->Project3D("yz");
1879 nuaRef->Scale(1./fCumuNUARef->GetNbinsX());
1880 nuaRef->SetName(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1881 nuaRef->SetTitle(Form("%sReferenceNUA%s", fType.Data(), GetQCType(fFlags)));
1882 nualist->Add(nuaRef);
1883 } else {
1884 temp = (TH2D*)fCumuNUARef->Project3D("yz");
1885 temp->Scale(1./fCumuNUARef->GetNbinsX());
1886 nuaRef->Add(temp);
1887 delete temp;
2b556440 1888 }
87f694ab
AH
1889 // Filling in underflow to make scaling possible in Terminate()
1890 nuaRef->Fill(0., -1., 1.);
1891 // Differential
1892 TH2D* nuaDiff = (TH2D*)nualist->FindObject(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1893 if (!nuaDiff) {
1894 nuaDiff = (TH2D*)fCumuNUADiff->Project3D("yz");
1895 nuaDiff->SetName(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1896 nuaDiff->SetTitle(Form("%sDifferentialNUA%s", fType.Data(), GetQCType(fFlags)));
1897 nualist->Add(nuaDiff);
1898 } else {
1899 temp = (TH2D*)fCumuNUADiff->Project3D("yz");
1900 nuaDiff->Add(temp);
1901 delete temp;
2b556440 1902 }
87f694ab
AH
1903 // Filling in underflow to make scaling possible in Terminate()
1904 nuaDiff->Fill(0., -1., 1.);
1905
1906 return;
1907}
1908//_____________________________________________________________________
1909void AliForwardFlowTaskQC::VertexBin::CalculateReferenceFlow(CumuHistos& cumu2h, CumuHistos& cumu4h, TH2I* quality,
1910 TH1D* chist, TH2D* dNdetaRef) const
1911{
1912 //
1913 // Calculates the reference flow
1914 //
1915 // Parameters:
1916 // cumu2h: CumuHistos object with QC{2} cumulants
1917 // cumu4h: CumuHistos object with QC{4} cumulants
1918 // quality: Histogram for success rate of cumulants
1919 // chist: Centrality histogram
1920 // dNdetaRef: dN/deta histogram for estimating multiplicity used for ref calculations
1921 //
1922
1923 // Normalizing common NUA hists
1924 for (Int_t cBin = 1; cBin <= fCumuNUARef->GetNbinsY(); cBin++) {
1925 Double_t cent = fCumuNUARef->GetYaxis()->GetBinCenter(cBin);
1926 for (Int_t eBin = 1; eBin <= fCumuNUARef->GetNbinsX(); eBin++) {
1927 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(eBin);
1928 Double_t mult = fCumuNUARef->GetBinContent(eBin, cBin, 0);
1929 if (mult == 0) continue;
1930 for (Int_t qBin = 1; qBin <= fCumuNUARef->GetNbinsZ(); qBin++) {
1931 fCumuNUARef->SetBinContent(eBin, cBin, qBin, fCumuNUARef->GetBinContent(eBin, cBin, qBin)/mult);
1932 fCumuNUARef->SetBinError(eBin, cBin, qBin, fCumuNUARef->GetBinError(eBin, cBin, qBin)/mult);
1933 }
1934 // Fill dN/deta diagnostics
1935 dNdetaRef->Fill(eta, cent, mult);
1936 }
008eda2b 1937 }
87f694ab 1938
58f5fae2 1939 // For flow calculations
87f694ab
AH
1940 TH3D* cumuRef = 0;
1941 TH2D* cumu2 = 0;
1942 TH2D* cumu2NUAold = 0;
87f694ab
AH
1943 TH2D* cumu4 = 0;
1944 TH2D* cumu4NUA = 0;
1945 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
1946 // Loop over cumulant histogram for final calculations
1947 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
1948 cumu2 = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
1949 if ((fFlags & kNUAcorr)) {
1950 cumu2NUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
87f694ab
AH
1951 }
1952 if ((fFlags & kStdQC)) {
1953 cumu4 = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNoNUA);
1954 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('r', n, CumuHistos::kNUAOld);
1955 }
1956 cumuRef = (TH3D*)fCumuHists.Get('r', n);
1957 // Begin loops
1958 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
1959 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
1960 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
1961 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
1962 for (Int_t etaBin = 1; etaBin <= cumuRef->GetNbinsX(); etaBin++) { // Eta loop begins
1963 Double_t eta = cumuRef->GetXaxis()->GetBinCenter(etaBin);
02738f97 1964 Double_t refEta = eta;
1965 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(refEta);
1966 if ((fFlags & kEtaGap)) refEta = -eta;
1967 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(refEta);
87f694ab
AH
1968 // 2-particle reference flow
1969 Double_t w2Two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
1970 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
1971 if (w2 == 0) continue;
1972 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
1973 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
1974 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
1975 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
1976 Double_t cos2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(2*n));
1977 Double_t sin2nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(2*n));
1978 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
1979 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
1980 Double_t two = w2Two / w2;
1981 Double_t qc2 = two;
1982 if (qc2 >= 0) cumu2->Fill(eta, cent, TMath::Sqrt(qc2));
1983
1984 if ((fFlags & kNUAcorr)) {
1985 // Old NUA
1986 // With no eta gap the last two terms are <<cos(phi)>>^2 and <<sin(phi)>>^2,
1987 // with eta gap the different coverage is taken into account.
1988 // The next line covers both cases.
1989 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
1990 // Extra NUA term from 2n cosines and sines
5d8a14bf 1991 Double_t den = 1+(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB);
87f694ab
AH
1992 if (den != 0) qc2 /= den;
1993 else qc2 = 0;
1994 }
1995 if (qc2 <= 0) {
1996 if (fDebug > 0)
1997 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
1998 fType.Data(), n, qc2, eta, cent));
1999 quality->Fill((n-2)*qualityFactor+2, Int_t(cent));
2000 continue;
2001 }
2002 Double_t vnTwo = TMath::Sqrt(qc2);
2003 if (!TMath::IsNaN(vnTwo)) {
2004 quality->Fill((n-2)*qualityFactor+1, Int_t(cent));
2005 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, vnTwo);
2006 }
2b556440 2007
87f694ab
AH
2008 if (!(fFlags & kStdQC)) continue;
2009 // 4-particle reference flow
2010 Double_t w4Four = cumuRef->GetBinContent(refEtaBinA, cBin, kW4Four);
2011 Double_t w4 = cumuRef->GetBinContent(refEtaBinA, cBin, kW4);
2012 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
2013 if (w4 == 0 || multm1m2 == 0) continue;
2014 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2015 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2016 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2017 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2018
2019 cosP1nPhi1P1nPhi2 /= w2;
2020 sinP1nPhi1P1nPhi2 /= w2;
2021 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2022 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2023 Double_t four = w4Four / w4;
2024 Double_t qc4 = four-2.*TMath::Power(two,2.);
2025 if (qc4 < 0) cumu4->Fill(eta, cent, TMath::Power(-qc4, 0.25));
2026
2027 if ((fFlags & kNUAcorr)) {
2028 qc4 += - 4.*cosP1nPhiA*cosP1nPhi1M1nPhi2M1nPhi3
2029 + 4.*sinP1nPhiA*sinP1nPhi1M1nPhi2M1nPhi3-TMath::Power(cosP1nPhi1P1nPhi2,2.)-TMath::Power(sinP1nPhi1P1nPhi2,2.)
2030 + 4.*cosP1nPhi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2031 + 8.*sinP1nPhi1P1nPhi2*sinP1nPhiA*cosP1nPhiA
2032 + 8.*two*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2033 - 6.*TMath::Power((TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.)),2.);
2034 }
2035 if (qc4 >= 0) {
2036 if (fDebug > 0)
2037 AliInfo(Form("%s: QC_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2038 fType.Data(), n, qc2, eta, cent));
2039 quality->Fill((n-2)*qualityFactor+6, Int_t(cent));
2040 continue;
2041 }
2042 Double_t vnFour = TMath::Power(-qc4, 0.25);
2043 if (!TMath::IsNaN(vnFour*multm1m2)) {
2044 quality->Fill((n-2)*qualityFactor+5, Int_t(cent));
2045 if ((fFlags & kNUAcorr)) cumu4NUA->Fill(eta, cent, vnFour);
2046 }
2047 } // End of eta
2048 } // End of cent
2049 } // End of moment
d420e249 2050
87f694ab
AH
2051 return;
2052}
2053//_____________________________________________________________________
2054void AliForwardFlowTaskQC::VertexBin::CalculateDifferentialFlow(CumuHistos& cumu2h, CumuHistos& cumu4h,
2055 TH2I* quality, TH2D* dNdetaDiff) const
2056{
2057 //
2058 // Calculates the differential flow
2059 //
2060 // Parameters:
2061 // cumu2h: CumuHistos object with QC{2} cumulants
2062 // cumu4h: CumuHistos object with QC{4} cumulants
2063 // quality: Histogram for success rate of cumulants
2064 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2065 //
2066
2067 for (Int_t cBin = 1; cBin <= fCumuNUADiff->GetNbinsY(); cBin++) {
2068 Double_t cent = fCumuNUADiff->GetYaxis()->GetBinCenter(cBin);
2069 for (Int_t eBin = 1; eBin <= fCumuNUADiff->GetNbinsX(); eBin++) {
2070 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(eBin);
2071 Double_t mult = fCumuNUADiff->GetBinContent(eBin, cBin, 0);
2072 if (mult == 0) continue;
2073 for (Int_t qBin = 1; qBin <= fCumuNUADiff->GetNbinsZ(); qBin++) {
2074 fCumuNUADiff->SetBinContent(eBin, cBin, qBin, fCumuNUADiff->GetBinContent(eBin, cBin, qBin)/mult);
2075 fCumuNUADiff->SetBinError(eBin, cBin, qBin, fCumuNUADiff->GetBinError(eBin, cBin, qBin)/mult);
008eda2b 2076 }
87f694ab
AH
2077 dNdetaDiff->Fill(eta, cent, mult);
2078 }
2079 }
2b556440 2080
87f694ab
AH
2081 // For flow calculations
2082 TH3D* cumuRef = 0;
2083 TH3D* cumuDiff = 0;
2084 TH2D* cumu2 = 0;
2085 TH2D* cumu2NUAold = 0;
87f694ab
AH
2086 TH2D* cumu4 = 0;
2087 TH2D* cumu4NUA = 0;
2088 Int_t qualityFactor = ((fFlags & kStdQC) ? 8 : 4); // used for correctly filling in quality hists
2089 // Loop over cumulant histogram for final calculations
2090 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2091 cumu2 = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNoNUA);
2092 if ((fFlags & kNUAcorr)) {
2093 cumu2NUAold = (TH2D*)cumu2h.Get('d', n, CumuHistos::kNUAOld);
87f694ab 2094 }
fdd86891 2095 if ((fFlags & kStdQC)) {
87f694ab
AH
2096 cumu4 = (TH2D*)cumu4h.Get('d',n);
2097 if ((fFlags & kNUAcorr)) cumu4NUA = (TH2D*)cumu4h.Get('d', n, CumuHistos::kNUAOld);
2098 }
2099 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2100 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2101 for (Int_t cBin = 1; cBin <= cumuDiff->GetNbinsY(); cBin++) { // Centrality loop begins
2102 Double_t cent = cumuDiff->GetYaxis()->GetBinCenter(cBin);
2103 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2104 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2105 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
02738f97 2106 Double_t refEta = eta;
2107 Int_t refEtaBinA = fCumuNUARef->GetXaxis()->FindBin(refEta);
2108 if ((fFlags & kEtaGap)) refEta = -eta;
2109 Int_t refEtaBinB = fCumuNUARef->GetXaxis()->FindBin(refEta);
87f694ab
AH
2110
2111 // Reference objects
2112 Double_t w2 = cumuRef->GetBinContent(refEtaBinA, cBin, kW2);
2113 if (w2 == 0) continue;
2114 Double_t two = cumuRef->GetBinContent(refEtaBinA, cBin, kW2Two);
2115 two /= w2;
2116 Double_t cosP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberCos(n));
2117 Double_t sinP1nPhiA = fCumuNUARef->GetBinContent(refEtaBinA, cBin, GetBinNumberSin(n));
2118 Double_t cosP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(n));
2119 Double_t sinP1nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(n));
2120 Double_t cos2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberCos(2*n));
2121 Double_t sin2nPhiB = fCumuNUARef->GetBinContent(refEtaBinB, cBin, GetBinNumberSin(2*n));
2122
2123 // 2-particle differential flow
2124 Double_t w2pTwoPrime = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2125 Double_t w2p = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2126 if (w2p == 0) continue;
2127 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2128 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2129 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2130 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2131 Double_t twoPrime = w2pTwoPrime / w2p;
2132
2133 Double_t qc2Prime = twoPrime;
2134 cumu2->Fill(eta, cent, qc2Prime);
2135 if ((fFlags & kNUAcorr)) {
2136 // Old nua
2137 qc2Prime -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB;
2138 // Extra NUA term from 2n cosines and sines
5d8a14bf 2139 qc2Prime /= (1.+(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
87f694ab
AH
2140 }
2141 if (!TMath::IsNaN(qc2Prime)) {
2142 quality->Fill((n-2)*qualityFactor+3, Int_t(cent));
2143 if ((fFlags & kNUAcorr)) cumu2NUAold->Fill(eta, cent, qc2Prime);
2144 }
2145 else
2146 quality->Fill((n-2)*qualityFactor+4, Int_t(cent));
2147 if (fDebug > 1)
2148 AliInfo(Form("%s: QC'_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2149 fType.Data(), n, qc2Prime, eta, cent));
2150
2151 if (!(fFlags & kStdQC)) continue;
2152 // Reference objects
2153 Double_t cosP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2);
2154 Double_t sinP1nPhi1P1nPhi2 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2);
2155 Double_t cosP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kCosphi1phi2phi3m);
2156 Double_t sinP1nPhi1M1nPhi2M1nPhi3 = cumuRef->GetBinContent(refEtaBinA, cBin, kSinphi1phi2phi3m);
2157 Double_t multm1m2 = cumuRef->GetBinContent(refEtaBinA, cBin, k3pWeight);
2158 cosP1nPhi1P1nPhi2 /= w2;
2159 sinP1nPhi1P1nPhi2 /= w2;
2160 cosP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2161 sinP1nPhi1M1nPhi2M1nPhi3 /= multm1m2;
2162
2163 // 4-particle differential flow
2164 Double_t w4pFourPrime = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2165 Double_t w4p = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2166 Double_t mpqMult = cumuDiff->GetBinContent(etaBin, cBin, k3pWeight);
2167 if (w4p == 0 || mpqMult == 0) continue;
2168 Double_t cosP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2);
2169 Double_t sinP1nPsi1P1nPhi2 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2);
2170 Double_t cosP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3m);
2171 Double_t sinP1nPsi1M1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3m);
2172 Double_t cosP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kCosphi1phi2phi3p);
2173 Double_t sinP1nPsi1P1nPhi2M1nPhi3 = cumuDiff->GetBinContent(etaBin, cBin, kSinphi1phi2phi3p);
2174
2175 cosP1nPsi1P1nPhi2 /= w2p;
2176 sinP1nPsi1P1nPhi2 /= w2p;
2177 cosP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2178 sinP1nPsi1M1nPhi2M1nPhi3 /= mpqMult;
2179 cosP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2180 sinP1nPsi1P1nPhi2M1nPhi3 /= mpqMult;
2181
2182 Double_t fourPrime = w4pFourPrime / w4p;
2183 Double_t qc4Prime = fourPrime-2.*twoPrime*two;
fdd86891 2184 if (cumu4) cumu4->Fill(eta, cent, qc4Prime);
87f694ab
AH
2185
2186 if ((fFlags & kNUAcorr)) {
2187 qc4Prime += - cosP1nPsi*cosP1nPhi1M1nPhi2M1nPhi3
2188 + sinP1nPsi*sinP1nPhi1M1nPhi2M1nPhi3
2189 - cosP1nPhiA*cosP1nPsi1M1nPhi2M1nPhi3
2190 + sinP1nPhiA*sinP1nPsi1M1nPhi2M1nPhi3
2191 - 2.*cosP1nPhiA*cosP1nPsi1P1nPhi2M1nPhi3
2192 - 2.*sinP1nPhiA*sinP1nPsi1P1nPhi2M1nPhi3
2193 - cosP1nPsi1P1nPhi2*cosP1nPhi1P1nPhi2
2194 - sinP1nPsi1P1nPhi2*sinP1nPhi1P1nPhi2
2195 + 2.*cosP1nPhi1P1nPhi2*(cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2196 + 2.*sinP1nPhi1P1nPhi2*(cosP1nPsi*sinP1nPhiA+sinP1nPsi*cosP1nPhiA)
2197 + 4.*two*(cosP1nPsi*cosP1nPhiA+sinP1nPsi*sinP1nPhiA)
2198 + 2.*cosP1nPsi1P1nPhi2*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2199 + 4.*sinP1nPsi1P1nPhi2*cosP1nPhiA*sinP1nPhiA
2200 + 4.*twoPrime*(TMath::Power(cosP1nPhiA,2.)+TMath::Power(sinP1nPhiA,2.))
2201 - 6.*(TMath::Power(cosP1nPhiA,2.)-TMath::Power(sinP1nPhiA,2.))
2202 * (cosP1nPsi*cosP1nPhiA-sinP1nPsi*sinP1nPhiA)
2203 - 12.*cosP1nPhiA*sinP1nPhiA
2204 * (sinP1nPsi*cosP1nPhiA+cosP1nPsi*sinP1nPhiA);
2205 }
2206// Double_t vnFourDiff = - qc4Prime / TMath::Power(-qc4, 0.75);
2207 if (!TMath::IsNaN(qc4Prime*mpqMult)) {
2208 quality->Fill((n-2)*qualityFactor+7, Int_t(cent));
fdd86891 2209 if (cumu4NUA) cumu4NUA->Fill(eta, cent, qc4Prime);
87f694ab
AH
2210 }
2211 else
2212 quality->Fill((n-2)*qualityFactor+8, Int_t(cent));
2213 if (fDebug > 1)
2214 AliInfo(Form("%s: v_%d{4} = %1.3f for eta = %1.2f and centrality %3.1f",
2215 fType.Data(), n, qc4Prime, eta, cent));
2216 } // End of eta loop
2217 } // End of centrality loop
2218 } // End of moment
2219
2220 return;
2221}
2222//_____________________________________________________________________
2223void AliForwardFlowTaskQC::VertexBin::Calculate3CorFlow(CumuHistos& cumu2h, TH2I* quality, TH1D* chist,
2224 TH2D* dNdetaRef, TH2D* dNdetaDiff) const
2225{
2226 //
2227 // Calculates the 3 sub flow
2228 //
2229 // Parameters:
2230 // cumu2h: CumuHistos object with QC{2} cumulants
2231 // quality: Histogram for success rate of cumulants
2232 // chist: Centrality histogram
2233 // dNdetaDiff: dN/deta histogram for estimating multiplicity used for diff calculations
2234 //
2235
2236 // For flow calculations
2237 TH3D* cumuRef = 0;
2238 TH3D* cumuDiff = 0;
2239 TH2D* cumu2r = 0;
2240 TH2D* cumu2rNUAold = 0;
87f694ab
AH
2241 TH2D* cumu2a = 0;
2242 TH2D* cumu2aNUAold = 0;
87f694ab
AH
2243 TH2D* cumu2b = 0;
2244 TH2D* cumu2bNUAold = 0;
87f694ab
AH
2245 // Loop over cumulant histogram for final calculations
2246 for (Int_t n = 2; n <= fMaxMoment; n++) { // Moment loop begins
2247 cumu2r = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNoNUA);
2248 cumu2a = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNoNUA);
2249 cumu2b = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNoNUA);
2250 if ((fFlags & kNUAcorr)) {
2251 cumu2rNUAold = (TH2D*)cumu2h.Get('r', n, CumuHistos::kNUAOld);
87f694ab 2252 cumu2aNUAold = (TH2D*)cumu2h.Get('a', n, CumuHistos::kNUAOld);
87f694ab 2253 cumu2bNUAold = (TH2D*)cumu2h.Get('b', n, CumuHistos::kNUAOld);
87f694ab
AH
2254 }
2255 cumuRef = (TH3D*)fCumuHists.Get('r',n);
2256 cumuDiff = (TH3D*)fCumuHists.Get('d',n);
2257 for (Int_t cBin = 1; cBin <= cumuRef->GetNbinsY(); cBin++) { // Centrality loop begins
2258 Double_t cent = cumuRef->GetYaxis()->GetBinCenter(cBin);
2259 if (n == 2) chist->Fill(cent, cumuRef->GetBinContent(0, cBin, 0));
2260 if (fDebug > 0) AliInfo(Form("%s - v_%d: centrality %3.1f:..", fType.Data(), n, cent));
2261 // Here it starts!
2262 Int_t prevLim = 0;
2263 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2264 Double_t cosP1nPhiA = 0;
2265 Double_t sinP1nPhiA = 0;
2266 Double_t cos2nPhiA = 0;
2267 Double_t sin2nPhiA = 0;
2268 Double_t cosP1nPhiB = 0;
2269 Double_t sinP1nPhiB = 0;
2270 Double_t cos2nPhiB = 0;
2271 Double_t sin2nPhiB = 0;
2272 Double_t multA = 0;
2273 Double_t multB = 0;
2274
2275 for (Int_t etaBin = 1; etaBin <= cumuDiff->GetNbinsX(); etaBin++) { // Eta loop begins
2276 Double_t eta = cumuDiff->GetXaxis()->GetBinCenter(etaBin);
2277 // 2-particle reference flow
2278 Double_t w2Two = cumuRef->GetBinContent(etaBin, cBin, kW2Two);
2279 Double_t w2 = cumuRef->GetBinContent(etaBin, cBin, kW2);
2280 if (w2 == 0) continue;
2281
2282 // Update NUA for new range!
2283 if (fEtaLims[prevLim] < eta) {
2284 GetLimits(prevLim, aLow, aHigh, bLow, bHigh);
2285 prevLim++;
2286 cosP1nPhiA = 0; sinP1nPhiA = 0; cos2nPhiA = 0; sin2nPhiA = 0; multA = 0;
2287 cosP1nPhiB = 0; sinP1nPhiB = 0; cos2nPhiB = 0; sin2nPhiB = 0; multB = 0;
2288 for (Int_t a = aLow; a <= aHigh; a++) {
2289 cosP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n));
2290 sinP1nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n));
2291 cos2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2292 sin2nPhiA += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2293 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2294 }
2295 for (Int_t b = bLow; b <= bHigh; b++) {
2296 cosP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n));
2297 sinP1nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n));
2298 cos2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2299 sin2nPhiB += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2300 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2301 }
1237bf7a 2302 if (multA == 0 || multB == 0) {
2303 AliWarning(Form("Empty NUA values for 3Cor! (%s)", cumuRef->GetName()));
2304 continue;
2305 }
87f694ab
AH
2306 cosP1nPhiA /= multA;
2307 sinP1nPhiA /= multA;
2308 cos2nPhiA /= multA;
2309 sin2nPhiA /= multA;
2310 cosP1nPhiB /= multB;
2311 sinP1nPhiB /= multB;
2312 cos2nPhiB /= multB;
2313 sin2nPhiB /= multB;
2314
2315 dNdetaRef->Fill(eta, cent, multA+multB);
2316 }
2317 Double_t two = w2Two / w2;
2318
2319 Double_t qc2 = two;
2320 if (qc2 >= 0) cumu2r->Fill(eta, cent, TMath::Sqrt(qc2));
2321
2322 if ((fFlags & kNUAcorr)) {
2323 // Old nua
2324 qc2 -= cosP1nPhiA*cosP1nPhiB + sinP1nPhiA*sinP1nPhiB;
2325 // Extra NUA term from 2n cosines and sines
5d8a14bf 2326 qc2 /= (1+(cos2nPhiA*cos2nPhiB + sin2nPhiA*sin2nPhiB));
87f694ab
AH
2327 }
2328 if (qc2 <= 0) {
2329 if (fDebug > 0)
2330 AliInfo(Form("%s: QC_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f - skipping",
2331 fType.Data(), n, qc2, eta, cent));
2332 quality->Fill((n-2)*4+2, Int_t(cent));
2333 continue;
2334 }
2335 Double_t vnTwo = TMath::Sqrt(qc2);
2336 if (!TMath::IsNaN(vnTwo)) {
2337 quality->Fill((n-2)*4+1, Int_t(cent));
2338 if ((fFlags & kNUAcorr)) cumu2rNUAold->Fill(eta, cent, vnTwo);
2339 }
2340
2341 // 2-particle differential flow
2342 Double_t w2pTwoPrimeA = cumuDiff->GetBinContent(etaBin, cBin, kW2Two);
2343 Double_t w2pA = cumuDiff->GetBinContent(etaBin, cBin, kW2);
2344 Double_t w2pTwoPrimeB = cumuDiff->GetBinContent(etaBin, cBin, kW4Four);
2345 Double_t w2pB = cumuDiff->GetBinContent(etaBin, cBin, kW4);
2346 if (w2pA == 0 || w2pB == 0) continue;
2347 Double_t cosP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(n));
2348 Double_t sinP1nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(n));
2349 Double_t cos2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberCos(2*n));
2350 Double_t sin2nPsi = fCumuNUADiff->GetBinContent(etaBin, cBin, GetBinNumberSin(2*n));
2351 Double_t mult = fCumuNUADiff->GetBinContent(etaBin, cBin, 0);
2352 if (mult == 0) continue;
2353 cosP1nPsi /= mult;
2354 sinP1nPsi /= mult;
2355 cos2nPsi /= mult;
2356 sin2nPsi /= mult;
2357 Double_t twoPrimeA = w2pTwoPrimeA / w2pA;
2358 Double_t twoPrimeB = w2pTwoPrimeB / w2pB;
2359 dNdetaDiff->Fill(eta, cent, mult);
2360
2361 Double_t qc2PrimeA = twoPrimeA;
2362 Double_t qc2PrimeB = twoPrimeB;
2363 if (qc2PrimeA*qc2PrimeB >= 0) {
2364 cumu2a->Fill(eta, cent, qc2PrimeA);
2365 cumu2b->Fill(eta, cent, qc2PrimeB);
2366 }
2367 if ((fFlags & kNUAcorr)) {
2368 // Old nua
2369 qc2PrimeA -= cosP1nPsi*cosP1nPhiA + sinP1nPsi*sinP1nPhiA;
2370 qc2PrimeB -= cosP1nPsi*cosP1nPhiB + sinP1nPsi*sinP1nPhiB; // Is this OK?
2371 // Extra NUA term from 2n cosines and sines
5d8a14bf 2372 if (cos2nPsi*cos2nPhiA + sin2nPsi*sin2nPhiA != -1.) qc2PrimeA /= (1.+(cos2nPsi*cos2nPhiA + sin2nPsi*sin2nPhiA));
2373 if (cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB != -1.) qc2PrimeB /= (1.+(cos2nPsi*cos2nPhiB + sin2nPsi*sin2nPhiB));
87f694ab
AH
2374 }
2375 if (!TMath::IsNaN(qc2PrimeA) && !TMath::IsNaN(qc2PrimeB) && qc2 != 0) {
2376 if (qc2PrimeA*qc2PrimeB >= 0) {
2377 quality->Fill((n-2)*4+3, Int_t(cent));
2378 if ((fFlags & kNUAcorr)) cumu2aNUAold->Fill(eta, cent, qc2PrimeA);
2379 if ((fFlags & kNUAcorr)) cumu2bNUAold->Fill(eta, cent, qc2PrimeB);
2380 }
d420e249 2381 }
2382 else
87f694ab
AH
2383 quality->Fill((n-2)*4+4, Int_t(cent));
2384 if (fDebug > 1)
2385 AliInfo(Form("%s: QC'a_%d{2} = %1.3f, QC'b_%d{2} = %1.3f for eta = %1.2f and centrality %3.1f",
2386 fType.Data(), n, qc2PrimeA, n, qc2PrimeB, eta, cent));
2387 } // End of eta loop
2388 } // End of centrality loop
2389 } // End of moment
d420e249 2390
87f694ab
AH
2391 return;
2392}
2393//_____________________________________________________________________
2394void AliForwardFlowTaskQC::VertexBin::SolveCoupledFlowEquations(CumuHistos& cumu, const Char_t type) const
2395{
2396 //
2397 // Function to solve the coupled flow equations
2398 // We solve it by using matrix calculations:
2399 // A*v_n = V => v_n = A^-1*V
2400 // First we set up a TMatrixD container to make ROOT
2401 // do the inversions in an efficient way, we multiply the current <<2>> estimates.
2402 // Then we fill new TH2D's if the corrected <<2>>'s (cumuNUA object).
2403 //
2404 // Parameters:
2405 // cumu: CumuHistos object - uncorrected
2406 // type: Reference ('r') or differential ('d') or ('a' or 'b') for 3 correlator
2407 //
2408
2409 // We start by declaring Matrix and vector objects, as their constructors are quite heavy
2410 TMatrixD mNUA(fMaxMoment-1, fMaxMoment-1);
2411 TVectorD vQC2(fMaxMoment-1);
2412
2413 for (Int_t cBin = 1; cBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsY(); cBin++) { // cent loop
2414 Double_t cent = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinCenter(cBin);
2415 for (Int_t eBin = 1; eBin <= cumu.Get(type, 2, CumuHistos::kNUAOld)->GetNbinsX(); eBin++) { // eta loop
2416 Double_t eta = cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin);
2417 mNUA.Zero(); // reset matrix
2418 vQC2.Zero(); // reset vector
2419 for (Int_t n = 0; n < fMaxMoment-1; n++) { // moment loop
2420 vQC2(n) = static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUAOld))->GetBinContent(eBin, cBin);
2421 if (type == 'r' || type == 'R') vQC2(n) *= vQC2(n); // going back to <<2>>
2422 for (Int_t m = 0; m < fMaxMoment-1; m++) { // cross moment
2423 mNUA(n,m) = CalculateNUAMatrixElement(n, m, type, eBin, cBin);
2424 } // End of cross moment loop
2425 } // End of moment loop
2426 // Invert matrix
2427 Double_t det = 0;
2428 mNUA.Invert(&det);
2429 // If determinant is non-zero we go with corrected results
2430 if (det != 0 ) vQC2 = mNUA*vQC2;
2431 else AliWarning(Form("Determinant == 0 - cent: %d-%d, eta: %f, type: '%c', data: %s, vtx: %d-%d%s",
2432 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinLowEdge(cBin)),
2433 Int_t(cumu.Get(type, 2, CumuHistos::kNUAOld)->GetYaxis()->GetBinUpEdge(cBin)),
2434 cumu.Get(type, 2, CumuHistos::kNUAOld)->GetXaxis()->GetBinCenter(eBin),
2435 type, fType.Data(), fVzMin, fVzMax,
fdd86891 2436 GetQCType(fFlags, kTRUE)));
87f694ab
AH
2437 // Go back to v_n for ref. keep <<2'>> for diff. flow).
2438 for (Int_t n = 0; n < fMaxMoment-1; n++) {
2439 Double_t vnTwo = 0;
2440 if (type == 'r' || type == 'R')
2441 vnTwo = (vQC2(n) > 0. ? TMath::Sqrt(vQC2(n)) : 0.);
2442 else {
2443 // is really more <<2'>> in this case
2444 vnTwo = vQC2(n);
2445 }
2446 // Fill in corrected v_n
2447 if (vnTwo != 0) static_cast<TH2D*>(cumu.Get(type, n+2, CumuHistos::kNUA))->Fill(eta, cent, vnTwo);
2448 } // End of moment loop
2b556440 2449 } // End of eta loop
2b556440 2450 } // End of centrality loop
d226802c 2451 return;
d2bea14e 2452}
d2bea14e 2453//_____________________________________________________________________
87f694ab 2454Double_t AliForwardFlowTaskQC::VertexBin::CalculateNUAMatrixElement(Int_t n, Int_t m, Char_t type, Int_t binA, Int_t cBin) const
d420e249 2455{
87f694ab
AH
2456 //
2457 // Calculates the (n,m)-th element in the NUA matrix: 1 if n == m, otherwise:
2458 // <<cos[(n-m)phi1]>>*<<cos[(n-m)phi2]>> + <<sin[(n-m)phi1]>>*<<sin[(n-m)phi2]>>
2459 // NUA(n,m) = -----------------------------------------------------------------------------
2460 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
d420e249 2461 //
87f694ab
AH
2462 // <<cos[(n+m)phi1]>>*<<cos[(n+m)phi2]>> + <<sin[(n+m)phi1]>>*<<sin[(n+m)phi2]>>
2463 // + -----------------------------------------------------------------------------
2464 // 1 + <<cos[2nphi1]>>*<<cos[2nphi2]>> + <<sin[2nphi1]>>*<<sin[2nphi2]>>
d420e249 2465 //
87f694ab
AH
2466 // Parameters:
2467 // n: row
2468 // m: coumn
2469 // type: Reference ('r') or differential ('d') or ('a' or 'b')
2470 // binA: eta bin of phi1
2471 // cBin: centrality bin
2472 //
2473 // Return: NUA(n,m)
2474 //
2475 if (n == m) return 1.;
2476 n += 2;
2477 m += 2;
2478
2479 Double_t cosnMmPhi1 = 0, cosnMmPhi2 = 0, sinnMmPhi1 = 0, sinnMmPhi2 = 0;
2480 Double_t cosnPmPhi1 = 0, cosnPmPhi2 = 0, sinnPmPhi1 = 0, sinnPmPhi2 = 0;
2481 Double_t cos2nPhi1 = 0, cos2nPhi2 = 0, sin2nPhi1 = 0, sin2nPhi2 = 0;
2482
2483 // reference flow
2484 if (type == 'r' || type == 'R') {
2485 if ((fFlags & k3Cor)) {
2486 Double_t eta = fCumuNUARef->GetXaxis()->GetBinCenter(binA);
2487 Int_t i = 0;
2488 while (fEtaLims[i] < eta) i++;
2489 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2490 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2491 Double_t multA = 0, multB = 0;
2492 for (Int_t a = aLow; a <= aHigh; a++) {
2493 cosnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n-m));
2494 sinnMmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n-m));
2495 cosnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(n+m));
2496 sinnPmPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(n+m));
2497 cos2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberCos(2*n));
2498 sin2nPhi1 += fCumuNUARef->GetBinContent(a, cBin, GetBinNumberSin(2*n));
2499 multA += fCumuNUARef->GetBinContent(a, cBin, 0);
2500 }
2501 for (Int_t b = bLow; b <= bHigh; b++) {
2502 cosnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n-m));
2503 sinnMmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n-m));
2504 cosnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(n+m));
2505 sinnPmPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(n+m));
2506 cos2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberCos(2*n));
2507 sin2nPhi2 += fCumuNUARef->GetBinContent(b, cBin, GetBinNumberSin(2*n));
2508 multB += fCumuNUARef->GetBinContent(b, cBin, 0);
2509 }
2510 if (multA == 0 || multB == 0) {
2511 if (fDebug > 0) AliWarning("multA or multB == 0 in matrix elements, aborting NUA");
2512 return 0.;
2513 }
2514 cosnMmPhi1 /= multA;
2515 sinnMmPhi1 /= multA;
2516 cosnPmPhi1 /= multA;
2517 sinnPmPhi1 /= multA;
2518 cos2nPhi1 /= multA;
2519 sin2nPhi1 /= multA;
2520 cosnMmPhi2 /= multB;
2521 sinnMmPhi2 /= multB;
2522 cosnPmPhi2 /= multB;
2523 sinnPmPhi2 /= multB;
2524 cos2nPhi2 /= multB;
2525 sin2nPhi2 /= multB;
2526 } else {
2527 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUARef->GetXaxis()->GetBinCenter(binA));
2528 cosnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2529 sinnMmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2530 cosnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2531 sinnPmPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2532 cos2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2533 sin2nPhi1 = fCumuNUARef->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2534 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2535 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2536 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2537 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2538 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2539 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2540 }
2541 } // differential flow
2542 else if (type == 'd' || type == 'D') {
2543 Int_t binB = fCumuNUARef->GetXaxis()->FindBin(-fCumuNUADiff->GetXaxis()->GetBinCenter(binA));
2544 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2545 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2546 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2547 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2548 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2549 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2550 cosnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n-m));
2551 sinnMmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n-m));
2552 cosnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(n+m));
2553 sinnPmPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(n+m));
2554 cos2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberCos(2*n));
2555 sin2nPhi2 = fCumuNUARef->GetBinContent(binB, cBin, GetBinNumberSin(2*n));
2556 } // 3 correlator part a or b
2557 else if (type == 'a' || type == 'A' || type == 'b' || type == 'B') {
2558 Double_t mult1 = 0, mult2 = 0;
2559 // POIs
2560 cosnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n-m));
2561 sinnMmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n-m));
2562 cosnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(n+m));
2563 sinnPmPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(n+m));
2564 cos2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberCos(2*n));
2565 sin2nPhi1 = fCumuNUADiff->GetBinContent(binA, cBin, GetBinNumberSin(2*n));
2566 mult1 = fCumuNUADiff->GetBinContent(binA, cBin, 0);
2567 // RPs
2568 Double_t eta = fCumuNUADiff->GetXaxis()->GetBinCenter(binA);
2569 Int_t i = 0;
2570 while (fEtaLims[i] < eta) i++;
2571 Int_t aLow = 0, aHigh = 0, bLow = 0, bHigh = 0;
2572 GetLimits(i-1, aLow, aHigh, bLow, bHigh);
2573 Int_t lLow = ((type == 'a' || type == 'A') ? aLow : bLow);
2574 Int_t lHigh = ((type == 'a' || type == 'A') ? aHigh : bHigh);
2575 for (Int_t l = lLow; l <= lHigh; l++) {
2576 cosnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n-m));
2577 sinnMmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n-m));
2578 cosnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(n+m));
2579 sinnPmPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(n+m));
2580 cos2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberCos(2*n));
2581 sin2nPhi2 += fCumuNUARef->GetBinContent(l, cBin, GetBinNumberSin(2*n));
2582 mult2 += fCumuNUARef->GetBinContent(l, cBin, 0);
2583 }
2584 if (mult1 == 0 || mult2 == 0) {
2585 if (fDebug > 0) AliWarning("mult1 or mult2 == 0 in matrix elements, aborting NUA");
2586 return 0.;
2587 }
2588 cosnMmPhi1 /= mult1;
2589 sinnMmPhi1 /= mult1;
2590 cosnPmPhi1 /= mult1;
2591 sinnPmPhi1 /= mult1;
2592 cos2nPhi1 /= mult1;
2593 sin2nPhi1 /= mult1;
2594 cosnMmPhi2 /= mult2;
2595 sinnMmPhi2 /= mult2;
2596 cosnPmPhi2 /= mult2;
2597 sinnPmPhi2 /= mult2;
2598 cos2nPhi2 /= mult2;
2599 sin2nPhi2 /= mult2;
d420e249 2600 }
d420e249 2601
87f694ab
AH
2602 // Actual calculation
2603 Double_t e = cosnMmPhi1*cosnMmPhi2 + sinnMmPhi1*sinnMmPhi2 + cosnPmPhi1*cosnPmPhi2 + sinnPmPhi1*sinnPmPhi2;
2604 Double_t den = 1 + cos2nPhi1*cos2nPhi2 + sin2nPhi1*sin2nPhi2;
2605 if (den != 0) e /= den;
2606 else return 0.;
2607
2608 return e;
2609}
2610//_____________________________________________________________________
2611void AliForwardFlowTaskQC::VertexBin::AddVertexBins(CumuHistos& cumu, TList* list, UInt_t nNUA) const
2612{
2613 //
2614 // Add up vertex bins with flow results
2615 //
2616 // Parameters:
2617 // cumu: CumuHistos object with vtxbin results
2618 // list: Outout list with added results
2619 // nNUA: # of NUA histograms to loop over
2620 //
2621 TH2D* vtxHist = 0;
2622 TProfile2D* avgProf = 0;
2623 TString name;
2624 Int_t nT = ((fFlags & k3Cor) ? 3 : 2);
2625 Char_t ct = '\0';
2626 for (UInt_t nua = 0; nua <= nNUA; nua++) { // NUA loop
2627 for (Int_t n = 2; n <= fMaxMoment; n++) { // moment loop
2628 for (Int_t t = 0; t < nT; t++) { // type loop (r/d/a/b)
2629 // Find type
2630 switch (t) {
2631 case 0: ct = 'r'; break;
2632 case 1: ct = ((fFlags & k3Cor) ? 'a' : 'd'); break;
2633 case 2: ct = 'b'; break;
2634 default: ct = '\0'; break;
2635 }
2636 vtxHist = static_cast<TH2D*>(cumu.Get(ct,n,nua));
2637 if (!vtxHist) {
2638 AliWarning("VertexBin::AddVertexBins: vtxHist not found!");
2639 continue;
2640 }
2641 name = vtxHist->GetName();
2642 // Strip name of vtx info
2643 Ssiz_t l = name.Last('x')-3;
2644 name.Resize(l);
2645 avgProf = (TProfile2D*)list->FindObject(name.Data());
2646 // if no output profile yet, make one
2647 if (!avgProf) {
2648 avgProf = new TProfile2D(name.Data(), name.Data(),
2649 vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXmin(), vtxHist->GetXaxis()->GetXmax(),
2650 vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXmin(), vtxHist->GetYaxis()->GetXmax());
2651 if (vtxHist->GetXaxis()->IsVariableBinSize())
2652 avgProf->GetXaxis()->Set(vtxHist->GetNbinsX(), vtxHist->GetXaxis()->GetXbins()->GetArray());
2653 if (vtxHist->GetYaxis()->IsVariableBinSize())
2654 avgProf->GetYaxis()->Set(vtxHist->GetNbinsY(), vtxHist->GetYaxis()->GetXbins()->GetArray());
2655 list->Add(avgProf);
2656 }
2657 // Fill in, cannot be done with Add function.
2658 for (Int_t e = 1; e <= vtxHist->GetNbinsX(); e++) { // eta loop
2659 Double_t eta = vtxHist->GetXaxis()->GetBinCenter(e);
2660 for (Int_t c = 1; c <= vtxHist->GetNbinsY(); c++) { // cent loop
2661 Double_t cent = vtxHist->GetYaxis()->GetBinCenter(c);
2662 Double_t cont = vtxHist->GetBinContent(e, c);
2663 if (cont == 0) continue;
2664 avgProf->Fill(eta, cent, cont);
2665 } // End of cent loop
2666 } // End of eta loop
2667 } // End of type loop
2668 } // End of moment loop
2669 } // End of nua loop
2670}
2671//_____________________________________________________________________
2672Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberCos(Int_t n) const
2673{
2674 //
2675 // Get the bin number of <<cos(nphi)>>
2676 //
2677 // Parameters:
2678 // n: moment
2679 //
2680 // Return: bin number
2681 //
2682 Int_t bin = 0;
2683 n = TMath::Abs(n);
2684
2685 if (n == 0) bin = fMaxMoment*4-1;
2686 else bin = n*2-1;
2687
2688 return bin;
2689}
2690//_____________________________________________________________________
2691Int_t AliForwardFlowTaskQC::VertexBin::GetBinNumberSin(Int_t n) const
2692{
2693 //
2694 // Get the bin number of <<sin(nphi)>>
2695 //
2696 // Parameters:
2697 // n: moment
2698 //
2699 // Return: bin number
2700 //
2701 Int_t bin = 0;
2702 n = TMath::Abs(n);
2703
2704 if (n == 0) bin = fMaxMoment*4;
2705 else bin = n*2;
2706
2707 return bin;
2708}
2709//_____________________________________________________________________
2710void AliForwardFlowTaskQC::VertexBin::SetupNUALabels(TAxis* a) const
2711{
2712 //
2713 // Setup NUA labels on axis
2714 //
2715 // Parameters:
2716 // a: Axis to set up
2717 //
2718 if (a->GetNbins() != GetBinNumberSin()) AliFatal("SetupNUALabels: Wrong number of bins on axis");
2719
2720 Int_t i = 1, j= 1;
2721 while (i <= a->GetNbins()) {
2722 a->SetBinLabel(i++, Form("<<cos(%d#varphi)>>", j));
2723 a->SetBinLabel(i++, Form("<<sin(%d#varphi)>>", j++));
d420e249 2724 }
2725
2726 return;
2727}
2728//_____________________________________________________________________
87f694ab
AH
2729TH2I* AliForwardFlowTaskQC::VertexBin::MakeQualityHist(const Char_t* name) const
2730{
2731 //
2732 // Add a histogram for checking the analysis quality
2733 //
2734 // Parameters:
2735 // const char*: name of data type
2736 //
2737 // Return: histogram for tracking successful calculations
2738 //
2739 Int_t nBins = ((fFlags & kStdQC) ? 8 : 4);
2740 TH2I* quality = new TH2I(name, name, (fMaxMoment-1)*nBins, 1, (fMaxMoment-1)*nBins+1, fCumuNUARef->GetNbinsY(),
2741 fCumuNUARef->GetYaxis()->GetXmin(), fCumuNUARef->GetYaxis()->GetXmax());
2742 quality->GetYaxis()->Set(fCumuNUARef->GetNbinsY(), fCumuNUARef->GetYaxis()->GetXbins()->GetArray());
2743 for (Int_t i = 2, j = 1; i <= fMaxMoment; i++) {
2744 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} > 0", i));
2745 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{2} <= 0", i));
2746 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} > 0", i));
2747 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{2} <= 0", i));
2748 if ((fFlags & kStdQC)) {
2749 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} < 0", i));
2750 quality->GetXaxis()->SetBinLabel(j++, Form("QC_{%d}{4} >= 0", i));
2751 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} < 0", i));
2752 quality->GetXaxis()->SetBinLabel(j++, Form("QC'_{%d}{4} >= 0", i));
2753 }
2754 }
2755
2756 return quality;
2757}
2758//_____________________________________________________________________
2759TH2D* AliForwardFlowTaskQC::VertexBin::MakeOutputHist(Int_t qc, Int_t n, const Char_t* ctype, UInt_t nua) const
2760{
2761 //
2762 // Setup a TH2D for the output
2763 //
2764 // Parameters:
2765 // qc # of particle correlations
2766 // n flow moment
2767 // ref Type: r/d/a/b
2768 // nua For nua corrected hists?
2769 //
2770 // Return: 2D hist for results
2771 //
2772 Bool_t ref = ((ctype[0] == 'R') || (ctype[0] == 'r'));
2773 TAxis* xAxis = (ref ? fCumuNUARef->GetXaxis() : fCumuNUADiff->GetXaxis());
2774 TAxis* yAxis = (ref ? fCumuNUARef->GetYaxis() : fCumuNUADiff->GetYaxis());
2775 TString ntype = "";
2776 switch (nua) {
2777 case CumuHistos::kNoNUA: ntype = "Un"; break;
2778 case CumuHistos::kNUAOld: ntype = "NUAOld"; break;
2779 case CumuHistos::kNUA: ntype = "NUA"; break;
2780 default: break;
2781 }
2782 TH2D* h = new TH2D(Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2783 fType.Data(), qc, n, ctype, ntype.Data(),
2784 GetQCType(fFlags), fVzMin, fVzMax),
2785 Form("%sQC%d_v%d_%s_%sCorr%s_vtx_%d_%d",
2786 fType.Data(), qc, n, ctype, ntype.Data(),
2787 GetQCType(fFlags), fVzMin, fVzMax),
2788 xAxis->GetNbins(), xAxis->GetXmin(), xAxis->GetXmax(),
2789 yAxis->GetNbins(), yAxis->GetXmin(), yAxis->GetXmax());
2790 if (xAxis->IsVariableBinSize()) h->GetXaxis()->Set(xAxis->GetNbins(), xAxis->GetXbins()->GetArray());
2791 h->GetYaxis()->Set(yAxis->GetNbins(), yAxis->GetXbins()->GetArray());
2792
2793 return h;
2794}
2795//_____________________________________________________________________
d420e249 2796void AliForwardFlowTaskQC::PrintFlowSetup() const
2797{
2798 //
87f694ab 2799 // Print the setup of the flow task
d420e249 2800 //
87f694ab
AH
2801 Printf("=======================================================");
2802 Printf("%s::Print", this->IsA()->GetName());
2803 Printf("Forward detector: :\t%s", ((fFlowFlags & kFMD) ? "FMD" : "VZERO"));
2804 Printf("Number of bins in vertex axis :\t%d", fVtxAxis->GetNbins());
2805 Printf("Range of vertex axis :\t[%3.1f,%3.1f]",
d420e249 2806 fVtxAxis->GetXmin(), fVtxAxis->GetXmax());
87f694ab
AH
2807 Printf("Number of bins in centrality axis :\t%d", fCentAxis->GetNbins());
2808 printf("Centrality binning :\t");
2809 for (Int_t cBin = 1; cBin <= fCentAxis->GetNbins(); cBin++) {
2810 printf("%02d-%02d%% ", Int_t(fCentAxis->GetBinLowEdge(cBin)), Int_t(fCentAxis->GetBinUpEdge(cBin)));
2811 if (cBin == fCentAxis->GetNbins()) printf("\n");
2812 else if (cBin % 4 == 0) printf("\n\t\t\t\t\t");
2813 }
2814 printf("Doing flow analysis for :\t");
2815 for (Int_t n = 2; n <= fMaxMoment; n++) printf("v%d ", n);
d420e249 2816 printf("\n");
87f694ab 2817 TString type = "Standard QC{2} and QC{4} calculations.";
87f694ab
AH
2818 if ((fFlowFlags & kEtaGap)) type = "QC{2} with a rapidity gap.";
2819 if ((fFlowFlags & k3Cor)) type = "QC{2} with 3 correlators.";
bdd49110 2820 if ((fFlowFlags & kTPC) == kTPC) type.ReplaceAll(".", " with TPC tracks for reference.");
2821 if ((fFlowFlags & kHybrid) == kHybrid) type.ReplaceAll(".", " with hybrid tracks for reference.");
87f694ab
AH
2822 Printf("QC calculation type :\t%s", type.Data());
2823 Printf("Symmetrize ref. flow wrt. eta = 0 :\t%s", ((fFlowFlags & kSymEta) ? "true" : "false"));
2824 Printf("Apply NUA correction terms :\t%s", ((fFlowFlags & kNUAcorr) ? "true" : "false"));
2825 Printf("Satellite vertex flag :\t%s", ((fFlowFlags & kSatVtx) ? "true" : "false"));
2826 Printf("FMD sigma cut: :\t%f", fFMDCut);
2827 Printf("SPD sigma cut: :\t%f", fSPDCut);
bdd49110 2828 if ((fFlowFlags & kEtaGap) || (fFlowFlags & kTracks))
87f694ab
AH
2829 Printf("Eta gap: :\t%f", fEtaGap);
2830 Printf("=======================================================");
2831}
2832//_____________________________________________________________________
2833const Char_t* AliForwardFlowTaskQC::GetQCType(UShort_t flags, Bool_t prependUS)
2834{
2835 //
2836 // Get the type of the QC calculations
2837 // Used for naming of objects in the VertexBin class,
2838 // important to avoid memory problems when running multiple
2839 // initializations of the class with different setups
2840 //
2841 // Parameters:
2842 // flags: Flow flags for type determination
2843 // prependUS: Prepend an underscore (_) to the name
2844 //
2845 // Return: QC calculation type
2846 //
2847 TString type = "";
2848 if ((flags & kStdQC)) type = "StdQC";
2849 else if ((flags & kEtaGap)) type = "EtaGap";
2850 else if ((flags & k3Cor)) type = "3Cor";
2851 else type = "UNKNOWN";
2852 if (prependUS) type.Prepend("_");
bdd49110 2853 if ((flags & kTPC) == kTPC) type.Append("TPCTr");
2854 if ((flags & kHybrid) == kHybrid) type.Append("HybTr");
2855
87f694ab
AH
2856 return type.Data();
2857}
2858//_____________________________________________________________________
fdd86891 2859TH1* AliForwardFlowTaskQC::CumuHistos::Get(Char_t t, Int_t n, UInt_t nua) const
87f694ab
AH
2860{
2861 //
2862 // Get histogram/profile for type t and moment n
2863 //
2864 // Parameters:
2865 // t: type = 'r'/'d'
2866 // n: moment
2867 // nua: NUA type
2868 //
2869 n = GetPos(n, nua);
2870 if (n < 0) AliFatal(Form("CumuHistos out of range: (%c,%d)", t, n));
2871
2872 TH1* h = 0;
2873 Int_t pos = -1;
2874 if (t == 'r' || t == 'R') pos = n;
2875 else if (t == 'd' || t == 'D') pos = n;
2876 else if (t == 'a' || t == 'A') pos = 2*n;
2877 else if (t == 'b' || t == 'B') pos = 2*n+1;
2878 else AliFatal(Form("CumuHistos wrong type: %c", t));
2879
2880 if (t == 'r' || t == 'R') {
2881 if (pos < fRefHists->GetEntries()) {
2882 h = (TH1*)fRefHists->At(pos);
2883 }
2884 } else if (pos < fDiffHists->GetEntries()) {
2885 h = (TH1*)fDiffHists->At(pos);
2886 }
2887 if (!h) AliFatal(Form("No hist found in list %c at pos %d", t, pos));
2888
2889 return h;
2890}
2891//_____________________________________________________________________
2892void AliForwardFlowTaskQC::CumuHistos::ConnectList(TString name, TList* l)
2893{
2894 //
2895 // Connect an output list with this object
2896 //
2897 // Parameters:
2898 // name: base name
2899 // l: list to keep outputs in
2900 //
2901 TString ref = name;
2902 ref.ReplaceAll("Cumu","CumuRef");
2903 fRefHists = (TList*)l->FindObject(ref.Data());
2904 if (!fRefHists) {
2905 fRefHists = new TList();
2906 fRefHists->SetName(ref.Data());
2907 l->Add(fRefHists);
2908 } else {
2909 // Check that the list correspond to fMaxMoments
2910 if (fRefHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1))
2911 AliError("CumuHistos::ConnectList Wrong number of hists in ref list,"
2912 "you are doing something wrong!");
2913 }
2914 TString diff = name;
2915 diff.ReplaceAll("Cumu","CumuDiff");
2916 fDiffHists = (TList*)l->FindObject(diff.Data());
2917 if (!fDiffHists) {
2918 fDiffHists = new TList();
2919 fDiffHists->SetName(diff.Data());
2920 l->Add(fDiffHists);
2921 } else {
2922 // Check that the list correspond to fMaxMoment
2923 if ((fDiffHists->GetEntries() != (fMaxMoment-1.)*(fNUA+1)) &&
2924 (fDiffHists->GetEntries() != 2*(fMaxMoment-1.)*(fNUA+1)))
2925 AliError(Form("CumuHistos::ConnectList Wrong number of hists in diff list,"
2926 "you are doing something wrong! (%s)",name.Data()));
2927 }
d420e249 2928
2929}
2930//_____________________________________________________________________
87f694ab
AH
2931void AliForwardFlowTaskQC::CumuHistos::Add(TH1* h) const
2932{
2933 //
2934 // Add a histogram to this objects lists
2935 //
2936 // Parameters:
2937 // h: histogram/profile to add
2938 //
2939 TString name = h->GetName();
2940 if (name.Contains("Ref")) {
2941 if (fRefHists) fRefHists->Add(h);
fdd86891 2942 else AliFatal("CumuHistos::Add() - fRefHists does not exist");
87f694ab
AH
2943 // Check that the list correspond to fMaxMoments
2944 if (fRefHists->GetEntries() > (fNUA+1)*(fMaxMoment-1.))
2945 AliError("CumuHistos::Add wrong number of hists in ref list, "
2946 "you are doing something wrong!");
2947 }
2948 else if (name.Contains("Diff")) {
2949 if (fDiffHists) fDiffHists->Add(h);
fdd86891 2950 else AliFatal("CumuHistos::Add() - fDiffHists does not exist");
87f694ab
AH
2951 // Check that the list correspond to fMaxMoment
2952 if (fDiffHists->GetEntries() > 2*(fNUA+1)*(fMaxMoment-1.))
2953 AliError("CumuHistos::Add wrong number of hists in diff list, "
2954 "you are doing something wrong!");
2955 }
2956 return;
2957}
2958//_____________________________________________________________________
2959Int_t AliForwardFlowTaskQC::CumuHistos::GetPos(Int_t n, UInt_t nua) const
2960{
2961 //
2962 // Get position in list of moment n objects
2963 // To take care of different numbering schemes
2964 //
2965 // Parameters:
2966 // n: moment
2967 // nua: # of nua corrections applied
2968 //
2969 // Return: position #
2970 //
2971 if (n > fMaxMoment) return -1;
2972 else return (n-2)+nua*(fMaxMoment-1);
2973}
2974//_____________________________________________________________________
d2bea14e 2975//
2976//
2977// EOF