1 //////////////////////////////////////////////////////////////////////
5 // Author: Emanuele Simili
7 //////////////////////////////////////////////////////////////////////
9 //_____________________________________________________________
12 // AliFlowEvent is the basic class to perform flow study in ALICE.
13 // The AliFlowEvent object contains data mebers wich summarize the ESD
14 // informations that are most useful for flow study, together with a
15 // collection of tracks (AliFlowTrackCollection) and reconstructed v0s.
16 // The class also implements member functions to calculate Multiplicity,
17 // Mean P and Pt, Q (the event plane vector), Psi (the event plane angle),
18 // normalized q (Q/sqrt(Mult) and Q/sqrt(sum of weights^2)), moreover,
19 // functions to separate random or eta sub-events, to fill the bayesian vector
20 // of particle abundance (for bayesian p.id calculation), to plug-in weights
21 // (to make the tracks' distribution isotropic and to enhance the resolution),
22 // and to select the tracks that are used in the event plane calculation (for
23 // each harmonic, selection, and subevent.
24 // AliFlowEvent supports the standard analysis as well as the Cumulant
25 // Analysis: method to extract the generating functions for the old and new
26 // cumulant methods is also there.
27 // The Flow Event structure (AliFlowEvent, AliFlowTrack, AliFlowV0 and
28 // AliFlowSelection) is independent from AliRoot, i.e. once the FlowEvents
29 // are filled from the AliESD or the MC KineTree (see AliFlowInterface: here
30 // AliRoot is needed), the flow analysis itself can be performed just under
31 // ROOT (see AliFlowAnalysisMaker).
33 // AliFlowEvent is adapted from the original class StFlowEvent, succesfully
34 // employed to study flow in the STAR experiment at RICH.
35 // Original Authors: Raimond Snellings & Art Poskanzer
38 #include "AliFlowEvent.h"
39 #include "AliFlowConstants.h"
44 using namespace std; //required for resolving the 'cout' symbol
47 Bool_t AliFlowEvent::fPtWgt = kFALSE ; // gives pT-based weights
48 Bool_t AliFlowEvent::fEtaWgt = kFALSE ; // gives eta-based weights
49 Bool_t AliFlowEvent::fOnePhiWgt = kTRUE ; // kTRUE --> ENABLEs SINGLE WEIGHT ISTOGRAM , kFALSE --> ENABLEs 3 WEIGHT ISTOGRAMS
50 Bool_t AliFlowEvent::fNoWgt = kFALSE ; // No Weight is used
51 // - Eta Sub-Events (later used to calculate the resolution)
52 Bool_t AliFlowEvent::fEtaSubs = kFALSE ; // makes eta subevents
54 ClassImp(AliFlowEvent)
55 //-----------------------------------------------------------
56 AliFlowEvent::AliFlowEvent(Int_t lenght)
58 // Default constructor: initializes the ObjArray of FlowTracks and FlowV0s,
59 // cleans the internal variables, sets all the weights to 1, sets default flags.
67 for(int zz=0;zz<3;zz++) { fZDCenergy[zz] = 0. ; }
69 // Make a new track collection
70 fTrackCollection = new TObjArray(lenght) ;
71 fV0Collection = new TObjArray(0) ;
73 // Set Weights Arrays to 1 (default)
74 for(int nS=0;nS<Flow::nSels;nS++)
76 for(int nH=0;nH<Flow::nHars;nH++)
78 for(int nP=0;nP<Flow::nPhiBins;nP++)
80 // enable this with: SetOnePhiWgt()
81 fPhiWgt[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgt[nS][nH][nP] << endl ;
82 // enable these with: SetFirstLastPhiWgt()
83 fPhiWgtPlus[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgtPlus[nS][nH][nP] << endl ;
84 fPhiWgtMinus[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgtMinus[nS][nH][nP] << endl ;
85 fPhiWgtCross[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgtCross[nS][nH][nP] << endl ;
89 //for(int nH=0;nH<Flow::nHars;nH++) { fExtPsi[nH] = 0. ; fExtRes[nH] = 0. ; }
91 // The Expected particles abundance is taken directly from Flow::fBayesian[] (see Bayesian P.Id.)
95 //-----------------------------------------------------------
96 AliFlowEvent::~AliFlowEvent()
98 // Default distructor: deletes the ObjArrays.
100 fTrackCollection->Delete() ; delete fTrackCollection ;
101 fV0Collection->Delete() ; delete fV0Collection ;
103 //-------------------------------------------------------------
105 //-------------------------------------------------------------
106 Double_t AliFlowEvent::PhiWeightRaw(Int_t selN, Int_t harN, AliFlowTrack* pFlowTrack) const
108 // Weight for making the event plane isotropic in the lab.
110 float phi = pFlowTrack->Phi() ; if(phi < 0.) { phi += 2*TMath::Pi() ; }
111 Double_t eta = (Double_t)pFlowTrack->Eta() ;
112 int n = (int)((phi/(2*TMath::Pi()))*Flow::nPhiBins);
114 Double_t phiWgt = 1. ;
117 phiWgt = (Double_t)fPhiWgt[selN][harN][n]; //cout << "Selection " << selN << " ; Harmonic " << harN << " ; PhiBin " << n << " - Wgt = " << phiWgt << endl ;
119 else if(FirstLastPhiWgt())
121 float zFirstPoint = pFlowTrack->ZFirstPoint(); // float zLastPoint = pFlowTrack->ZLastPoint();
123 if (zFirstPoint > 0. && eta > 0.) { phiWgt = (Double_t)fPhiWgtPlus[selN][harN][n] ; }
124 else if(zFirstPoint < 0. && eta < 0.) { phiWgt = (Double_t)fPhiWgtMinus[selN][harN][n] ; }
125 else { phiWgt = (Double_t)fPhiWgtCross[selN][harN][n] ; }
130 //-------------------------------------------------------------
131 Double_t AliFlowEvent::Weight(Int_t selN, Int_t harN, AliFlowTrack* pFlowTrack) const
133 // Weight for enhancing the resolution (eta gives sign +/- for Odd Harmonics)
135 bool oddHar = (harN+1) % 2 ;
136 Double_t phiWgt = 1. ;
139 Double_t pt = (Double_t)pFlowTrack->Pt();
140 if(pt < Flow::fPtWgtSaturation) { phiWgt *= pt ; }
141 else { phiWgt *= Flow::fPtWgtSaturation ; } // pt weighting going constant
143 Double_t eta = (Double_t)pFlowTrack->Eta();
144 Double_t etaAbs = TMath::Abs(eta);
145 if(EtaWgt() && oddHar) { phiWgt *= etaAbs ; }
146 if(oddHar && eta < 0.) { phiWgt *= -1. ; }
150 //-------------------------------------------------------------
151 Double_t AliFlowEvent::PhiWeight(Int_t selN, Int_t harN, AliFlowTrack* pFlowTrack) const
153 // Weight for making the event plane isotropic in the lab and enhancing the resolution
154 // (it simply rerurns PhiWeightRaw() * Weight()). If fNoWgt = kTRUE, returns +/-1 ,
155 // basing on Sign(eta), for odd harmonics .
157 if(fNoWgt) // no weights (but +/- according to eta)
159 bool oddHar = (harN+1) % 2 ;
160 if(oddHar) { return TMath::Sign((Double_t)1.,(Double_t)pFlowTrack->Eta()) ; }
161 else { return (Double_t)1. ; }
163 Double_t phiWgtRaw = PhiWeightRaw(selN, harN, pFlowTrack);
164 Double_t weight = Weight(selN, harN, pFlowTrack);
165 if(Flow::fDebug) { cout << "[PhiWeight]: phiWgtRaw = " << phiWgtRaw << " , weight = " << weight << " , eta = " << pFlowTrack->Eta() << endl ; }
167 return phiWgtRaw * weight;
169 //-------------------------------------------------------------
170 Int_t AliFlowEvent::Mult(AliFlowSelection* pFlowSelect)
172 // Multiplicity of tracks in the specified Selection
176 int sub = pFlowSelect->Sub() ;
177 if(sub<0) { return fMult[pFlowSelect->Sel()][pFlowSelect->Har()] ; }
178 else { return fMultSub[sub][pFlowSelect->Sel()][pFlowSelect->Har()] ; }
183 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
185 AliFlowTrack* pFlowTrack ;
186 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
187 if(pFlowSelect->Select(pFlowTrack)) { mult++ ; }
191 //-------------------------------------------------------------
192 Float_t AliFlowEvent::MeanPt(AliFlowSelection* pFlowSelect)
194 // Mean pt of tracks in the specified Selection
196 Double_t meanPt = 0. ;
200 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
202 AliFlowTrack* pFlowTrack ;
203 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
204 if (pFlowSelect->Select(pFlowTrack))
206 sumPt += pFlowTrack->Pt();
210 if(mult) { meanPt = sumPt/(float)mult ; }
214 //-------------------------------------------------------------
215 TVector2 AliFlowEvent::Q(AliFlowSelection* pFlowSelect)
217 // Event plane vector for the specified Selection
221 int sub = pFlowSelect->Sub() ;
222 if(sub<0) { return fQ[pFlowSelect->Sel()][pFlowSelect->Har()] ; }
223 else { return fQSub[sub][pFlowSelect->Sel()][pFlowSelect->Har()] ; }
227 Double_t mQx=0. , mQy=0. ;
228 int selN = pFlowSelect->Sel() ;
229 int harN = pFlowSelect->Har() ;
230 double order = (double)(harN + 1) ;
233 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
235 AliFlowTrack* pFlowTrack ;
236 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
237 if(pFlowSelect->Select(pFlowTrack))
239 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
240 float phi = pFlowTrack->Phi();
241 mQx += phiWgt * cos(phi * order) ;
242 mQy += phiWgt * sin(phi * order) ;
243 if(Flow::fDebug) { cout << itr << " phi = " << phi << " , wgt = " << phiWgt << endl ; }
250 //-------------------------------------------------------------
251 Float_t AliFlowEvent::Psi(AliFlowSelection* pFlowSelect)
253 // Event plane angle for the specified Selection
255 int harN = pFlowSelect->Har() ;
256 float order = (float)(harN + 1) ;
259 TVector2 mQ = Q(pFlowSelect);
260 if(mQ.Mod()) // if vector is not 0
262 psi= mQ.Phi() / order ;
263 if (psi < 0.) { psi += 2*TMath::Pi() / order ; }
267 //-------------------------------------------------------------
268 TVector2 AliFlowEvent::NormQ(AliFlowSelection* pFlowSelect)
270 // Normalized Q = Q/sqrt(sum of weights^2) for the specified Selection
274 TVector2 mQ = fQ[pFlowSelect->Sel()][pFlowSelect->Har()] ;
275 double SumOfWeightSqr = fSumOfWeightSqr[pFlowSelect->Sel()][pFlowSelect->Har()] ;
276 if(SumOfWeightSqr) { mQ /= TMath::Sqrt(SumOfWeightSqr) ; }
277 else { mQ.Set(0.,0.) ; }
282 Double_t mQx=0. , mQy=0. ;
283 double SumOfWeightSqr = 0 ;
284 int selN = pFlowSelect->Sel() ;
285 int harN = pFlowSelect->Har() ;
286 double order = (double)(harN + 1) ;
288 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
290 AliFlowTrack* pFlowTrack ;
291 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
292 if (pFlowSelect->Select(pFlowTrack))
294 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
295 SumOfWeightSqr += phiWgt*phiWgt;
297 float phi = pFlowTrack->Phi();
298 mQx += phiWgt * cos(phi * order);
299 mQy += phiWgt * sin(phi * order);
302 if(SumOfWeightSqr) { mQ.Set(mQx/TMath::Sqrt(SumOfWeightSqr), mQy/TMath::Sqrt(SumOfWeightSqr)); }
303 else { mQ.Set(0.,0.); }
307 //-------------------------------------------------------------
308 Float_t AliFlowEvent::q(AliFlowSelection* pFlowSelect)
310 // Magnitude of normalized Q vector (without pt or eta weighting) for the specified Selection
313 Double_t mQx = 0. , mQy = 0. ;
314 int selN = pFlowSelect->Sel() ;
315 int harN = pFlowSelect->Har() ;
316 double order = (double)(harN + 1) ;
317 double SumOfWeightSqr = 0 ;
320 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
322 AliFlowTrack* pFlowTrack ;
323 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
324 if(pFlowSelect->Select(pFlowTrack))
326 double phiWgt = PhiWeightRaw(selN, harN, pFlowTrack); // Raw
327 SumOfWeightSqr += phiWgt*phiWgt;
328 float phi = pFlowTrack->Phi();
329 mQx += phiWgt * cos(phi * order);
330 mQy += phiWgt * sin(phi * order);
333 if(SumOfWeightSqr) { mQ.Set(mQx/TMath::Sqrt(SumOfWeightSqr), mQy/TMath::Sqrt(SumOfWeightSqr)); }
334 else { mQ.Set(0.,0.); }
338 //-----------------------------------------------------------------------
339 Double_t AliFlowEvent::G_New(AliFlowSelection* pFlowSelect, Double_t Zx, Double_t Zy)
341 // Generating function for the new cumulant method. Eq. 3 in the Practical Guide
343 int selN = pFlowSelect->Sel();
344 int harN = pFlowSelect->Har();
345 double order = (double)(harN + 1);
347 double mult = (double)Mult(pFlowSelect);
351 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
353 AliFlowTrack* pFlowTrack ;
354 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
355 if (pFlowSelect->Select(pFlowTrack))
357 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
358 float phi = pFlowTrack->Phi();
359 theG *= (1. + (phiWgt/mult) * (2.* Zx * cos(phi * order) + 2.* Zy * sin(phi * order) ) );
364 //-----------------------------------------------------------------------
365 Double_t AliFlowEvent::G_Old(AliFlowSelection* pFlowSelect, Double_t Zx, Double_t Zy)
367 // Generating function for the old cumulant method (if expanded in Taylor
368 // series, one recovers G_New() in new new cumulant method)
370 TVector2 normQ = NormQ(pFlowSelect);
372 return exp(2*Zx*normQ.X() + 2*Zy*normQ.Y());
374 //-----------------------------------------------------------------------
375 Double_t AliFlowEvent::SumWeightSquare(AliFlowSelection* pFlowSelect)
377 // Return sum of weights^2 for the specified Selection (used for normalization)
381 return fSumOfWeightSqr[pFlowSelect->Sel()][pFlowSelect->Har()] ;
384 int selN = pFlowSelect->Sel();
385 int harN = pFlowSelect->Har();
386 Double_t SumOfWeightSqr = 0;
389 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
391 AliFlowTrack* pFlowTrack ;
392 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
393 if (pFlowSelect->Select(pFlowTrack))
395 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
396 SumOfWeightSqr += phiWgt*phiWgt;
399 if(SumOfWeightSqr < 0.) { return Mult(pFlowSelect) ; }
401 return SumOfWeightSqr;
403 //-------------------------------------------------------------
404 Double_t AliFlowEvent::WgtMult_q4(AliFlowSelection* pFlowSelect)
406 // Used only for the old cumulant method, for getting q4 when weight is on.
407 // Replace multiplicity in Eq.(74b) by this quantity when weight is on.
408 // This is derived based on (A4) in the old cumulant paper.
410 int selN = pFlowSelect->Sel();
411 int harN = pFlowSelect->Har();
413 double theMeanWj4 = 0.;
414 double theMeanWj2 = 0.;
415 double theSumOfWgtSqr = 0;
419 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
421 AliFlowTrack* pFlowTrack ;
422 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
423 if (pFlowSelect->Select(pFlowTrack))
425 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
426 phiWgtSq = phiWgt*phiWgt;
427 theSumOfWgtSqr += phiWgtSq;
428 theMeanWj4 += phiWgtSq*phiWgtSq;
432 if (theMult <= 0.) return theMult;
434 theMeanWj4 /= theMult;
435 theMeanWj2 = theSumOfWgtSqr / theMult;
437 return (theSumOfWgtSqr*theSumOfWgtSqr)/(theMult*(-theMeanWj4+2*theMeanWj2*theMeanWj2));
439 //-------------------------------------------------------------
440 Double_t AliFlowEvent::WgtMult_q6(AliFlowSelection* pFlowSelect)
442 // Used only for the old cumulant method. For getting q6 when weight is on.
443 // Replace multiplicity in Eq.(74c) by this quantity when weight is on.
444 // This is derived based on (A4) in the old cumulant paper.
446 int selN = pFlowSelect->Sel();
447 int harN = pFlowSelect->Har();
449 double theMeanWj6 = 0.;
450 double theMeanWj4 = 0.;
451 double theMeanWj2 = 0.;
452 double theSumOfWgtSqr = 0;
456 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
458 AliFlowTrack* pFlowTrack ;
459 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
460 if (pFlowSelect->Select(pFlowTrack))
462 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
463 phiWgtSq = phiWgt*phiWgt;
464 theSumOfWgtSqr += phiWgtSq;
465 theMeanWj4 += phiWgtSq*phiWgtSq;
466 theMeanWj6 += phiWgtSq*phiWgtSq*phiWgtSq;
470 if (theMult <= 0.) return theMult*theMult;
472 theMeanWj6 /= theMult;
473 theMeanWj4 /= theMult;
474 theMeanWj2 = theSumOfWgtSqr / theMult;
476 return 4.*(theSumOfWgtSqr*theSumOfWgtSqr*theSumOfWgtSqr)/(theMult*(theMeanWj6-9.*theMeanWj2*theMeanWj4+12.*theMeanWj2*theMeanWj2*theMeanWj2));
478 //-------------------------------------------------------------
479 void AliFlowEvent::SetSelections(AliFlowSelection* pFlowSelect)
481 // Sets the selection of tracks used in the Reaction Plane calculation
482 // for the specific Harmonic and Selection - this does not cut trow away
483 // tracks from the event, neither exclude them from flow study. See also
484 // the AliFlowSelection class.
485 // Strategy of Selection:
486 // For the specific Harmonic and Selection, IF cuts
487 // are defined (such that low<high) and IF the track satisfies them, THEN
488 // the respective track's flag (bool AliFlowTrack::mSelection[har][sel])
489 // is set kTRUE so that the track, from now on, will be included in the
490 // R.P. determination for that selection.
491 // If NO cuts are defined -> ALL Flags are setted kTRUE (all particle
492 // used for all the Reaction Planes -> no difference in Psi[har][sel]).
493 // -------------------------------------------------------------------
494 // The first selection (all harmonics) is set kTRUE : no conditions.
497 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
499 AliFlowTrack* pFlowTrack ;
500 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
501 pFlowTrack->ResetSelection() ; // this re-sets all the mSelection flags to 0
503 // * this sets all the selection n.[0] flag kTRUE (all harmonics) *
504 for(int harN=0;harN<Flow::nHars;harN++) { pFlowTrack->SetSelect(harN,0) ; }
506 // Track need to be Constrainable
507 if(pFlowSelect->ConstrainCut() && !pFlowTrack->IsConstrainable()) continue ;
509 // PID - gets rid of the track with AliFlowTrack::Pid() != AliFlowSelection::Pid() (if there)
510 if(pFlowSelect->Pid()[0] != '\0')
512 if(strstr(pFlowSelect->Pid(), "h")!=0)
514 int charge = pFlowTrack->Charge() ;
515 if(strcmp("h+",pFlowSelect->Pid())==0 && charge != 1) continue;
516 if(strcmp("h-",pFlowSelect->Pid())==0 && charge != -1) continue;
521 strcpy(pid, pFlowTrack->Pid());
522 if(strstr(pid, pFlowSelect->Pid())==0) continue;
525 double eta = (double)(pFlowTrack->Eta());
526 float Pt = pFlowTrack->Pt();
527 float gDca = pFlowTrack->Dca() ;
529 // Global DCA - gets rid of the track with DCA outside the range
530 if((pFlowSelect->DcaGlobalCutHi()>pFlowSelect->DcaGlobalCutLo()) && (gDca<pFlowSelect->DcaGlobalCutLo() || gDca>pFlowSelect->DcaGlobalCutHi())) continue ;
532 // Pt & Eta - this is done differently for different Harmonic & Selection
533 for(int selN = 1; selN < Flow::nSels; selN++) // not even consider the 0th selection (no cut applied there)
535 // min. TPC hits required
536 if(pFlowSelect->NhitsCut(selN) && (pFlowTrack->FitPtsTPC()<pFlowSelect->NhitsCut(selN))) continue ;
538 for(int harN = 0; harN < Flow::nHars; harN++)
540 // Eta - gets rid of the track with Eta outside the range
541 if((pFlowSelect->EtaCutHi(harN%2,selN)>pFlowSelect->EtaCutLo(harN%2,selN)) && (TMath::Abs(eta)<pFlowSelect->EtaCutLo(harN%2,selN) || TMath::Abs(eta)>pFlowSelect->EtaCutHi(harN%2,selN))) continue ;
542 // Pt - gets rid of the track with Pt outside the range
543 if((pFlowSelect->PtCutHi(harN%2,selN)>pFlowSelect->PtCutLo(harN%2,selN)) && (Pt<pFlowSelect->PtCutLo(harN%2,selN) || Pt>pFlowSelect->PtCutHi(harN%2,selN))) continue ;
545 pFlowTrack->SetSelect(harN, selN) ; // if cuts defined (low<high) && track is in the range -> Set [har][sel] Flag ON
549 cout << " harN " << harN%2 << " , selN " << selN << " - si" << endl ;
550 if(pFlowSelect->Pid()[0] != '\0') { cout << " track: pid " << pFlowTrack->Pid() << " = "<< pFlowSelect->Pid() << endl ; }
551 cout << " track: dca " << pFlowSelect->DcaGlobalCutLo() << " < " << gDca << " < " << pFlowSelect->DcaGlobalCutHi() << endl ;
552 cout << " track: eta " << pFlowSelect->EtaCutLo(harN,selN) << " < |" << eta << "| < " << pFlowSelect->EtaCutHi(harN,selN) << endl ;
553 cout << " track: pT " << pFlowSelect->PtCutLo(harN,selN) << " < " << Pt << " < " << pFlowSelect->PtCutHi(harN,selN) << endl ;
554 pFlowTrack->PrintSelection() ;
560 //-------------------------------------------------------------
561 void AliFlowEvent::SetPids()
563 // Re-sets the tracks P.id. (using the current Flow::fBayesian[] array)
565 const Int_t code[] = {11,13,211,321,2212,10010020} ;
566 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
568 AliFlowTrack* pFlowTrack ;
569 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
570 TVector bayPid = pFlowTrack->PidProbs() ;
571 Int_t maxN = 2 ; // if No id. -> then is a Pi
572 Float_t pid_max = bayPid[2] ; // (if all equal, Pi probability get's the advantage to be the first)
573 for(Int_t nP=0;nP<Flow::nPid;nP++)
575 if(bayPid[nP]>pid_max) { maxN = nP ; pid_max = bayPid[nP] ; }
577 Int_t pdg_code = TMath::Sign(code[maxN],pFlowTrack->Charge()) ;
578 pFlowTrack->SetMostLikelihoodPID(pdg_code);
581 //-------------------------------------------------------------
582 void AliFlowEvent::MakeSubEvents()
584 // Make random or eta sub-events
586 if(EtaSubs()) { MakeEtaSubEvents() ; }
587 else { MakeRndSubEvents() ; }
589 //-------------------------------------------------------------
590 void AliFlowEvent::MakeRndSubEvents()
592 // Make random subevents
594 int eventMult[Flow::nHars][Flow::nSels] = {{0}};
595 int harN, selN, subN = 0;
597 // loop to count the total number of tracks for each selection
598 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
600 AliFlowTrack* pFlowTrack ;
601 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
602 for (selN = 0; selN < Flow::nSels; selN++)
604 for (harN = 0; harN < Flow::nHars; harN++)
606 if(pFlowTrack->Select(harN, selN)) { eventMult[harN][selN]++ ; }
610 // loop to set the SubEvent member
611 for (selN = 0; selN < Flow::nSels; selN++)
613 for (harN = 0; harN < Flow::nHars; harN++)
615 int subEventMult = eventMult[harN][selN] / Flow::nSubs;
620 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
622 AliFlowTrack* pFlowTrack ;
623 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
624 if(pFlowTrack->Select(harN, selN))
626 pFlowTrack->SetSubevent(harN, selN, subN);
628 if (countN % subEventMult == 0.) { subN++ ; }
636 //-------------------------------------------------------------
637 void AliFlowEvent::MakeEtaSubEvents()
639 // Make subevents for positive and negative eta
640 // (when done, fEtaSubs flag setted to kTRUE).
643 // loop to set the SubEvent member
644 for (selN = 0; selN < Flow::nSels; selN++)
646 for (harN = 0; harN < Flow::nHars; harN++)
648 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
650 AliFlowTrack* pFlowTrack ;
651 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
652 if(pFlowTrack->Select(harN, selN))
654 float eta = pFlowTrack->Eta();
655 if (eta > 0.) { pFlowTrack->SetSubevent(harN, selN, 0) ; }
656 else { pFlowTrack->SetSubevent(harN, selN, 1) ; }
662 //-------------------------------------------------------------
663 void AliFlowEvent::RandomShuffle()
665 // Randomly re-shuffles the tracks in the array; if a track is not
666 // primary, the reference carried by the reconstructed mother (in
667 // the v0 array) is changed accordingly.
670 UInt_t imax = TrackCollection()->GetEntries() ;
671 TRandom* rnd = new TRandom(0) ; // SetSeed(0) ;
672 TObjArray* newTrackCollection = new TObjArray(imax) ;
674 // re-arranges the ObjArray (TrackCollection())
675 for(UInt_t itr=0;itr<imax;itr++)
677 AliFlowTrack* pFlowTrack ;
678 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
680 UInt_t rndNumber = rnd->Integer(imax) ;
681 Bool_t put = kFALSE ;
684 if(!newTrackCollection->At(rndNumber))
686 newTrackCollection->AddAt(pFlowTrack, rndNumber) ;
687 put = kTRUE ; tot++ ; if(Flow::fDebug) { cout << " " << itr << " --> " << rndNumber << endl ; }
691 rndNumber++ ; if(rndNumber>=imax) { rndNumber -= imax ; }
695 if(Flow::fDebug) { cout << "* RandomShuffle() : " << tot << "/" << imax << " flow tracks have been shuffled " << endl ; }
696 fTrackCollection = newTrackCollection ;
698 //-----------------------------------------------------------------------
699 UInt_t AliFlowEvent::Centrality()
701 // Returns the Centrality Class as stored
703 if(fCentrality < 0) { SetCentrality() ; }
706 //-----------------------------------------------------------------------
707 void AliFlowEvent::SetCentrality(Int_t cent)
709 // Set the Centrality Classes to "cent" .
713 //-----------------------------------------------------------------------
714 void AliFlowEvent::SetCentrality()
716 // Sets the Centrality Classes basing on Multiplicity at mid rapidity,
717 // ... (ZDC information can be added) .
720 Int_t tracks = MultEta() ;
724 cent = Flow::fCentNorm ;
725 //if centrality classes are not defined, does it now (with CentNorm & MaxMult)
726 if(cent[Flow::nCents-1] <= 1)
728 for(Int_t ic=0;ic<Flow::nCents;ic++)
730 cent[ic] *= Flow::fMaxMult ;
731 if(Flow::fDebug) { cout << "Centrality[" << ic << "] = " << cent[ic] << " . " << endl ; }
735 else if((RunID() != -1) && (CenterOfMassEnergy() == 5500.))
737 cent = (Float_t*)Flow::fCent0 ;
739 else // other definition of centrality are possible...
741 cent = (Float_t*)Flow::fCent0 ;
743 if (tracks < cent[0]) { fCentrality = 0; }
744 else if (tracks < cent[1]) { fCentrality = 1; }
745 else if (tracks < cent[2]) { fCentrality = 2; }
746 else if (tracks < cent[3]) { fCentrality = 3; }
747 else if (tracks < cent[4]) { fCentrality = 4; }
748 else if (tracks < cent[5]) { fCentrality = 5; }
749 else if (tracks < cent[6]) { fCentrality = 6; }
750 else if (tracks < cent[7]) { fCentrality = 7; }
751 else if (tracks < cent[8]) { fCentrality = 8; }
752 else { fCentrality = 9; }
754 if(Flow::fDebug) { cout << " * Centrality Class : " << fCentrality << " . " << endl ; }
756 //-----------------------------------------------------------------------
757 void AliFlowEvent::Bayesian(Double_t bayes[Flow::nPid])
759 // Returns bayesian array of particles' abundances (from Flow::)
761 for(Int_t i=0;i<Flow::nPid;i++) { bayes[i] = Flow::fBayesian[i] ; }
763 //-----------------------------------------------------------------------
764 TVector AliFlowEvent::Bayesian()
766 TVector bayes(Flow::nPid) ;
767 for(Int_t i=0;i<Flow::nPid;i++) { bayes[i] = Flow::fBayesian[i] ; }
770 //-----------------------------------------------------------------------
771 void AliFlowEvent::PrintFlagList() const
773 // Prints the list of selection cuts ( called in AliFlowInterface::Finish() )
775 cout << "#######################################################" << endl;
776 cout << "# Weighting and Striping:" << endl;
779 cout << "# PtWgt = kTRUE " << endl ; // (also for output of PhiWgt file?)
780 cout << "# PtWgt Saturation = " << Flow::fPtWgtSaturation << endl;
784 cout << "# PtWgt = kFALSE" << endl;
788 cout << "# EtaWgt = kTRUE " << endl ; // (also for output of PhiWgt file for odd harmonics?)
792 cout << "# EtaWgt = kFALSE" << endl;
794 cout << "#######################################################" << endl;
796 //-----------------------------------------------------------------------
797 void AliFlowEvent::SetEventID(const Int_t& id)
799 // Sets Event ID and the Event name (name = evtNumber_runId)
804 if(fRunID) { name += "_" ; name += fRunID ; }
805 SetName(name) ; // from TNamed::SetName
807 //-----------------------------------------------------------------------
808 Int_t AliFlowEvent::MultEta()
810 // Returns the multiplicity in the interval |eta|<(Flow::fEetaMid), used
811 // for centrality measurement (see centrality classes in fCentrality) .
813 Int_t goodtracks = 0 ;
814 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
816 AliFlowTrack* pFlowTrack ;
817 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
818 if((pFlowTrack->Charge()) && (TMath::Abs(pFlowTrack->Eta())<Flow::fEtaMid)) { goodtracks++ ; }
822 //-----------------------------------------------------------------------
823 Int_t AliFlowEvent::UncorrNegMult(Float_t eta) const
825 // Negative multiplicity in the interval (-eta..eta)
826 // (default is Flow::fEetaGood = 0.9)
829 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
831 AliFlowTrack* pFlowTrack ;
832 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
833 if((pFlowTrack->Charge()<0) && (TMath::Abs(pFlowTrack->Eta())<TMath::Abs(eta))) { negMult++ ; }
838 //-----------------------------------------------------------------------
839 Int_t AliFlowEvent::UncorrPosMult(Float_t eta) const
841 // Positive multiplicity in the interval (-eta..eta)
842 // (default is Flow::fEetaGood = 0.9)
845 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
847 AliFlowTrack* pFlowTrack ;
848 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
849 if((pFlowTrack->Charge()>0) && (TMath::Abs(pFlowTrack->Eta())<TMath::Abs(eta))) { posMult++ ; }
854 //-----------------------------------------------------------------------
855 void AliFlowEvent::VertexPos(Float_t vtx[3]) const
857 for(Int_t ii=0;ii<3;ii++) { vtx[ii] = fVertexPos[ii] ; }
859 //-----------------------------------------------------------------------
860 TVector3 AliFlowEvent::VertexPos() const
864 return TVector3(vertex) ;
866 //-----------------------------------------------------------------------
867 void AliFlowEvent::SetVertexPos(Float_t v1,Float_t v2,Float_t v3)
869 fVertexPos[0] = v1 ; fVertexPos[1] = v2 ; fVertexPos[2] = v3 ;
871 //-----------------------------------------------------------------------
872 void AliFlowEvent::MakeAll()
874 // calculates all quantities in 1 shoot ...
877 Double_t mQx[Flow::nSels][Flow::nHars] ;
878 Double_t mQy[Flow::nSels][Flow::nHars] ;
879 Double_t mQxSub[Flow::nSubs][Flow::nSels][Flow::nHars] ;
880 Double_t mQySub[Flow::nSubs][Flow::nSels][Flow::nHars] ;
882 int selN, harN, subN ;
883 for(selN=0;selN<Flow::nSels;selN++)
885 for(harN=0;harN<Flow::nHars;harN++)
887 mQx[selN][harN] = 0. ;
888 mQy[selN][harN] = 0. ;
889 fMult[selN][harN] = 0 ;
890 fSumOfWeightSqr[selN][harN] = 0. ;
891 for(subN=0;subN<Flow::nSubs;subN++)
893 mQxSub[subN][selN][harN] = 0. ;
894 mQySub[subN][selN][harN] = 0. ;
895 fMultSub[subN][selN][harN] = 0 ;
905 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
907 AliFlowTrack* pFlowTrack ;
908 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
909 phi = pFlowTrack->Phi();
910 for(selN=0;selN<Flow::nSels;selN++)
912 for(harN=0;harN<Flow::nHars;harN++)
914 order = (double)(harN+1) ;
915 if(pFlowTrack->Select(harN,selN))
917 phiWgt = PhiWeight(selN,harN,pFlowTrack) ;
918 fSumOfWeightSqr[selN][harN] += phiWgt*phiWgt ;
919 mQx[selN][harN] += phiWgt * cos(phi * order) ;
920 mQy[selN][harN] += phiWgt * sin(phi * order) ;
921 fMult[selN][harN]++ ;
922 for(subN=0;subN<Flow::nSubs;subN++)
924 if(pFlowTrack->Select(harN,selN,subN))
926 mQxSub[subN][selN][harN] += phiWgt * cos(phi * order) ;
927 mQySub[subN][selN][harN] += phiWgt * sin(phi * order) ;
928 fMultSub[subN][selN][harN]++ ;
936 for(selN=0;selN<Flow::nSels;selN++)
938 for(harN=0;harN<Flow::nHars;harN++)
940 fQ[selN][harN].Set(mQx[selN][harN],mQy[selN][harN]) ;
941 for(subN=0;subN<Flow::nSubs;subN++) { fQSub[subN][selN][harN].Set(mQxSub[subN][selN][harN],mQySub[subN][selN][harN]) ; }
947 // //-----------------------------------------------------------------------
948 // Float_t AliFlowEvent::ExtPsi(Int_t harN) const
950 // // external R.P. angle (check input source...)
952 // if(harN<Flow::nHars) { return fExtPsi[harN] ; }
955 // cout << "AliFlowEvent::ExtPsi(" << harN << ") : harmonic " << harN+1 << " is not there !" << endl ;
959 // //-----------------------------------------------------------------------
960 // Float_t AliFlowEvent::ExtRes(Int_t harN) const
962 // // external R.P. resolution (check input source...)
964 // if(harN<Flow::nHars) { return fExtRes[harN] ; }
967 // cout << "AliFlowEvent::ExtRes(" << harN << ") : harmonic " << harN+1 << " is not there !" << endl ;
971 // //-----------------------------------------------------------------------
972 // void AliFlowEvent::SetExtPsi(Int_t harN,Float_t psi)
974 // if(harN<Flow::nHars) { fExtPsi[harN] = psi ; }
976 // //-----------------------------------------------------------------------
977 // void AliFlowEvent::SetExtRes(Int_t harN,Float_t res)
979 // if(harN<Flow::nHars) { fExtRes[harN] = res ; }
981 // //-----------------------------------------------------------------------
985 //-----------------------------------------------------------------------
986 // - those will go into the .h as inline functions .....................
987 //-----------------------------------------------------------------------
988 TObjArray* AliFlowEvent::TrackCollection() const { return fTrackCollection; }
989 TObjArray* AliFlowEvent::V0Collection() const { return fV0Collection; }
990 //-----------------------------------------------------------------------
991 Int_t AliFlowEvent::EventID() const { return fEventID; }
992 Int_t AliFlowEvent::RunID() const { return fRunID; }
993 Double_t AliFlowEvent::CenterOfMassEnergy() const { return Flow::fCenterOfMassEnergy ; }
994 Double_t AliFlowEvent::MagneticField() const { return Flow::fMagneticField ; }
995 Short_t AliFlowEvent::BeamMassNumberEast() const { return Flow::fBeamMassNumberEast ; }
996 Short_t AliFlowEvent::BeamMassNumberWest() const { return Flow::fBeamMassNumberWest ; }
997 UInt_t AliFlowEvent::OrigMult() const { return fOrigMult; }
998 Long_t AliFlowEvent::L0TriggerWord() const { return fL0TriggerWord; }
999 Int_t AliFlowEvent::V0Mult() const { return V0Collection()->GetEntries() ; }
1000 Int_t AliFlowEvent::FlowEventMult() const { return TrackCollection()->GetEntries() ; }
1001 Int_t AliFlowEvent::ZDCpart() const { return fZDCpart; }
1002 Float_t AliFlowEvent::ZDCenergy(Int_t npem) const { return fZDCenergy[npem]; }
1003 Float_t AliFlowEvent::PtWgtSaturation() const { return Flow::fPtWgtSaturation; }
1004 Bool_t AliFlowEvent::PtWgt() const { return fPtWgt; }
1005 Bool_t AliFlowEvent::EtaWgt() const { return fEtaWgt; }
1006 Bool_t AliFlowEvent::FirstLastPhiWgt() const { return !fOnePhiWgt ; }
1007 Bool_t AliFlowEvent::OnePhiWgt() const { return fOnePhiWgt ; }
1008 Bool_t AliFlowEvent::NoWgt() const { return fNoWgt; }
1009 Bool_t AliFlowEvent::EtaSubs() const { return fEtaSubs ; }
1010 //-----------------------------------------------------------------------
1011 void AliFlowEvent::SetEtaSubs(Bool_t etasub) { fEtaSubs = etasub ; }
1012 void AliFlowEvent::SetRunID(const Int_t& id) { fRunID = id; }
1013 void AliFlowEvent::SetMagneticField(const Double_t& mf) { Flow::fMagneticField = mf; }
1014 void AliFlowEvent::SetCenterOfMassEnergy(const Double_t& cms) { Flow::fCenterOfMassEnergy = cms; }
1015 void AliFlowEvent::SetBeamMassNumberEast(const Short_t& bme) { Flow::fBeamMassNumberEast = bme; }
1016 void AliFlowEvent::SetBeamMassNumberWest(const Short_t& bmw) { Flow::fBeamMassNumberWest = bmw; }
1017 void AliFlowEvent::SetOrigMult(const UInt_t& tracks) { fOrigMult = tracks; }
1018 void AliFlowEvent::SetL0TriggerWord(const Long_t& trigger) { fL0TriggerWord = trigger; }
1019 void AliFlowEvent::SetZDCpart(Int_t zdcp) { fZDCpart = zdcp ; }
1020 void AliFlowEvent::SetZDCenergy(Float_t n, Float_t p, Float_t em) { fZDCenergy[0] = n ; fZDCenergy[1] = p ; fZDCenergy[2] = em ; }
1021 //-----------------------------------------------------------------------
1022 void AliFlowEvent::SetBayesian(Double_t bayes[Flow::nPid])
1024 for(Int_t i=0;i<Flow::nPid;i++) { Flow::fBayesian[i] = bayes[i] ; }
1026 //-----------------------------------------------------------------------
1027 void AliFlowEvent::SetNoWgt(Bool_t nowgt)
1029 // Sets no phi weightening, but Wgt = 1*sign(Eta) for odd harmonics .
1031 fNoWgt = nowgt ; // cout << " Wgt = +1 (positive Eta) or -1 (negative Eta) . " << endl ;
1033 //-----------------------------------------------------------------------
1034 void AliFlowEvent::SetOnePhiWgt() { fOnePhiWgt = kTRUE ; }
1035 void AliFlowEvent::SetFirstLastPhiWgt() { fOnePhiWgt = kFALSE ; }
1036 void AliFlowEvent::SetPtWgt(Bool_t PtWgt) { fPtWgt = PtWgt; }
1037 void AliFlowEvent::SetEtaWgt(Bool_t EtaWgt) { fEtaWgt = EtaWgt; }
1038 //-----------------------------------------------------------------------
1040 void AliFlowEvent::SetPhiWeight(const Flow::PhiWgt_t& pPhiWgt) { memcpy (fPhiWgt, pPhiWgt, sizeof(Flow::PhiWgt_t)); }
1041 void AliFlowEvent::SetPhiWeightPlus(const Flow::PhiWgt_t& pPhiWgtPlus) { memcpy (fPhiWgtPlus, pPhiWgtPlus, sizeof(Flow::PhiWgt_t)); }
1042 void AliFlowEvent::SetPhiWeightMinus(const Flow::PhiWgt_t& pPhiWgtMinus) { memcpy (fPhiWgtMinus, pPhiWgtMinus, sizeof(Flow::PhiWgt_t)); }
1043 void AliFlowEvent::SetPhiWeightCross(const Flow::PhiWgt_t& pPhiWgtCross) { memcpy (fPhiWgtCross, pPhiWgtCross, sizeof(Flow::PhiWgt_t)); }
1045 //-----------------------------------------------------------------------
1046 //////////////////////////////////////////////////////////////////////