1 /*************************************************************************
2 * Copyright(c) 1998-2008, 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 * create an event and perform *
18 * flow analysis 'on the fly' *
20 * authors: Raimond Snellings *
21 * (snelling@nikhef.nl) *
24 *********************************/
26 #include "Riostream.h"
31 #include "AliFlowEventSimpleMakerOnTheFly.h"
32 #include "AliFlowEventSimple.h"
33 #include "AliFlowTrackSimple.h"
35 ClassImp(AliFlowEventSimpleMakerOnTheFly)
38 //========================================================================
41 AliFlowEventSimpleMakerOnTheFly::AliFlowEventSimpleMakerOnTheFly(UInt_t iseed):
42 fMultDistrOfRPsIsGauss(kFALSE),
44 fMultiplicitySpreadOfRP(0.),
48 fPtDependentHarmonicV1(kFALSE),
49 fEtaDependentHarmonicV1(kFALSE),
50 fPtDependentHarmonicV2(kFALSE),
51 fEtaDependentHarmonicV2(kFALSE),
52 fPtDependentHarmonicV4(kFALSE),
53 fEtaDependentHarmonicV4(kFALSE),
56 fConstantV2IsSampledFromGauss(kFALSE),
75 fPhiDistribution(NULL),
82 fNonflowSectorMin(0.),
83 fNonflowSectorMax(TMath::TwoPi()),
90 fMyTRandom3 = new TRandom3(iseed);
91 gRandom->SetSeed(fMyTRandom3->Integer(65539));
95 //========================================================================
98 AliFlowEventSimpleMakerOnTheFly::~AliFlowEventSimpleMakerOnTheFly()
101 if (fPtSpectra) delete fPtSpectra;
102 if (fPhiDistribution) delete fPhiDistribution;
103 if (fMyTRandom3) delete fMyTRandom3;
107 //========================================================================
110 void AliFlowEventSimpleMakerOnTheFly::Init()
112 // define the pt spectra and phi distribution
114 // pt spectra of pions (Boltzman):
115 Double_t dPtMin = 0.; // to be improved (move this to the body of contstructor?)
116 Double_t dPtMax = 10.; // to be improved (move this to the body of contstructor?)
118 fPtSpectra = new TF1("fPtSpectra","[0]*x*TMath::Exp(-pow(0.13957*0.13957+x*x,0.5)/[1])",dPtMin,dPtMax);
119 fPtSpectra->SetParName(0,"Multiplicity of RPs");
120 fPtSpectra->SetParName(1,"Temperature of RPs");
123 Double_t dPhiMin = 0.; // to be improved (move this to the body of contstructor?)
124 Double_t dPhiMax = TMath::TwoPi(); // to be improved (move this to the body of contstructor?)
126 fPhiDistribution = new TF1("fPhiDistribution","1+2.*[0]*TMath::Cos(x-[2])+2.*[1]*TMath::Cos(2*(x-[2]))+2.*[3]*TMath::Cos(4*(x-[2]))",dPhiMin,dPhiMax);
127 fPhiDistribution->SetParName(0,"directed flow");
128 fPhiDistribution->SetParName(1,"elliptic flow");
129 fPhiDistribution->SetParName(2,"Reaction Plane");
130 fPhiDistribution->SetParName(3,"harmonic 4"); // to be improved (name)
134 //========================================================================
136 AliFlowEventSimple* AliFlowEventSimpleMakerOnTheFly::CreateEventOnTheFly(AliFlowTrackSimpleCuts *cutsRP, AliFlowTrackSimpleCuts *cutsPOI)
138 // method to create event on the fly
140 AliFlowEventSimple* pEvent = new AliFlowEventSimple(fMultiplicityOfRP);
142 // sampling the multiplicity:
143 Int_t iNewMultiplicityOfRP = fMultiplicityOfRP;
145 if(fMultDistrOfRPsIsGauss) {
146 if (fMultiplicitySpreadOfRP>0.0) iNewMultiplicityOfRP = (Int_t)fMyTRandom3->Gaus(fMultiplicityOfRP,fMultiplicitySpreadOfRP);
147 fPtSpectra->SetParameter(0,iNewMultiplicityOfRP);
149 if (fMinMultOfRP != fMaxMultOfRP) {
150 iNewMultiplicityOfRP = (Int_t)fMyTRandom3->Uniform(fMinMultOfRP,fMaxMultOfRP);
151 fPtSpectra->SetParameter(0,iNewMultiplicityOfRP);
153 fPtSpectra->SetParameter(0,fMinMultOfRP);
157 // set the 'temperature' of RPs
158 fPtSpectra->SetParameter(1,fTemperatureOfRP);
160 // sampling the reaction plane
161 Double_t dMCReactionPlaneAngle = fMyTRandom3->Uniform(0.,TMath::TwoPi());
162 fPhiDistribution->SetParameter(2,dMCReactionPlaneAngle);
165 if(!(fPtDependentHarmonicV1 || fEtaDependentHarmonicV1))
167 Double_t dNewV1RP=fV1RP;
168 if(fV1SpreadRP>0.0) {dNewV1RP = fMyTRandom3->Gaus(fV1RP,fV1SpreadRP);}
169 fPhiDistribution->SetParameter(0,dNewV1RP);
173 if(!(fPtDependentHarmonicV2 || fEtaDependentHarmonicV2))
175 Double_t dNewV2RP = fV2RP;
176 if(fConstantV2IsSampledFromGauss)
180 dNewV2RP = fMyTRandom3->Gaus(fV2RP,fV2SpreadRP);
182 fPhiDistribution->SetParameter(1,dNewV2RP);
183 } else if(fMinV2RP < fMaxV2RP)
185 dNewV2RP = fMyTRandom3->Uniform(fMinV2RP,fMaxV2RP);
186 fPhiDistribution->SetParameter(1,dNewV2RP);
187 } else if(fMinV2RP == fMaxV2RP)
190 fPhiDistribution->SetParameter(1,dNewV2RP);
192 } // end of if(!(bPtDependentHarmonicV2 || bEtaDependentHarmonicV2))
195 if(!(fPtDependentHarmonicV4 || fEtaDependentHarmonicV4))
197 Double_t dNewV4RP = fV4RP;
198 if(fV4SpreadRP>0.0) dNewV4RP = fMyTRandom3->Gaus(fV4RP,fV4SpreadRP);
199 fPhiDistribution->SetParameter(3,dNewV4RP);
203 Double_t dEtaMin = -1.; // to be improved
204 Double_t dEtaMax = 1.; // to be improved
206 Int_t iGoodTracks = 0;
207 Int_t iSelParticlesRP = 0;
208 Int_t iSelParticlesPOI = 0;
209 // parameters of original tracks:
210 Double_t dPhiOriginalTrack = 0.;
211 Double_t dPtOriginalTrack = 0.;
212 Double_t dEtaOriginalTrack = 0.;
213 // parameters of splitted tracks:
214 Double_t dPhiSplittedTrack = 0.;
215 Double_t dPtSplittedTrack = 0.;
216 Double_t dEtaSplittedTrack = 0.;
218 Double_t dTmpV1 = 0.;
219 Double_t dTmpV2 = 0.;
220 Double_t dTmpV4 = 0.;
221 Bool_t bUniformAcceptance = kTRUE;
222 Double_t Pi = TMath::Pi();
224 if(!((fPhiMin1==0.) && (fPhiMax1==0.) && (fPhiMin2==0.) && (fPhiMax2==0.))) {
225 bUniformAcceptance = kFALSE;
227 // loop over original tracks:
228 for(Int_t i=0;i<iNewMultiplicityOfRP;i++)
230 // sample the pt and eta for original track:
231 dPtOriginalTrack = fPtSpectra->GetRandom();
232 dEtaOriginalTrack = fMyTRandom3->Uniform(dEtaMin,dEtaMax);
233 // generate flow harmonics which will determine the azimuthal distribution (to be improved - optimized):
235 if(fPtDependentHarmonicV2 || fEtaDependentHarmonicV2)
237 if(fEtaDependentHarmonicV2)
239 if(fV2vsEtaSpread>0.)
241 dTmpV2 = TMath::Exp(-pow(dEtaOriginalTrack/fV2vsEtaSpread,2.));
243 if(!fPtDependentHarmonicV2)
245 dTmpV2*=fV2vsPtEtaMax;
247 } // end of if(fEtaDependentHarmonicV2)
248 if(fPtDependentHarmonicV2)
250 if(!fEtaDependentHarmonicV2)
252 if(dPtOriginalTrack >= fV2PtCutOff) {dTmpV2 = fV2vsPtEtaMax;}
253 else {dTmpV2 = fV2vsPtEtaMax*(dPtOriginalTrack/fV2PtCutOff);}
256 if(dPtOriginalTrack >= fV2PtCutOff) {dTmpV2 *= fV2vsPtEtaMax;}
257 else {dTmpV2 *= fV2vsPtEtaMax*(dPtOriginalTrack/fV2PtCutOff);}
259 } // end of if(fPtDependentHarmonicV2)
260 // flow harmonic is determined and plugged in as a parameter in the predefined azimuthal distribution:
261 fPhiDistribution->SetParameter(1,dTmpV2);
264 if(fPtDependentHarmonicV1 || fEtaDependentHarmonicV1)
266 if(fEtaDependentHarmonicV1)
268 dTmpV1 = -1.*dEtaOriginalTrack;
269 if(!fPtDependentHarmonicV1)
271 dTmpV1*=fV1vsPtEtaMax;
273 } // end of if(fEtaDependentHarmonicV1)
274 if(fPtDependentHarmonicV1)
276 if(!fEtaDependentHarmonicV1)
278 if(dPtOriginalTrack >= fV1PtCutOff) {dTmpV1 = fV1vsPtEtaMax;}
279 else {dTmpV1 = fV1vsPtEtaMax*(dPtOriginalTrack/fV1PtCutOff);}
282 if(dPtOriginalTrack >= fV1PtCutOff) {dTmpV1 *= fV1vsPtEtaMax;}
283 else {dTmpV1 *= fV1vsPtEtaMax*(dPtOriginalTrack/fV1PtCutOff);}
285 } // end of if(fPtDependentHarmonicV1)
286 // flow harmonic is determined and plugged in as a parameter in the predefined azimuthal distribution:
287 fPhiDistribution->SetParameter(0,dTmpV1);
290 if(fPtDependentHarmonicV4 || fEtaDependentHarmonicV4)
292 dTmpV4 = pow(dTmpV2,2.);
293 fPhiDistribution->SetParameter(3,dTmpV4);
295 // sample the phi angle for original track:
296 dPhiOriginalTrack = fPhiDistribution->GetRandom();
297 // from each original track make fNoOfLoops splitted tracks if the particle is ongoing in
298 // detector's sector ranging from fNonflowSectorMin to fNonflowSectorMax
299 // (simulating nonflow correlations between fNoOfLoops tracks in certain detector's sector):
300 for(Int_t d=0;d<fNoOfLoops;d++)
302 if(d>0 && (dPhiOriginalTrack>=fNonflowSectorMin && dPhiOriginalTrack<fNonflowSectorMax))
304 dPhiSplittedTrack = dPhiOriginalTrack;
305 dPtSplittedTrack = dPtOriginalTrack;
306 dEtaSplittedTrack = dEtaOriginalTrack;
310 dPhiSplittedTrack = fMyTRandom3->Uniform(dPhiOriginalTrack-fPhiRange,dPhiOriginalTrack+fPhiRange);
311 if(dPhiSplittedTrack<0)
313 dPhiSplittedTrack+=TMath::TwoPi(); // to ensure angle is in [0,2Pi>
315 if(dPhiSplittedTrack>=TMath::TwoPi())
317 dPhiSplittedTrack-=TMath::TwoPi(); // to ensure angle is in [0,2Pi>
319 } // end of if(fPhiRange>0.)
323 Double_t minPt = dPtOriginalTrack-fPtRange;
324 Double_t maxPt = dPtOriginalTrack+fPtRange;
327 minPt = 0.; // protection against pt<0 for splitted track
329 dPtSplittedTrack = fMyTRandom3->Uniform(minPt,maxPt);
330 } // end of if(fPtRange>0.)
334 dEtaSplittedTrack = fMyTRandom3->Uniform(dEtaOriginalTrack-fEtaRange,dEtaOriginalTrack+fEtaRange);
335 } // end of if(fEtaRange>0.)
337 Double_t dTmpPhi = -44.;
338 Double_t dTmpPt = -44.;
339 Double_t dTmpEta = -44.;
342 if(dPhiOriginalTrack>=fNonflowSectorMin && dPhiOriginalTrack<fNonflowSectorMax)
344 dTmpPhi = dPhiSplittedTrack;
345 dTmpPt = dPtSplittedTrack;
346 dTmpEta = dEtaSplittedTrack;
350 dTmpPhi = dPhiOriginalTrack;
351 dTmpPt = dPtOriginalTrack;
352 dTmpEta = dEtaOriginalTrack;
354 // make the new track:
355 AliFlowTrackSimple *pTrack = new AliFlowTrackSimple();
356 // uniform acceptance:
357 if(bUniformAcceptance)
359 pTrack->SetPt(dTmpPt);
360 pTrack->SetEta(dTmpEta);
361 pTrack->SetPhi(dTmpPhi);
363 if(cutsRP->PassesCuts(pTrack))
365 pTrack->SetForRPSelection(kTRUE);
368 // assign particles to subevents:
369 if(pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
371 pTrack->SetForSubevent(0);
373 if(pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
375 pTrack->SetForSubevent(1);
377 // checking POI cuts:
378 if(cutsPOI->PassesCuts(pTrack))
380 pTrack->SetForPOISelection(kTRUE);
383 pEvent->TrackCollection()->Add(pTrack);
385 } // end of if(bUniformAcceptance)
386 // non-uniform acceptance, 1st sector:
387 else if ((dTmpPhi > fPhiMin1*Pi/180) && (dTmpPhi < fPhiMax1*Pi/180))
389 if(fMyTRandom3->Uniform(0,1) > 1 - fProbability1)
391 pTrack->SetPt(dTmpPt);
392 pTrack->SetEta(dTmpEta);
393 pTrack->SetPhi(dTmpPhi);
395 if(cutsRP->PassesCuts(pTrack))
397 pTrack->SetForRPSelection(kTRUE);
400 // assign particles to subevents
401 if (pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
403 pTrack->SetForSubevent(0);
405 if (pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
407 pTrack->SetForSubevent(1);
409 // checking POI cuts:
410 if(cutsPOI->PassesCuts(pTrack))
412 pTrack->SetForPOISelection(kTRUE);
415 pEvent->TrackCollection()->Add(pTrack);
417 } // end of if(fMyTRandom3->Uniform(0,1) > 1 - fProbability1)
418 } // end of else if ((dTmpPhi > fPhiMin1*Pi/180) && (dTmpPhi < fPhiMax1*Pi/180))
419 // non-uniform acceptance, 2nd sector:
420 else if ((dTmpPhi > fPhiMin2*Pi/180) && (dTmpPhi < fPhiMax2*Pi/180))
422 if(fMyTRandom3->Uniform(0,1) > 1 - fProbability2)
424 pTrack->SetPt(dTmpPt);
425 pTrack->SetEta(dTmpEta);
426 pTrack->SetPhi(dTmpPhi);
428 if(cutsRP->PassesCuts(pTrack))
430 pTrack->SetForRPSelection(kTRUE);
433 // assign particles to subevents
434 if (pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
436 pTrack->SetForSubevent(0);
438 if (pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
440 pTrack->SetForSubevent(1);
442 // checking POI cuts:
443 if(cutsPOI->PassesCuts(pTrack))
445 pTrack->SetForPOISelection(kTRUE);
448 pEvent->TrackCollection()->Add(pTrack);
450 } // end of if(fMyTRandom3->Uniform(0,1) > 1 - fProbability2)
451 } // end of else if ((dTmpPhi > fPhiMin2*Pi/180) && (dTmpPhi < fPhiMax2*Pi/180))
454 pTrack->SetPt(dTmpPt);
455 pTrack->SetEta(dTmpEta);
456 pTrack->SetPhi(dTmpPhi);
458 if(cutsRP->PassesCuts(pTrack))
460 pTrack->SetForRPSelection(kTRUE);
463 // assign particles to subevents
464 if (pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
466 pTrack->SetForSubevent(0);
468 if (pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
470 pTrack->SetForSubevent(1);
472 // checking POI cuts:
473 if(cutsPOI->PassesCuts(pTrack))
475 pTrack->SetForPOISelection(kTRUE);
478 pEvent->TrackCollection()->Add(pTrack);
481 } // end of for(Int_t d=0;d<fNoOfLoops;d++)
482 } // end of for(Int_t i=0;i<iNewMultiplicityOfRP;i++)
484 // update the event quantities
485 pEvent->SetEventNSelTracksRP(iSelParticlesRP);
486 pEvent->SetNumberOfTracks(iGoodTracks); // total number of tracks (RPs + POIs + the ones that didn't pass neither RP nor POI cuts)
487 pEvent->SetMCReactionPlaneAngle(dMCReactionPlaneAngle);
490 if(fPtDependentHarmonicV1 || fEtaDependentHarmonicV1 ||
491 fPtDependentHarmonicV2 || fEtaDependentHarmonicV2 ||
492 fPtDependentHarmonicV4 || fEtaDependentHarmonicV4)
500 if ( (++fCount % cycle) == 0) {
501 if (!dMCReactionPlaneAngle == 0) cout<<" MC Reaction Plane Angle = "<< dMCReactionPlaneAngle << endl;
502 else cout<<" MC Reaction Plane Angle = unknown "<< endl;
503 cout<<" iGoodTracks = "<< iGoodTracks << endl;
504 cout<<" # of RP selected tracks = "<<iSelParticlesRP<<endl;
505 cout<<" # of POI selected tracks = "<<iSelParticlesPOI<<endl;
506 cout << "# " << fCount << " events processed" << endl;
511 } // end of CreateEventOnTheFly()