1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /*****************************************************************
17 AliFlowEventSimple: A simple event
20 origin: Naomi van der Kolk (kolk@nikhef.nl)
21 Ante Bilandzic (anteb@nikhef.nl)
22 Raimond Snellings (Raimond.Snellings@nikhef.nl)
23 mods: Mikolaj Krzewicki (mikolaj.krzewicki@cern.ch)
24 *****************************************************************/
26 #include "Riostream.h"
27 #include "TObjArray.h"
31 #include "TParticle.h"
37 #include "TParameter.h"
39 #include "AliFlowVector.h"
40 #include "AliFlowTrackSimple.h"
41 #include "AliFlowTrackSimpleCuts.h"
42 #include "AliFlowEventSimple.h"
48 ClassImp(AliFlowEventSimple)
50 //-----------------------------------------------------------------------
51 AliFlowEventSimple::AliFlowEventSimple():
52 fTrackCollection(NULL),
53 fReferenceMultiplicity(0),
55 fUseGlauberMCSymmetryPlanes(kFALSE),
56 fUseExternalSymmetryPlanes(kFALSE),
65 fMCReactionPlaneAngle(0.),
66 fMCReactionPlaneAngleIsSet(kFALSE),
67 fAfterBurnerPrecision(0.001),
68 fUserModified(kFALSE),
69 fNumberOfTracksWrap(NULL),
70 fNumberOfRPsWrap(NULL),
71 fNumberOfFlowTagsWrap(NULL),
72 fMCReactionPlaneAngleWrap(NULL),
73 fShuffledIndexes(NULL),
74 fShuffleTracks(kFALSE),
75 fMothersCollection(NULL),
77 fNumberOfFlowTagClasses(2),
78 fNumberOfFlowTags(NULL)
80 cout << "AliFlowEventSimple: Default constructor to be used only by root for io" << endl;
83 //-----------------------------------------------------------------------
84 AliFlowEventSimple::AliFlowEventSimple( Int_t n,
85 ConstructionMethod method,
91 fTrackCollection(new TObjArray(n)),
92 fReferenceMultiplicity(0),
94 fUseGlauberMCSymmetryPlanes(kFALSE),
95 fUseExternalSymmetryPlanes(kFALSE),
104 fMCReactionPlaneAngle(0.),
105 fMCReactionPlaneAngleIsSet(kFALSE),
106 fAfterBurnerPrecision(0.001),
107 fUserModified(kFALSE),
108 fNumberOfTracksWrap(NULL),
109 fNumberOfRPsWrap(NULL),
110 fNumberOfFlowTagsWrap(NULL),
111 fMCReactionPlaneAngleWrap(NULL),
112 fShuffledIndexes(NULL),
113 fShuffleTracks(kFALSE),
114 fMothersCollection(new TObjArray()),
116 fNumberOfFlowTagClasses(2),
117 fNumberOfFlowTags(new Int_t[fNumberOfFlowTagClasses])
120 // if second argument is set to AliFlowEventSimple::kGenerate
121 // it generates n random tracks with given Pt distribution
122 // (a sane default is provided), phi and eta are uniform
124 if (method==kGenerate)
125 Generate(n,ptDist,phiMin,phiMax,etaMin,etaMax);
128 //-----------------------------------------------------------------------
129 AliFlowEventSimple::AliFlowEventSimple(const AliFlowEventSimple& anEvent):
131 fTrackCollection((TObjArray*)(anEvent.fTrackCollection)->Clone()),
132 fReferenceMultiplicity(anEvent.fReferenceMultiplicity),
133 fNumberOfTracks(anEvent.fNumberOfTracks),
134 fUseGlauberMCSymmetryPlanes(anEvent.fUseGlauberMCSymmetryPlanes),
135 fUseExternalSymmetryPlanes(anEvent.fUseExternalSymmetryPlanes),
136 fPsi1(anEvent.fPsi1),
137 fPsi2(anEvent.fPsi2),
138 fPsi3(anEvent.fPsi3),
139 fPsi4(anEvent.fPsi4),
140 fPsi5(anEvent.fPsi5),
141 fPsi1Psi3(anEvent.fPsi1Psi3),
142 fPsi2Psi4(anEvent.fPsi2Psi4),
143 fPsi3Psi5(anEvent.fPsi3Psi5),
144 fMCReactionPlaneAngle(anEvent.fMCReactionPlaneAngle),
145 fMCReactionPlaneAngleIsSet(anEvent.fMCReactionPlaneAngleIsSet),
146 fAfterBurnerPrecision(anEvent.fAfterBurnerPrecision),
147 fUserModified(anEvent.fUserModified),
148 fNumberOfTracksWrap(anEvent.fNumberOfTracksWrap),
149 fNumberOfRPsWrap(anEvent.fNumberOfRPsWrap),
150 fNumberOfFlowTagsWrap(anEvent.fNumberOfFlowTagsWrap),
151 fMCReactionPlaneAngleWrap(anEvent.fMCReactionPlaneAngleWrap),
152 fShuffledIndexes(NULL),
153 fShuffleTracks(anEvent.fShuffleTracks),
154 fMothersCollection(new TObjArray()),
155 fCentrality(anEvent.fCentrality),
156 fNumberOfFlowTagClasses(anEvent.fNumberOfFlowTagClasses),
157 fNumberOfFlowTags(new Int_t[fNumberOfFlowTagClasses])
160 memcpy(fNumberOfFlowTags,anEvent.fNumberOfFlowTags,fNumberOfFlowTagClasses*sizeof(Int_t));
163 //-----------------------------------------------------------------------
164 void AliFlowEventSimple::SetNumberOfPOIs( Int_t np, Int_t tagClass)
166 //set the number of POIs increasing the size of the array in necessary
167 if (tagClass>=fNumberOfFlowTagClasses) SetNumberOfFlowTagClasses(tagClass+1);
168 fNumberOfFlowTags[tagClass] = np;
171 //-----------------------------------------------------------------------
172 void AliFlowEventSimple::IncrementNumberOfPOIs(Int_t tagClass)
174 if (tagClass>=fNumberOfFlowTagClasses) SetNumberOfFlowTagClasses(tagClass+1);
175 fNumberOfFlowTags[tagClass]++;
178 //-----------------------------------------------------------------------
179 void AliFlowEventSimple::SetNumberOfFlowTagClasses(Int_t n)
181 //set the number of poi classes, resize the array if larger is needed
182 //never shrink the array
183 //never decrease the stored number
184 if (n>fNumberOfFlowTagClasses)
186 Int_t* tmp = new Int_t[n];
187 for (Int_t j=0; j<n; j++) { tmp[j]=0; }
188 memcpy(tmp,fNumberOfFlowTags,fNumberOfFlowTagClasses*sizeof(Int_t));
189 delete [] fNumberOfFlowTags;
190 fNumberOfFlowTags = tmp;
191 fNumberOfFlowTagClasses = n;
194 //-----------------------------------------------------------------------
195 AliFlowEventSimple& AliFlowEventSimple::operator=(const AliFlowEventSimple& anEvent)
197 //assignment operator
198 if (&anEvent==this) return *this; //check self-assignment
199 if (fTrackCollection) fTrackCollection->Delete();
200 delete fTrackCollection;
201 fTrackCollection = (TObjArray*)(anEvent.fTrackCollection)->Clone(); //deep copy
202 fReferenceMultiplicity = anEvent.fReferenceMultiplicity;
203 fNumberOfTracks = anEvent.fNumberOfTracks;
204 fNumberOfFlowTagClasses = anEvent.fNumberOfFlowTagClasses;
205 delete [] fNumberOfFlowTags;
206 fNumberOfFlowTags=new Int_t[fNumberOfFlowTagClasses];
207 memcpy(fNumberOfFlowTags,anEvent.fNumberOfFlowTags,fNumberOfFlowTagClasses*sizeof(Int_t));
208 fUseGlauberMCSymmetryPlanes = anEvent.fUseGlauberMCSymmetryPlanes;
209 fUseExternalSymmetryPlanes = anEvent.fUseExternalSymmetryPlanes;
210 fPsi1 = anEvent.fPsi1;
211 fPsi2 = anEvent.fPsi2;
212 fPsi3 = anEvent.fPsi3;
213 fPsi4 = anEvent.fPsi4;
214 fPsi5 = anEvent.fPsi5;
215 fPsi1Psi3 = anEvent.fPsi1Psi3;
216 fPsi2Psi4 = anEvent.fPsi2Psi4;
217 fPsi3Psi5 = anEvent.fPsi3Psi5;
218 fMCReactionPlaneAngle = anEvent.fMCReactionPlaneAngle;
219 fMCReactionPlaneAngleIsSet = anEvent.fMCReactionPlaneAngleIsSet;
220 fAfterBurnerPrecision = anEvent.fAfterBurnerPrecision;
221 fUserModified=anEvent.fUserModified;
222 fNumberOfTracksWrap = anEvent.fNumberOfTracksWrap;
223 fNumberOfRPsWrap = anEvent.fNumberOfRPsWrap;
224 fNumberOfFlowTagsWrap = anEvent.fNumberOfFlowTagsWrap;
225 fMCReactionPlaneAngleWrap=anEvent.fMCReactionPlaneAngleWrap;
226 fShuffleTracks=anEvent.fShuffleTracks;
227 delete [] fShuffledIndexes;
231 //-----------------------------------------------------------------------
232 AliFlowEventSimple::~AliFlowEventSimple()
235 if (fTrackCollection) fTrackCollection->Delete();
236 delete fTrackCollection;
237 delete fNumberOfTracksWrap;
238 delete fNumberOfRPsWrap;
239 delete fNumberOfFlowTagsWrap;
240 delete fMCReactionPlaneAngleWrap;
241 delete fShuffledIndexes;
242 delete fMothersCollection;
243 delete [] fNumberOfFlowTags;
246 //-----------------------------------------------------------------------
247 void AliFlowEventSimple::SetUseExternalSymmetryPlanes(TF1 *gPsi1Psi3,
250 //Use symmetry planes, setup correlations between different Psi_n
251 fUseExternalSymmetryPlanes = kTRUE;
253 //Correlations between Psi_1 and Psi_3
254 if(gPsi1Psi3) fPsi1Psi3 = gPsi1Psi3;
256 fPsi1Psi3 = new TF1("fPsi1Psi3","[0]*x+[1]",0.,2.*TMath::Pi());
257 fPsi1Psi3->SetParameter(0,1.);
258 fPsi1Psi3->SetParameter(1,0.);
261 //Correlations between Psi_2 and Psi_4
262 if(gPsi2Psi4) fPsi2Psi4 = gPsi2Psi4;
264 fPsi2Psi4 = new TF1("fPsi2Psi4","[0]*x+[1]",0.,2.*TMath::Pi());
265 fPsi2Psi4->SetParameter(0,1.);
266 fPsi2Psi4->SetParameter(1,0.);
269 //Correlations between Psi_3 and Psi_5
270 if(gPsi3Psi5) fPsi3Psi5 = gPsi3Psi5;
272 fPsi3Psi5 = new TF1("fPsi3Psi5","[0]*x+[1]",0.,2.*TMath::Pi());
273 fPsi3Psi5->SetParameter(0,1.);
274 fPsi3Psi5->SetParameter(1,0.);
278 //-----------------------------------------------------------------------
279 void AliFlowEventSimple::Generate(Int_t nParticles,
286 //generate nParticles random tracks uniform in phi and eta
287 //according to the specified pt distribution
290 static TF1 ptdistribution("ptSpectra","x*TMath::Exp(-pow(0.13957*0.13957+x*x,0.5)/0.4)",0.1,10.);
291 ptDist=&ptdistribution;
294 for (Int_t i=0; i<nParticles; i++)
296 AliFlowTrackSimple* track = new AliFlowTrackSimple();
297 track->SetPhi( gRandom->Uniform(phiMin,phiMax) );
298 track->SetEta( gRandom->Uniform(etaMin,etaMax) );
299 track->SetPt( ptDist->GetRandom() );
300 track->SetCharge( (gRandom->Uniform()-0.5<0)?-1:1 );
303 if(fUseExternalSymmetryPlanes) {
304 Double_t betaParameter = gRandom->Gaus(0.,1.3);
305 fPsi1Psi3->SetParameter(1,betaParameter);
307 betaParameter = gRandom->Gaus(0.,0.9);
308 fPsi2Psi4->SetParameter(1,betaParameter);
310 betaParameter = gRandom->Gaus(0.,1.5);
311 fPsi3Psi5->SetParameter(1,betaParameter);
313 fPsi1 = gRandom->Uniform(2.*TMath::Pi());
314 fPsi2 = gRandom->Uniform(2.*TMath::Pi());
315 fPsi3 = fPsi1Psi3->Eval(fPsi1);
316 if(fPsi3 < 0) fPsi3 += 2.*TMath::Pi();
317 else if(fPsi3 > 2.*TMath::Pi()) fPsi3 -= 2.*TMath::Pi();
318 fPsi4 = fPsi2Psi4->Eval(fPsi2);
319 if(fPsi4 < 0) fPsi4 += 2.*TMath::Pi();
320 else if(fPsi4 > 2.*TMath::Pi()) fPsi4 -= 2.*TMath::Pi();
321 fPsi5 = fPsi3Psi5->Eval(fPsi3);
322 if(fPsi5 < 0) fPsi5 += 2.*TMath::Pi();
323 else if(fPsi5 > 2.*TMath::Pi()) fPsi5 -= 2.*TMath::Pi();
325 fMCReactionPlaneAngle=fPsi2;
326 fMCReactionPlaneAngleIsSet=kTRUE;
329 fMCReactionPlaneAngle=gRandom->Uniform(0.0,TMath::TwoPi());
330 fMCReactionPlaneAngleIsSet=kTRUE;
335 //-----------------------------------------------------------------------
336 AliFlowTrackSimple* AliFlowEventSimple::GetTrack(Int_t i)
338 //get track i from collection
339 if (i>=fNumberOfTracks) return NULL;
341 //if asked use the shuffled index
344 if (!fShuffledIndexes) ShuffleTracks();
345 trackIndex=fShuffledIndexes[i];
347 AliFlowTrackSimple* pTrack = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(trackIndex)) ;
351 //-----------------------------------------------------------------------
352 void AliFlowEventSimple::ShuffleTracks()
354 //shuffle track indexes
355 if (!fShuffledIndexes)
357 //initialize the table with shuffled indexes
358 fShuffledIndexes = new Int_t[fNumberOfTracks];
359 for (Int_t j=0; j<fNumberOfTracks; j++) { fShuffledIndexes[j]=j; }
362 std::random_shuffle(&fShuffledIndexes[0], &fShuffledIndexes[fNumberOfTracks]);
363 Printf("Tracks shuffled! tracks: %i",fNumberOfTracks);
366 //-----------------------------------------------------------------------
367 void AliFlowEventSimple::AddTrack( AliFlowTrackSimple* track )
369 //add a track, delete the old one if necessary
370 if (fNumberOfTracks < fTrackCollection->GetEntriesFast())
372 TObject* o = fTrackCollection->At(fNumberOfTracks);
375 fTrackCollection->AddAtAndExpand(track,fNumberOfTracks);
376 if (track->GetNDaughters()>0)
378 //if there track has daughters cache in the collection of mothers
379 fMothersCollection->Add(track);
384 //-----------------------------------------------------------------------
385 void AliFlowEventSimple::TrackAdded()
387 //book keeping after a new track has been added
389 if (fShuffledIndexes)
391 delete [] fShuffledIndexes;
392 fShuffledIndexes=NULL;
396 //-----------------------------------------------------------------------
397 AliFlowTrackSimple* AliFlowEventSimple::MakeNewTrack()
399 AliFlowTrackSimple *t=dynamic_cast<AliFlowTrackSimple *>(fTrackCollection->RemoveAt(fNumberOfTracks));
400 if( !t ) { // If there was no track at the end of the list then create a new track
401 t=new AliFlowTrackSimple();
407 //-----------------------------------------------------------------------
408 AliFlowVector AliFlowEventSimple::GetQ( Int_t n,
410 Bool_t usePhiWeights,
412 Bool_t useEtaWeights )
414 // calculate Q-vector in harmonic n without weights (default harmonic n=2)
421 Double_t sumOfWeights = 0.;
425 Double_t dWeight = 1.;
427 AliFlowTrackSimple* pTrack = NULL;
430 Double_t dBinWidthPt = 0.;
431 Double_t dPtMin = 0.;
432 Double_t dBinWidthEta = 0.;
433 Double_t dEtaMin = 0.;
435 Double_t wPhi = 1.; // weight Phi
436 Double_t wPt = 1.; // weight Pt
437 Double_t wEta = 1.; // weight Eta
439 TH1F *phiWeights = NULL;
440 TH1D *ptWeights = NULL;
441 TH1D *etaWeights = NULL;
447 phiWeights = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights"));
448 if(phiWeights) nBinsPhi = phiWeights->GetNbinsX();
452 ptWeights = dynamic_cast<TH1D *>(weightsList->FindObject("pt_weights"));
455 dBinWidthPt = ptWeights->GetBinWidth(1); // assuming that all bins have the same width
456 dPtMin = (ptWeights->GetXaxis())->GetXmin();
461 etaWeights = dynamic_cast<TH1D *>(weightsList->FindObject("eta_weights"));
464 dBinWidthEta = etaWeights->GetBinWidth(1); // assuming that all bins have the same width
465 dEtaMin = (etaWeights->GetXaxis())->GetXmin();
468 } // end of if(weightsList)
471 for(Int_t i=0; i<fNumberOfTracks; i++)
473 pTrack = (AliFlowTrackSimple*)fTrackCollection->At(i);
476 if(pTrack->InRPSelection())
478 dPhi = pTrack->Phi();
480 dEta = pTrack->Eta();
481 dWeight = pTrack->Weight();
483 // determine Phi weight: (to be improved, I should here only access it + the treatment of gaps in the if statement)
484 if(phiWeights && nBinsPhi)
486 wPhi = phiWeights->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*nBinsPhi/TMath::TwoPi())));
488 // determine v'(pt) weight:
489 if(ptWeights && dBinWidthPt)
491 wPt=ptWeights->GetBinContent(1+(Int_t)(TMath::Floor((dPt-dPtMin)/dBinWidthPt)));
493 // determine v'(eta) weight:
494 if(etaWeights && dBinWidthEta)
496 wEta=etaWeights->GetBinContent(1+(Int_t)(TMath::Floor((dEta-dEtaMin)/dBinWidthEta)));
499 // building up the weighted Q-vector:
500 dQX += dWeight*wPhi*wPt*wEta*TMath::Cos(iOrder*dPhi);
501 dQY += dWeight*wPhi*wPt*wEta*TMath::Sin(iOrder*dPhi);
503 // weighted multiplicity:
504 sumOfWeights += dWeight*wPhi*wPt*wEta;
506 } // end of if (pTrack->InRPSelection())
507 } // end of if (pTrack)
510 cerr << "no particle!!!"<<endl;
512 } // loop over particles
515 vQ.SetMult(sumOfWeights);
516 vQ.SetHarmonic(iOrder);
517 vQ.SetFlowTagType(AliFlowTrackSimple::kRP);
518 vQ.SetSubeventNumber(-1);
524 //-----------------------------------------------------------------------
525 void AliFlowEventSimple::Get2Qsub( AliFlowVector* Qarray,
528 Bool_t usePhiWeights,
530 Bool_t useEtaWeights )
533 // calculate Q-vector in harmonic n without weights (default harmonic n=2)
538 Double_t sumOfWeights = 0.;
542 Double_t dWeight = 1.;
544 AliFlowTrackSimple* pTrack = NULL;
546 Int_t iNbinsPhiSub0 = 0;
547 Int_t iNbinsPhiSub1 = 0;
548 Double_t dBinWidthPt = 0.;
549 Double_t dPtMin = 0.;
550 Double_t dBinWidthEta= 0.;
551 Double_t dEtaMin = 0.;
553 Double_t dWphi = 1.; // weight Phi
554 Double_t dWpt = 1.; // weight Pt
555 Double_t dWeta = 1.; // weight Eta
557 TH1F* phiWeightsSub0 = NULL;
558 TH1F* phiWeightsSub1 = NULL;
559 TH1D* ptWeights = NULL;
560 TH1D* etaWeights = NULL;
566 phiWeightsSub0 = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights_sub0"));
568 iNbinsPhiSub0 = phiWeightsSub0->GetNbinsX();
570 phiWeightsSub1 = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights_sub1"));
572 iNbinsPhiSub1 = phiWeightsSub1->GetNbinsX();
577 ptWeights = dynamic_cast<TH1D *>(weightsList->FindObject("pt_weights"));
580 dBinWidthPt = ptWeights->GetBinWidth(1); // assuming that all bins have the same width
581 dPtMin = (ptWeights->GetXaxis())->GetXmin();
586 etaWeights = dynamic_cast<TH1D *>(weightsList->FindObject("eta_weights"));
589 dBinWidthEta = etaWeights->GetBinWidth(1); // assuming that all bins have the same width
590 dEtaMin = (etaWeights->GetXaxis())->GetXmin();
593 } // end of if(weightsList)
595 //loop over the two subevents
596 for (Int_t s=0; s<2; s++)
599 for(Int_t i=0; i<fNumberOfTracks; i++)
601 pTrack = (AliFlowTrackSimple*)fTrackCollection->At(i);
604 cerr << "no particle!!!"<<endl;
607 if(pTrack->InRPSelection() && (pTrack->InSubevent(s)))
609 dPhi = pTrack->Phi();
611 dEta = pTrack->Eta();
612 dWeight = pTrack->Weight();
614 // determine Phi weight: (to be improved, I should here only access it + the treatment of gaps in the if statement)
617 if(phiWeightsSub0 && iNbinsPhiSub0) {
618 Int_t phiBin = 1+(Int_t)(TMath::Floor(dPhi*iNbinsPhiSub0/TMath::TwoPi()));
619 //use the phi value at the center of the bin
620 dPhi = phiWeightsSub0->GetBinCenter(phiBin);
621 dWphi = phiWeightsSub0->GetBinContent(phiBin);
626 if(phiWeightsSub1 && iNbinsPhiSub1) {
627 Int_t phiBin = 1+(Int_t)(TMath::Floor(dPhi*iNbinsPhiSub1/TMath::TwoPi()));
628 //use the phi value at the center of the bin
629 dPhi = phiWeightsSub1->GetBinCenter(phiBin);
630 dWphi = phiWeightsSub1->GetBinContent(phiBin);
634 // determine v'(pt) weight:
635 if(ptWeights && dBinWidthPt)
637 dWpt=ptWeights->GetBinContent(1+(Int_t)(TMath::Floor((dPt-dPtMin)/dBinWidthPt)));
640 // determine v'(eta) weight:
641 if(etaWeights && dBinWidthEta)
643 dWeta=etaWeights->GetBinContent(1+(Int_t)(TMath::Floor((dEta-dEtaMin)/dBinWidthEta)));
646 // building up the weighted Q-vector:
647 dQX += dWeight*dWphi*dWpt*dWeta*TMath::Cos(iOrder*dPhi);
648 dQY += dWeight*dWphi*dWpt*dWeta*TMath::Sin(iOrder*dPhi);
650 // weighted multiplicity:
651 sumOfWeights+=dWeight*dWphi*dWpt*dWeta;
653 } // end of if (pTrack->InRPSelection())
654 } // loop over particles
656 Qarray[s].Set(dQX,dQY);
657 Qarray[s].SetMult(sumOfWeights);
658 Qarray[s].SetHarmonic(iOrder);
659 Qarray[s].SetFlowTagType(AliFlowTrackSimple::kRP);
660 Qarray[s].SetSubeventNumber(s);
671 //-----------------------------------------------------------------------
672 void AliFlowEventSimple::Print(Option_t *option) const
674 // -*-*-*-*-*Print some global quantities for this histogram collection class *-*-*-*-*-*-*-*
675 // ===============================================
676 // printf( "TH1.Print Name = %s, Entries= %d, Total sum= %g\n",GetName(),Int_t(fEntries),GetSumOfWeights());
677 printf( "Class.Print Name = %s, #tracks= %d, Number of RPs= %d, Number of POIs = %d, MC EventPlaneAngle= %f\n",
678 GetName(),fNumberOfTracks, fNumberOfFlowTags[0], fNumberOfFlowTags[1], fMCReactionPlaneAngle );
680 TString optionstr(option);
681 if (!optionstr.Contains("all")) return;
682 if (fTrackCollection)
684 fTrackCollection->Print(option);
688 printf( "Empty track collection \n");
692 //-----------------------------------------------------------------------
693 void AliFlowEventSimple::Browse(TBrowser *b)
697 if (!fNumberOfTracksWrap)
699 fNumberOfTracksWrap = new TParameter<int>("fNumberOfTracks", fNumberOfTracks);
700 b->Add(fNumberOfTracksWrap);
702 if (!fNumberOfRPsWrap)
704 fNumberOfRPsWrap = new TParameter<int>("fNumberOfRPs", GetNumberOfRPs());
705 b->Add(fNumberOfRPsWrap);
707 if (!fNumberOfFlowTagsWrap)
709 fNumberOfFlowTagsWrap = new TParameter<int>("fNumberOfFlowTags", GetNumberOfPOIs());
710 b->Add(fNumberOfFlowTagsWrap);
712 if (!fMCReactionPlaneAngleWrap)
714 fMCReactionPlaneAngleWrap = new TParameter<double>(" fMCReactionPlaneAngle", fMCReactionPlaneAngle);
715 b->Add( fMCReactionPlaneAngleWrap);
717 if (fTrackCollection) b->Add(fTrackCollection,"AliFlowTracksSimple");
720 //-----------------------------------------------------------------------
721 AliFlowEventSimple::AliFlowEventSimple( TTree* inputTree,
722 const AliFlowTrackSimpleCuts* rpCuts,
723 const AliFlowTrackSimpleCuts* poiCuts):
724 fTrackCollection(NULL),
725 fReferenceMultiplicity(0),
727 fUseGlauberMCSymmetryPlanes(kFALSE),
728 fUseExternalSymmetryPlanes(kFALSE),
737 fMCReactionPlaneAngle(0.),
738 fMCReactionPlaneAngleIsSet(kFALSE),
739 fAfterBurnerPrecision(0.001),
740 fUserModified(kFALSE),
741 fNumberOfTracksWrap(NULL),
742 fNumberOfRPsWrap(NULL),
743 fNumberOfFlowTagsWrap(NULL),
744 fMCReactionPlaneAngleWrap(NULL),
745 fShuffledIndexes(NULL),
746 fShuffleTracks(kFALSE),
747 fMothersCollection(new TObjArray()),
749 fNumberOfFlowTagClasses(poiCuts->GetNumberOfPOIclasses()+1),
750 fNumberOfFlowTags(new Int_t[fNumberOfFlowTagClasses])
752 //constructor, fills the event from a TTree of kinematic.root files
753 //applies RP and POI cuts, tags the tracks
755 Int_t numberOfInputTracks = inputTree->GetEntries() ;
756 fTrackCollection = new TObjArray(numberOfInputTracks/2);
758 TParticle* pParticle = new TParticle();
759 inputTree->SetBranchAddress("Particles",&pParticle);
761 for (Int_t i=0; i<numberOfInputTracks; i++)
763 inputTree->GetEntry(i); //get input particle
765 if (!pParticle) continue; //no particle
766 if (!pParticle->IsPrimary()) continue;
768 Bool_t rpOK = (rpCuts->PassesCuts(pParticle)>0);
769 Int_t poiType = poiCuts->PassesCuts(pParticle);
771 if (rpOK || poiType>0)
773 AliFlowTrackSimple* pTrack = new AliFlowTrackSimple(pParticle);
775 //marking the particles used for int. flow:
778 pTrack->TagRP(kTRUE);
779 fNumberOfFlowTags[0]++;
780 cout<<"numberOfRPs = "<<fNumberOfFlowTags[0]<<endl;
782 //marking the particles used for diff. flow:
785 pTrack->Tag(poiType);
786 fNumberOfFlowTags[poiType]++;
787 printf("fNumberOfFlowTags[%i] = %i",poiType,fNumberOfFlowTags[poiType]);
789 //adding a particles which were used either for int. or diff. flow to the list
796 //_____________________________________________________________________________
797 void AliFlowEventSimple::CloneTracks(Int_t n)
799 //clone every track n times to add non-flow
800 if (n<=0) return; //no use to clone stuff zero or less times
801 Int_t ntracks = fNumberOfTracks;
802 fTrackCollection->Expand((n+1)*fNumberOfTracks);
803 for (Int_t i=0; i<n; i++)
805 for (Int_t itrack=0; itrack<ntracks; itrack++)
807 AliFlowTrackSimple* track = dynamic_cast<AliFlowTrackSimple*>(fTrackCollection->At(itrack));
808 if (!track) continue;
809 AddTrack(static_cast<AliFlowTrackSimple*>(track->Clone()));
815 //_____________________________________________________________________________
816 void AliFlowEventSimple::ResolutionPt(Double_t res)
818 //smear pt of all tracks by gaussian with sigma=res
819 for (Int_t i=0; i<fNumberOfTracks; i++)
821 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
822 if (track) track->ResolutionPt(res);
827 //_____________________________________________________________________________
828 void AliFlowEventSimple::TagSubeventsInEta( Double_t etaMinA,
833 //Flag two subevents in given eta ranges
834 for (Int_t i=0; i<fNumberOfTracks; i++)
836 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
837 if (!track) continue;
838 track->ResetSubEventTags();
839 Double_t eta=track->Eta();
840 if (eta >= etaMinA && eta <= etaMaxA) track->SetForSubevent(0);
841 if (eta >= etaMinB && eta <= etaMaxB) track->SetForSubevent(1);
845 //_____________________________________________________________________________
846 void AliFlowEventSimple::TagSubeventsByCharge()
848 //Flag two subevents in given eta ranges
849 for (Int_t i=0; i<fNumberOfTracks; i++)
851 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
852 if (!track) continue;
853 track->ResetSubEventTags();
854 Int_t charge=track->Charge();
855 if (charge<0) track->SetForSubevent(0);
856 if (charge>0) track->SetForSubevent(1);
860 //_____________________________________________________________________________
861 void AliFlowEventSimple::AddV1( Double_t v1 )
863 //add v2 to all tracks wrt the reaction plane angle
864 for (Int_t i=0; i<fNumberOfTracks; i++)
866 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
868 if((fUseExternalSymmetryPlanes)||(fUseGlauberMCSymmetryPlanes))
869 track->AddV1(v1, fPsi1, fAfterBurnerPrecision);
871 track->AddV1(v1, fMCReactionPlaneAngle, fAfterBurnerPrecision);
877 //_____________________________________________________________________________
878 void AliFlowEventSimple::AddV2( Double_t v2 )
880 //add v2 to all tracks wrt the reaction plane angle
881 for (Int_t i=0; i<fNumberOfTracks; i++)
883 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
885 if((fUseExternalSymmetryPlanes)||(fUseGlauberMCSymmetryPlanes))
886 track->AddV2(v2, fPsi2, fAfterBurnerPrecision);
888 track->AddV2(v2, fMCReactionPlaneAngle, fAfterBurnerPrecision);
894 //_____________________________________________________________________________
895 void AliFlowEventSimple::AddV3( Double_t v3 )
897 //add v3 to all tracks wrt the reaction plane angle
898 for (Int_t i=0; i<fNumberOfTracks; i++)
900 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
902 if((fUseExternalSymmetryPlanes)||(fUseGlauberMCSymmetryPlanes))
903 track->AddV3(v3, fPsi3, fAfterBurnerPrecision);
905 track->AddV3(v3, fMCReactionPlaneAngle, fAfterBurnerPrecision);
911 //_____________________________________________________________________________
912 void AliFlowEventSimple::AddV4( Double_t v4 )
914 //add v4 to all tracks wrt the reaction plane angle
915 for (Int_t i=0; i<fNumberOfTracks; i++)
917 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
919 if((fUseExternalSymmetryPlanes)||(fUseGlauberMCSymmetryPlanes))
920 track->AddV4(v4, fPsi4, fAfterBurnerPrecision);
922 track->AddV4(v4, fMCReactionPlaneAngle, fAfterBurnerPrecision);
928 //_____________________________________________________________________________
929 void AliFlowEventSimple::AddV5( Double_t v5 )
931 //add v4 to all tracks wrt the reaction plane angle
932 for (Int_t i=0; i<fNumberOfTracks; i++)
934 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
936 if((fUseExternalSymmetryPlanes)||(fUseGlauberMCSymmetryPlanes))
937 track->AddV5(v5, fPsi5, fAfterBurnerPrecision);
939 track->AddV5(v5, fMCReactionPlaneAngle, fAfterBurnerPrecision);
945 //_____________________________________________________________________________
946 void AliFlowEventSimple::AddFlow( Double_t v1, Double_t v2, Double_t v3, Double_t v4, Double_t v5,
947 Double_t rp1, Double_t rp2, Double_t rp3, Double_t rp4, Double_t rp5 )
949 //add flow to all tracks wrt the reaction plane angle, for all harmonic separate angle
950 for (Int_t i=0; i<fNumberOfTracks; i++)
952 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
953 if (track) track->AddFlow(v1,v2,v3,v4,v5,rp1,rp2,rp3,rp4,rp5,fAfterBurnerPrecision);
958 //_____________________________________________________________________________
959 void AliFlowEventSimple::AddFlow( Double_t v1, Double_t v2, Double_t v3, Double_t v4, Double_t v5 )
961 //add flow to all tracks wrt the reaction plane angle
962 for (Int_t i=0; i<fNumberOfTracks; i++)
964 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
965 if (track) track->AddFlow(v1,v2,v3,v4,v5,fMCReactionPlaneAngle, fAfterBurnerPrecision);
970 //_____________________________________________________________________________
971 void AliFlowEventSimple::AddV2( TF1* ptDepV2 )
973 //add v2 to all tracks wrt the reaction plane angle
974 for (Int_t i=0; i<fNumberOfTracks; i++)
976 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
977 if (!track) continue;
978 Double_t v2 = ptDepV2->Eval(track->Pt());
979 track->AddV2(v2, fMCReactionPlaneAngle, fAfterBurnerPrecision);
984 //_____________________________________________________________________________
985 void AliFlowEventSimple::TagRP( const AliFlowTrackSimpleCuts* cuts )
987 //tag tracks as reference particles (RPs)
988 for (Int_t i=0; i<fNumberOfTracks; i++)
990 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
991 if (!track) continue;
992 Bool_t pass=cuts->PassesCuts(track);
993 Bool_t rpTrack=track->InRPSelection();
996 if (!rpTrack) fNumberOfFlowTags[0]++; //only increase if not already tagged
1000 if (rpTrack) fNumberOfFlowTags[0]--; //only decrease if detagging
1002 track->SetForRPSelection(pass);
1006 //_____________________________________________________________________________
1007 void AliFlowEventSimple::TagPOI( const AliFlowTrackSimpleCuts* cuts, Int_t poiType )
1009 //tag tracks as particles of interest (POIs)
1010 for (Int_t i=0; i<fNumberOfTracks; i++)
1012 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
1013 if (!track) continue;
1014 Bool_t pass=cuts->PassesCuts(track);
1015 Bool_t poiTrack=track->InPOISelection();
1018 if (!poiTrack) fNumberOfFlowTags[poiType]++; //only increase if not already tagged
1022 if (poiTrack) fNumberOfFlowTags[poiType]--; //only decrease if detagging
1024 track->Tag(poiType,pass);
1028 //_____________________________________________________________________________
1029 void AliFlowEventSimple::DefineDeadZone( Double_t etaMin,
1034 //mark tracks in given eta-phi region as dead
1035 //by resetting the flow bits
1036 for (Int_t i=0; i<fNumberOfTracks; i++)
1038 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
1039 Double_t eta = track->Eta();
1040 Double_t phi = track->Phi();
1041 if (eta>etaMin && eta<etaMax && phi>phiMin && phi<phiMax)
1043 if (track->InRPSelection()) {fNumberOfFlowTags[0]--;}
1044 for (Int_t j=1; j<fNumberOfFlowTagClasses; j++)
1046 if (track->CheckTag(j)) {fNumberOfFlowTags[j]--;}
1048 track->ResetFlowTags();
1053 //_____________________________________________________________________________
1054 Int_t AliFlowEventSimple::CleanUpDeadTracks()
1056 //remove tracks that have no flow tags set and cleanup the container
1057 //returns number of cleaned tracks
1059 for (Int_t i=0; i<fNumberOfTracks; i++)
1061 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
1062 if (!track) continue;
1063 if (track->IsDead()) {delete track;track=NULL;ncleaned++;}
1065 fTrackCollection->Compress(); //clean up empty slots
1066 fNumberOfTracks-=ncleaned; //update number of tracks
1067 delete [] fShuffledIndexes; fShuffledIndexes=NULL;
1071 //_____________________________________________________________________________
1072 TF1* AliFlowEventSimple::SimplePtDepV2()
1074 //return a standard pt dependent v2 formula, user has to clean up!
1075 return new TF1("StandardPtDepV2","((x<1.0)*(0.05/1.0)*x+(x>=1.0)*0.05)");
1078 //_____________________________________________________________________________
1079 TF1* AliFlowEventSimple::SimplePtSpectrum()
1081 //return a standard pt spectrum, user has to clean up!
1082 return new TF1("StandardPtSpectrum","x*TMath::Exp(-pow(0.13957*0.13957+x*x,0.5)/0.4)",0.1,10.);
1085 //_____________________________________________________________________________
1086 void AliFlowEventSimple::ClearFast()
1088 //clear the counters without deleting allocated objects so they can be reused
1089 fReferenceMultiplicity = 0;
1090 fNumberOfTracks = 0;
1091 for (Int_t i=0; i<fNumberOfFlowTagClasses; i++)
1093 fNumberOfFlowTags[i] = 0;
1095 fMCReactionPlaneAngle = 0.0;
1096 fMCReactionPlaneAngleIsSet = kFALSE;
1097 fAfterBurnerPrecision = 0.001;
1098 fUserModified = kFALSE;
1099 delete [] fShuffledIndexes; fShuffledIndexes=NULL;