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 "AliFlowTrack.h"
40 #include "AliFlowV0.h"
41 #include "AliFlowSelection.h"
42 #include "AliFlowConstants.h"
47 #include "TClonesArray.h"
52 using namespace std; //required for resolving the 'cout' symbol
55 Bool_t AliFlowEvent::fgPtWgt = kFALSE ; // gives pT-based weights
56 Bool_t AliFlowEvent::fgEtaWgt = kFALSE ; // gives eta-based weights
57 Bool_t AliFlowEvent::fgOnePhiWgt = kTRUE ; // kTRUE --> ENABLEs SINGLE WEIGHT ISTOGRAM , kFALSE --> ENABLEs 3 WEIGHT ISTOGRAMS
58 Bool_t AliFlowEvent::fgNoWgt = kFALSE ; // No Weight is used
59 // - Eta Sub-Events (later used to calculate the resolution)
60 Bool_t AliFlowEvent::fgEtaSubs = kFALSE ; // makes eta subevents
61 Bool_t AliFlowEvent::fgCustomRespFunc = kFALSE ; // custom "detector response function" is used for P.Id (see AliFlowTrack)
63 ClassImp(AliFlowEvent)
64 //-----------------------------------------------------------
65 AliFlowEvent::AliFlowEvent(Int_t lenght):
72 fTrackCollection(0x0),
76 // Default constructor: initializes the ObjArray of FlowTracks and FlowV0s,
77 // cleans the internal variables, sets all the weights to 1, sets default flags.
79 for(int zz=0;zz<3;zz++) { fZDCenergy[zz] = 0. ; }
80 for(int i=0;i<AliFlowConstants::kHars;i++) { fExtPsi[i] = 0. ; fExtRes[i] = 0.; }
82 // Make a new track collection
83 fTrackCollection = new TClonesArray("AliFlowTrack",lenght) ; fTrackCollection->BypassStreamer(kTRUE) ;
84 fV0Collection = new TClonesArray("AliFlowV0",lenght) ; fV0Collection->BypassStreamer(kTRUE) ;
86 // Set Weights Arrays to 1 (default)
87 for(int nS=0;nS<AliFlowConstants::kSels;nS++)
89 for(int nH=0;nH<AliFlowConstants::kHars;nH++)
91 for(int nP=0;nP<AliFlowConstants::kPhiBins;nP++)
93 // enable this with: SetOnePhiWgt()
94 fPhiWgt[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgt[nS][nH][nP] << endl ;
95 // enable these with: SetFirstLastPhiWgt()
96 fPhiWgtPlus[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgtPlus[nS][nH][nP] << endl ;
97 fPhiWgtMinus[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgtMinus[nS][nH][nP] << endl ;
98 fPhiWgtCross[nS][nH][nP] = 1. ; // cout << nS << nH << nP << " val " << fPhiWgtCross[nS][nH][nP] << endl ;
102 //for(int nH=0;nH<AliFlowConstants::kHars;nH++) { fExtPsi[nH] = 0. ; fExtRes[nH] = 0. ; }
104 // The Expected particles abundance is taken directly from AliFlowConstants::fgBayesian[] (see Bayesian P.Id.)
107 //-----------------------------------------------------------
108 AliFlowEvent::~AliFlowEvent()
110 // Default distructor: deletes the ObjArrays.
112 fTrackCollection->Delete() ; delete fTrackCollection ;
113 fV0Collection->Delete() ; delete fV0Collection ;
115 //-------------------------------------------------------------
117 //-------------------------------------------------------------
118 Double_t AliFlowEvent::PhiWeightRaw(Int_t selN, Int_t harN, AliFlowTrack* pFlowTrack) const
120 // Weight for making the event plane isotropic in the lab.
122 float phi = pFlowTrack->Phi() ; if(phi < 0.) { phi += 2*TMath::Pi() ; }
123 Double_t eta = (Double_t)pFlowTrack->Eta() ;
124 int n = (int)((phi/(2*TMath::Pi()))*AliFlowConstants::kPhiBins);
126 Double_t phiWgt = 1. ;
129 phiWgt = (Double_t)fPhiWgt[selN][harN][n]; //cout << "Selection " << selN << " ; Harmonic " << harN << " ; PhiBin " << n << " - Wgt = " << phiWgt << endl ;
131 else if(FirstLastPhiWgt())
133 float zFirstPoint = pFlowTrack->ZFirstPoint(); // float zLastPoint = pFlowTrack->ZLastPoint();
135 if (zFirstPoint > 0. && eta > 0.) { phiWgt = (Double_t)fPhiWgtPlus[selN][harN][n] ; }
136 else if(zFirstPoint < 0. && eta < 0.) { phiWgt = (Double_t)fPhiWgtMinus[selN][harN][n] ; }
137 else { phiWgt = (Double_t)fPhiWgtCross[selN][harN][n] ; }
142 //-------------------------------------------------------------
143 Double_t AliFlowEvent::Weight(Int_t selN, Int_t harN, AliFlowTrack* pFlowTrack) const
145 // Weight for enhancing the resolution (eta gives sign +/- for Odd Harmonics)
147 if(selN>AliFlowConstants::kSels) { selN = 0 ; }
148 bool oddHar = (harN+1) % 2 ;
149 Double_t phiWgt = 1. ;
152 Double_t pt = (Double_t)pFlowTrack->Pt();
153 if(pt < AliFlowConstants::fgPtWgtSaturation) { phiWgt *= pt ; }
154 else { phiWgt *= AliFlowConstants::fgPtWgtSaturation ; } // pt weighting going constant
156 Double_t eta = (Double_t)pFlowTrack->Eta();
157 Double_t etaAbs = TMath::Abs(eta);
158 if(EtaWgt() && oddHar) { phiWgt *= etaAbs ; }
159 if(oddHar && eta < 0.) { phiWgt *= -1. ; }
163 //-------------------------------------------------------------
164 Double_t AliFlowEvent::PhiWeight(Int_t selN, Int_t harN, AliFlowTrack* pFlowTrack) const
166 // Weight for making the event plane isotropic in the lab and enhancing the resolution
167 // (it simply rerurns PhiWeightRaw() * Weight()). If fgNoWgt = kTRUE, returns +/-1 ,
168 // basing on Sign(eta), for odd harmonics .
170 if(fgNoWgt) // no weights (but +/- according to eta)
172 bool oddHar = (harN+1) % 2 ;
173 if(oddHar) { return TMath::Sign((Double_t)1.,(Double_t)pFlowTrack->Eta()) ; }
174 else { return (Double_t)1. ; }
176 Double_t phiWgtRaw = PhiWeightRaw(selN, harN, pFlowTrack);
177 Double_t weight = Weight(selN, harN, pFlowTrack);
178 if(AliFlowConstants::fgDebug) { cout << "[PhiWeight]: phiWgtRaw = " << phiWgtRaw << " , weight = " << weight << " , eta = " << pFlowTrack->Eta() << endl ; }
180 return phiWgtRaw * weight;
182 //-------------------------------------------------------------
183 Int_t AliFlowEvent::Mult(AliFlowSelection* pFlowSelect) const
185 // Multiplicity of tracks in the specified Selection
189 int sub = pFlowSelect->Sub() ;
190 if(sub<0) { return fMult[pFlowSelect->Sel()][pFlowSelect->Har()] ; }
191 else { return fMultSub[sub][pFlowSelect->Sel()][pFlowSelect->Har()] ; }
196 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
198 AliFlowTrack* pFlowTrack ;
199 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
200 if(pFlowSelect->Select(pFlowTrack)) { mult++ ; }
204 //-------------------------------------------------------------
205 Float_t AliFlowEvent::MeanPt(AliFlowSelection* pFlowSelect) const
207 // Mean pt of tracks in the specified Selection
209 Double_t meanPt = 0. ;
213 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
215 AliFlowTrack* pFlowTrack ;
216 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
217 if (pFlowSelect->Select(pFlowTrack))
219 sumPt += pFlowTrack->Pt();
223 if(mult) { meanPt = sumPt/(float)mult ; }
227 //-------------------------------------------------------------
228 TVector2 AliFlowEvent::Q(AliFlowSelection* pFlowSelect) const
230 // Event plane vector for the specified Selection
234 int sub = pFlowSelect->Sub() ;
235 if(sub<0) { return fQ[pFlowSelect->Sel()][pFlowSelect->Har()] ; }
236 else { return fQSub[sub][pFlowSelect->Sel()][pFlowSelect->Har()] ; }
240 Double_t mQx=0. , mQy=0. ;
241 int selN = pFlowSelect->Sel() ;
242 int harN = pFlowSelect->Har() ;
243 double order = (double)(harN + 1) ;
246 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
248 AliFlowTrack* pFlowTrack ;
249 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
250 if(pFlowSelect->Select(pFlowTrack))
252 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
253 float phi = pFlowTrack->Phi();
254 mQx += phiWgt * cos(phi * order) ;
255 mQy += phiWgt * sin(phi * order) ;
256 if(AliFlowConstants::fgDebug) { cout << itr << " phi = " << phi << " , wgt = " << phiWgt << endl ; }
263 //-------------------------------------------------------------
264 Float_t AliFlowEvent::Psi(AliFlowSelection* pFlowSelect) const
266 // Event plane angle for the specified Selection
268 int harN = pFlowSelect->Har() ;
269 float order = (float)(harN + 1) ;
272 TVector2 mQ = Q(pFlowSelect);
273 if(mQ.Mod()) // if vector is not 0
275 psi= mQ.Phi() / order ;
276 if (psi < 0.) { psi += 2*TMath::Pi() / order ; }
280 //-------------------------------------------------------------
281 TVector2 AliFlowEvent::NormQ(AliFlowSelection* pFlowSelect) const
283 // Normalized Q = Q/sqrt(sum of weights^2) for the specified Selection
287 TVector2 mQ = fQ[pFlowSelect->Sel()][pFlowSelect->Har()] ;
288 double sumOfWeightSqr = fSumOfWeightSqr[pFlowSelect->Sel()][pFlowSelect->Har()] ;
289 if(sumOfWeightSqr) { mQ /= TMath::Sqrt(sumOfWeightSqr) ; }
290 else { mQ.Set(0.,0.) ; }
295 Double_t mQx=0. , mQy=0. ;
296 double sumOfWeightSqr = 0 ;
297 int selN = pFlowSelect->Sel() ;
298 int harN = pFlowSelect->Har() ;
299 double order = (double)(harN + 1) ;
301 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
303 AliFlowTrack* pFlowTrack ;
304 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
305 if (pFlowSelect->Select(pFlowTrack))
307 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
308 sumOfWeightSqr += phiWgt*phiWgt;
310 float phi = pFlowTrack->Phi();
311 mQx += phiWgt * cos(phi * order);
312 mQy += phiWgt * sin(phi * order);
315 if(sumOfWeightSqr) { mQ.Set(mQx/TMath::Sqrt(sumOfWeightSqr), mQy/TMath::Sqrt(sumOfWeightSqr)); }
316 else { mQ.Set(0.,0.); }
320 //-------------------------------------------------------------
321 Float_t AliFlowEvent::OldQ(AliFlowSelection* pFlowSelect) const
323 // Magnitude of normalized Q vector (without pt or eta weighting) for the specified Selection
326 Double_t mQx = 0. , mQy = 0. ;
327 int selN = pFlowSelect->Sel() ;
328 int harN = pFlowSelect->Har() ;
329 double order = (double)(harN + 1) ;
330 double sumOfWeightSqr = 0 ;
333 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
335 AliFlowTrack* pFlowTrack ;
336 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
337 if(pFlowSelect->Select(pFlowTrack))
339 double phiWgt = PhiWeightRaw(selN, harN, pFlowTrack); // Raw
340 sumOfWeightSqr += phiWgt*phiWgt;
341 float phi = pFlowTrack->Phi();
342 mQx += phiWgt * cos(phi * order);
343 mQy += phiWgt * sin(phi * order);
346 if(sumOfWeightSqr) { mQ.Set(mQx/TMath::Sqrt(sumOfWeightSqr), mQy/TMath::Sqrt(sumOfWeightSqr)); }
347 else { mQ.Set(0.,0.); }
351 //-----------------------------------------------------------------------
352 Double_t AliFlowEvent::NewG(AliFlowSelection* pFlowSelect, Double_t Zx, Double_t Zy) const
354 // Generating function for the new cumulant method. Eq. 3 in the Practical Guide
356 int selN = pFlowSelect->Sel();
357 int harN = pFlowSelect->Har();
358 double order = (double)(harN + 1);
360 double mult = (double)Mult(pFlowSelect);
364 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
366 AliFlowTrack* pFlowTrack ;
367 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
368 if (pFlowSelect->Select(pFlowTrack))
370 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
371 float phi = pFlowTrack->Phi();
372 theG *= (1. + (phiWgt/mult) * (2.* Zx * cos(phi * order) + 2.* Zy * sin(phi * order) ) );
377 //-----------------------------------------------------------------------
378 Double_t AliFlowEvent::OldG(AliFlowSelection* pFlowSelect, Double_t Zx, Double_t Zy) const
380 // Generating function for the old cumulant method (if expanded in Taylor
381 // series, one recovers NewG() in new new cumulant method)
383 TVector2 normQ = NormQ(pFlowSelect) ;
385 return exp(2*Zx*normQ.X() + 2*Zy*normQ.Y());
387 //-----------------------------------------------------------------------
388 Double_t AliFlowEvent::SumWeightSquare(AliFlowSelection* pFlowSelect) const
390 // Return sum of weights^2 for the specified Selection (used for normalization)
392 if(fDone) { return fSumOfWeightSqr[pFlowSelect->Sel()][pFlowSelect->Har()] ; }
394 int selN = pFlowSelect->Sel();
395 int harN = pFlowSelect->Har();
396 Double_t sumOfWeightSqr = 0;
398 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
400 AliFlowTrack* pFlowTrack ;
401 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
402 if (pFlowSelect->Select(pFlowTrack))
404 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
405 sumOfWeightSqr += phiWgt*phiWgt;
408 if(sumOfWeightSqr < 0.) { return Mult(pFlowSelect) ; }
410 return sumOfWeightSqr;
412 //-------------------------------------------------------------
413 Double_t AliFlowEvent::WgtMultQ4(AliFlowSelection* pFlowSelect) const
415 // Used only for the old cumulant method, for getting q4 when weight is on.
416 // Replace multiplicity in Eq.(74b) by this quantity when weight is on.
417 // This is derived based on (A4) in the old cumulant paper.
419 int selN = pFlowSelect->Sel();
420 int harN = pFlowSelect->Har();
422 double theMeanWj4 = 0.;
423 double theMeanWj2 = 0.;
424 double theSumOfWgtSqr = 0;
428 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
430 AliFlowTrack* pFlowTrack ;
431 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
432 if (pFlowSelect->Select(pFlowTrack))
434 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
435 phiWgtSq = phiWgt*phiWgt;
436 theSumOfWgtSqr += phiWgtSq;
437 theMeanWj4 += phiWgtSq*phiWgtSq;
441 if (theMult <= 0.) return theMult;
443 theMeanWj4 /= theMult;
444 theMeanWj2 = theSumOfWgtSqr / theMult;
446 return (theSumOfWgtSqr*theSumOfWgtSqr)/(theMult*(-theMeanWj4+2*theMeanWj2*theMeanWj2));
448 //-------------------------------------------------------------
449 Double_t AliFlowEvent::WgtMultQ6(AliFlowSelection* pFlowSelect) const
451 // Used only for the old cumulant method. For getting q6 when weight is on.
452 // Replace multiplicity in Eq.(74c) by this quantity when weight is on.
453 // This is derived based on (A4) in the old cumulant paper.
455 int selN = pFlowSelect->Sel();
456 int harN = pFlowSelect->Har();
458 double theMeanWj6 = 0.;
459 double theMeanWj4 = 0.;
460 double theMeanWj2 = 0.;
461 double theSumOfWgtSqr = 0;
465 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
467 AliFlowTrack* pFlowTrack ;
468 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
469 if (pFlowSelect->Select(pFlowTrack))
471 double phiWgt = PhiWeight(selN, harN, pFlowTrack);
472 phiWgtSq = phiWgt*phiWgt;
473 theSumOfWgtSqr += phiWgtSq;
474 theMeanWj4 += phiWgtSq*phiWgtSq;
475 theMeanWj6 += phiWgtSq*phiWgtSq*phiWgtSq;
479 if (theMult <= 0.) return theMult*theMult;
481 theMeanWj6 /= theMult;
482 theMeanWj4 /= theMult;
483 theMeanWj2 = theSumOfWgtSqr / theMult;
485 return 4.*(theSumOfWgtSqr*theSumOfWgtSqr*theSumOfWgtSqr)/(theMult*(theMeanWj6-9.*theMeanWj2*theMeanWj4+12.*theMeanWj2*theMeanWj2*theMeanWj2));
487 //-------------------------------------------------------------
488 void AliFlowEvent::SetSelections(AliFlowSelection* pFlowSelect)
490 // Sets the selection of tracks used in the Reaction Plane calculation
491 // for the specific Harmonic and Selection - this does not cut trow away
492 // tracks from the event, neither exclude them from flow study. See also
493 // the AliFlowSelection class.
494 // Strategy of Selection:
495 // For the specific Harmonic and Selection, IF cuts
496 // are defined (such that low<high) and IF the track satisfies them, THEN
497 // the respective track's flag (bool AliFlowTrack::mSelection[har][sel])
498 // is set kTRUE so that the track, from now on, will be included in the
499 // R.P. determination for that selection.
500 // If NO cuts are defined -> ALL Flags are setted kTRUE (all particle
501 // used for all the Reaction Planes -> no difference in Psi[har][sel]).
502 // -------------------------------------------------------------------
503 // The first selection (all harmonics) is set kTRUE : no conditions.
506 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
508 AliFlowTrack* pFlowTrack ;
509 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
510 pFlowTrack->ResetSelection() ; // this re-sets all the mSelection flags to 0
512 // * this sets all the selection n.[0] flag kTRUE (all harmonics) *
513 for(int harN=0;harN<AliFlowConstants::kHars;harN++) { pFlowTrack->SetSelect(harN,0) ; }
515 // Track need to be Constrainable
516 if(pFlowSelect->ConstrainCut() && !pFlowTrack->IsConstrainable()) continue ;
518 // PID - gets rid of the track with AliFlowTrack::Pid() != AliFlowSelection::Pid() (if there)
519 if(pFlowSelect->Pid()[0] != '\0')
521 if(strstr(pFlowSelect->Pid(), "h")!=0)
523 int charge = pFlowTrack->Charge() ;
524 if(strcmp("h+",pFlowSelect->Pid())==0 && charge != 1) continue;
525 if(strcmp("h-",pFlowSelect->Pid())==0 && charge != -1) continue;
530 strcpy(pid, pFlowTrack->Pid());
531 if(strstr(pid, pFlowSelect->Pid())==0) continue;
534 double eta = (double)(pFlowTrack->Eta());
535 float pt = pFlowTrack->Pt();
536 float gDca = pFlowTrack->Dca() ;
538 // Global DCA - gets rid of the track with DCA outside the range
539 if((pFlowSelect->DcaGlobalCutHi()>pFlowSelect->DcaGlobalCutLo()) && (gDca<pFlowSelect->DcaGlobalCutLo() || gDca>pFlowSelect->DcaGlobalCutHi())) continue ;
541 // Pt & Eta - this is done differently for different Harmonic & Selection
542 for(int selN = 1; selN < AliFlowConstants::kSels; selN++) // not even consider the 0th selection (no cut applied there)
544 // min. TPC hits required
545 if(pFlowSelect->NhitsCut(selN) && (pFlowTrack->FitPtsTPC()<pFlowSelect->NhitsCut(selN))) continue ;
547 for(int harN = 0; harN < AliFlowConstants::kHars; harN++)
549 // Eta - gets rid of the track with Eta outside the range
550 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 ;
551 // Pt - gets rid of the track with Pt outside the range
552 if((pFlowSelect->PtCutHi(harN%2,selN)>pFlowSelect->PtCutLo(harN%2,selN)) && (pt<pFlowSelect->PtCutLo(harN%2,selN) || pt>pFlowSelect->PtCutHi(harN%2,selN))) continue ;
554 pFlowTrack->SetSelect(harN, selN) ; // if cuts defined (low<high) && track is in the range -> Set [har][sel] Flag ON
556 if(AliFlowConstants::fgDebug)
560 cout << " n. " << itr << " , pFlowTrack->PrintSelection() = " ; pFlowTrack->PrintSelection() ;
561 if(pFlowSelect->Pid()[0] != '\0') { cout << " track: pid " << pFlowTrack->Pid() << " = "<< pFlowSelect->Pid() << endl ; }
562 cout << " track: dca " << pFlowSelect->DcaGlobalCutLo() << " < " << gDca << " < " << pFlowSelect->DcaGlobalCutHi() << endl ;
563 cout << " track: eta " << pFlowSelect->EtaCutLo(harN,selN) << " < |" << eta << "| < " << pFlowSelect->EtaCutHi(harN,selN) << endl ;
564 cout << " track: pT " << pFlowSelect->PtCutLo(harN,selN) << " < " << pt << " < " << pFlowSelect->PtCutHi(harN,selN) << endl ;
565 cout << " pFlowTrack->PrintSelection() = " ; pFlowTrack->PrintSelection() ;
567 // cout << " selN " << selN << " , harN " << harN%2 << " - si" << endl ;
573 //-------------------------------------------------------------
574 void AliFlowEvent::SetPids()
576 // Re-sets the tracks P.id. (using the current AliFlowConstants::fgBayesian[] array).
577 // To use the Raw P.Id (just the detector response function), set fgBayesian[] = {1,1,1,1,1,1}.
579 const Int_t kCode[] = {11,13,211,321,2212,10010020} ;
580 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
582 AliFlowTrack* pFlowTrack ;
583 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
585 Float_t bayPid[AliFlowConstants::kPid] ;
586 if(fgCustomRespFunc) { pFlowTrack->PidProbsC(bayPid) ; }
587 else { pFlowTrack->PidProbs(bayPid) ; }
589 Int_t maxN = 2 ; // if No id. -> then is a Pi
590 Float_t pidMax = bayPid[2] ; // (if all equal, Pi probability was the first)
591 for(Int_t nP=0;nP<AliFlowConstants::kPid;nP++)
593 if(bayPid[nP]>pidMax) { maxN = nP ; pidMax = bayPid[nP] ; }
595 Int_t pdgCode = TMath::Sign(kCode[maxN],pFlowTrack->Charge()) ;
596 pFlowTrack->SetMostLikelihoodPID(pdgCode) ;
599 //-------------------------------------------------------------
600 void AliFlowEvent::MakeSubEvents() const
602 // Make random or eta sub-events
604 if(fgEtaSubs) { MakeEtaSubEvents() ; }
605 else { MakeRndSubEvents() ; }
607 //-------------------------------------------------------------
608 void AliFlowEvent::MakeRndSubEvents() const
610 // Make random subevents
612 int eventMult[AliFlowConstants::kHars][AliFlowConstants::kSels] = {{0}};
613 int harN, selN, subN = 0;
615 // loop to count the total number of tracks for each selection
616 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
618 AliFlowTrack* pFlowTrack ;
619 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
620 for (selN = 0; selN < AliFlowConstants::kSels; selN++)
622 for (harN = 0; harN < AliFlowConstants::kHars; harN++)
624 if(pFlowTrack->Select(harN, selN)) { eventMult[harN][selN]++ ; }
628 // loop to set the SubEvent member
629 for (selN = 0; selN < AliFlowConstants::kSels; selN++)
631 for (harN = 0; harN < AliFlowConstants::kHars; harN++)
633 int subEventMult = eventMult[harN][selN] / AliFlowConstants::kSubs;
638 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
640 AliFlowTrack* pFlowTrack ;
641 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
642 if(pFlowTrack->Select(harN, selN))
644 pFlowTrack->SetSubevent(harN, selN, subN);
646 if (countN % subEventMult == 0.) { subN++ ; }
654 //-------------------------------------------------------------
655 void AliFlowEvent::MakeEtaSubEvents() const
657 // Make subevents for positive and negative eta
658 // (when done, fgEtaSubs flag setted to kTRUE).
661 // loop to set the SubEvent member
662 for (selN = 0; selN < AliFlowConstants::kSels; selN++)
664 for (harN = 0; harN < AliFlowConstants::kHars; harN++)
666 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
668 AliFlowTrack* pFlowTrack ;
669 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
670 if(pFlowTrack->Select(harN, selN))
672 float eta = pFlowTrack->Eta();
673 if (eta > 0.) { pFlowTrack->SetSubevent(harN, selN, 0) ; }
674 else { pFlowTrack->SetSubevent(harN, selN, 1) ; }
680 //-------------------------------------------------------------
681 void AliFlowEvent::RandomShuffle()
683 // Randomly re-shuffles the tracks in the array; if a track is not
684 // primary, the reference carried by the reconstructed mother (in
685 // the v0 array) is changed accordingly.
687 return ; // ...at the moment is disabled ... //
690 // UInt_t imax = fTrackCollection->GetEntries() ;
691 // TRandom* rnd = new TRandom(0) ; // SetSeed(0) ;
692 // TClonesArray* newTrackCollection = new TClonesArray("AliFlowTrack",imax) ;
694 // // re-arranges the ObjArray (TrackCollection())
695 // for(UInt_t itr=0;itr<imax;itr++)
697 // AliFlowTrack* pFlowTrack ;
698 // pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
700 // UInt_t rndNumber = rnd->Integer(imax) ;
701 // Bool_t put = kFALSE ;
704 // if(!newTrackCollection->AddrAt(rndNumber))
706 // ... new(newTrackCollection[rndNumber]) AliFlowTrack(*pFlowTrack) ;
707 // put = kTRUE ; tot++ ;
708 // if(AliFlowConstants::fgDebug) { cout << " " << itr << " --> " << rndNumber << endl ; }
712 // rndNumber++ ; if(rndNumber>=imax) { rndNumber -= imax ; }
716 // if(AliFlowConstants::fgDebug) { cout << "* RandomShuffle() : " << tot << "/" << imax << " flow tracks have been shuffled " << endl ; }
717 // fTrackCollection = newTrackCollection ;
719 //-----------------------------------------------------------------------
720 UInt_t AliFlowEvent::Centrality()
722 // Returns the Centrality Class as stored
724 if(fCentrality < 0) { SetCentrality() ; }
727 //-----------------------------------------------------------------------
728 void AliFlowEvent::SetCentrality()
730 // Sets the Centrality Classes basing on Multiplicity at mid rapidity,
731 // ... (ZDC information can be added) .
734 Int_t tracks = MultEta() ;
738 cent = AliFlowConstants::fgCentNorm ;
739 //if centrality classes are not defined, does it now (with CentNorm & MaxMult)
740 if(cent[AliFlowConstants::kCents-1] <= 1)
742 for(Int_t ic=0;ic<AliFlowConstants::kCents;ic++)
744 cent[ic] *= AliFlowConstants::fgMaxMult ;
745 if(AliFlowConstants::fgDebug) { cout << "Centrality[" << ic << "] = " << cent[ic] << " . " << endl ; }
749 else if((RunID() != -1) && (CenterOfMassEnergy() == 5500.))
751 cent = (Float_t*)AliFlowConstants::fgCent0 ;
753 else // other definition of centrality are possible ...
755 cent = (Float_t*)AliFlowConstants::fgCent0 ;
757 if (tracks < cent[0]) { fCentrality = 0; }
758 else if (tracks < cent[1]) { fCentrality = 1; }
759 else if (tracks < cent[2]) { fCentrality = 2; }
760 else if (tracks < cent[3]) { fCentrality = 3; }
761 else if (tracks < cent[4]) { fCentrality = 4; }
762 else if (tracks < cent[5]) { fCentrality = 5; }
763 else if (tracks < cent[6]) { fCentrality = 6; }
764 else if (tracks < cent[7]) { fCentrality = 7; }
765 else if (tracks < cent[8]) { fCentrality = 8; }
766 else { fCentrality = 9; }
768 if(AliFlowConstants::fgDebug) { cout << " * Centrality Class : " << fCentrality << " . " << endl ; }
770 //-----------------------------------------------------------------------
771 TVector AliFlowEvent::Bayesian() const
773 // Returns bayesian array of particle abundances (from AliFlowConstants::)
775 TVector bayes(AliFlowConstants::kPid) ;
776 for(Int_t i=0;i<AliFlowConstants::kPid;i++) { bayes[i] = AliFlowConstants::fgBayesian[i] ; }
779 //-----------------------------------------------------------------------
780 void AliFlowEvent::PrintFlagList() const
782 // Prints the list of selection cuts ( called in AliFlowInterface::Finish() )
784 cout << "#######################################################" << endl;
785 cout << "# Weighting and Striping:" << endl;
788 cout << "# PtWgt = kTRUE " << endl ; // (also for output of PhiWgt file?)
789 cout << "# PtWgt Saturation = " << AliFlowConstants::fgPtWgtSaturation << endl;
793 cout << "# PtWgt = kFALSE" << endl;
797 cout << "# EtaWgt = kTRUE " << endl ; // (also for output of PhiWgt file for odd harmonics?)
801 cout << "# EtaWgt = kFALSE" << endl;
803 cout << "#######################################################" << endl;
805 //-----------------------------------------------------------------------
806 Int_t AliFlowEvent::MultEta() const
808 // Returns the multiplicity in the interval |eta|<(AliFlowConstants::fgEetaMid), used
809 // for centrality measurement (see centrality classes in fCentrality) .
811 Int_t goodtracks = 0 ;
812 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
814 AliFlowTrack* pFlowTrack ;
815 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
816 if((pFlowTrack->Charge()) && (TMath::Abs(pFlowTrack->Eta())<AliFlowConstants::fgEtaMid)) { goodtracks++ ; }
820 //-----------------------------------------------------------------------
821 Int_t AliFlowEvent::UncorrNegMult(Float_t eta) const
823 // Negative multiplicity in the interval (-eta..eta)
824 // (default is AliFlowConstants::fgEetaGood = 0.9)
827 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
829 AliFlowTrack* pFlowTrack ;
830 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
831 if((pFlowTrack->Charge()<0) && (TMath::Abs(pFlowTrack->Eta())<TMath::Abs(eta))) { negMult++ ; }
836 //-----------------------------------------------------------------------
837 Int_t AliFlowEvent::UncorrPosMult(Float_t eta) const
839 // Positive multiplicity in the interval (-eta..eta)
840 // (default is AliFlowConstants::fgEetaGood = 0.9)
843 for(Int_t itr=0;itr<TrackCollection()->GetEntries();itr++)
845 AliFlowTrack* pFlowTrack ;
846 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
847 if((pFlowTrack->Charge()>0) && (TMath::Abs(pFlowTrack->Eta())<TMath::Abs(eta))) { posMult++ ; }
852 //-----------------------------------------------------------------------
853 TVector3 AliFlowEvent::VertexPos() const
855 // Returns primary vertex position as a TVector3
859 return TVector3(vertex) ;
861 //-----------------------------------------------------------------------
862 void AliFlowEvent::MakeAll()
864 // calculates all quantities in 1 shoot
866 Double_t mQx[AliFlowConstants::kSels][AliFlowConstants::kHars] ;
867 Double_t mQy[AliFlowConstants::kSels][AliFlowConstants::kHars] ;
868 Double_t mQxSub[AliFlowConstants::kSubs][AliFlowConstants::kSels][AliFlowConstants::kHars] ;
869 Double_t mQySub[AliFlowConstants::kSubs][AliFlowConstants::kSels][AliFlowConstants::kHars] ;
871 int selN, harN, subN ;
872 for(selN=0;selN<AliFlowConstants::kSels;selN++)
874 for(harN=0;harN<AliFlowConstants::kHars;harN++)
876 mQx[selN][harN] = 0. ;
877 mQy[selN][harN] = 0. ;
878 fMult[selN][harN] = 0 ;
879 fSumOfWeightSqr[selN][harN] = 0. ;
880 for(subN=0;subN<AliFlowConstants::kSubs;subN++)
882 mQxSub[subN][selN][harN] = 0. ;
883 mQySub[subN][selN][harN] = 0. ;
884 fMultSub[subN][selN][harN] = 0 ;
894 for(itr=0;itr<TrackCollection()->GetEntries();itr++)
896 AliFlowTrack* pFlowTrack ;
897 pFlowTrack = (AliFlowTrack*)TrackCollection()->At(itr) ;
898 phi = pFlowTrack->Phi();
899 for(selN=0;selN<AliFlowConstants::kSels;selN++)
901 for(harN=0;harN<AliFlowConstants::kHars;harN++)
903 order = (double)(harN+1) ;
904 if(pFlowTrack->Select(harN,selN))
906 phiWgt = PhiWeight(selN,harN,pFlowTrack) ;
907 fSumOfWeightSqr[selN][harN] += phiWgt*phiWgt ;
908 mQx[selN][harN] += phiWgt * cos(phi * order) ;
909 mQy[selN][harN] += phiWgt * sin(phi * order) ;
910 fMult[selN][harN]++ ;
911 for(subN=0;subN<AliFlowConstants::kSubs;subN++)
913 if(pFlowTrack->Select(harN,selN,subN))
915 mQxSub[subN][selN][harN] += phiWgt * cos(phi * order) ;
916 mQySub[subN][selN][harN] += phiWgt * sin(phi * order) ;
917 fMultSub[subN][selN][harN]++ ;
925 for(selN=0;selN<AliFlowConstants::kSels;selN++)
927 for(harN=0;harN<AliFlowConstants::kHars;harN++)
929 fQ[selN][harN].Set(mQx[selN][harN],mQy[selN][harN]) ;
930 for(subN=0;subN<AliFlowConstants::kSubs;subN++) { fQSub[subN][selN][harN].Set(mQxSub[subN][selN][harN],mQySub[subN][selN][harN]) ; }
936 //-----------------------------------------------------------------------