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