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 fUseGlauberModel(kFALSE),
43 fMultDistrOfRPsIsGauss(kFALSE),
45 fMultiplicitySpreadOfRP(0.),
49 fPtDependentHarmonicV1(kFALSE),
50 fEtaDependentHarmonicV1(kFALSE),
51 fPtDependentHarmonicV2(kFALSE),
52 fEtaDependentHarmonicV2(kFALSE),
53 fPtDependentHarmonicV4(kFALSE),
54 fEtaDependentHarmonicV4(kFALSE),
57 fConstantV2IsSampledFromGauss(kFALSE),
76 fPhiDistribution(NULL),
83 fNonflowSectorMin(0.),
84 fNonflowSectorMax(TMath::TwoPi()),
91 fMyTRandom3 = new TRandom3(iseed);
92 gRandom->SetSeed(fMyTRandom3->Integer(65539));
96 //========================================================================
99 AliFlowEventSimpleMakerOnTheFly::~AliFlowEventSimpleMakerOnTheFly()
102 if (fPtSpectra) delete fPtSpectra;
103 if (fPhiDistribution) delete fPhiDistribution;
104 if (fMyTRandom3) delete fMyTRandom3;
108 //========================================================================
111 void AliFlowEventSimpleMakerOnTheFly::Init()
113 // define the pt spectra and phi distribution
115 // pt spectra of pions (Boltzman):
116 Double_t dPtMin = 0.; // to be improved (move this to the body of contstructor?)
117 Double_t dPtMax = 10.; // to be improved (move this to the body of contstructor?)
119 fPtSpectra = new TF1("fPtSpectra","[0]*x*TMath::Exp(-pow(0.13957*0.13957+x*x,0.5)/[1])",dPtMin,dPtMax);
120 fPtSpectra->SetParName(0,"Multiplicity of RPs");
121 fPtSpectra->SetParName(1,"Temperature of RPs");
124 Double_t dPhiMin = 0.; // to be improved (move this to the body of contstructor?)
125 Double_t dPhiMax = TMath::TwoPi(); // to be improved (move this to the body of contstructor?)
127 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);
128 fPhiDistribution->SetParName(0,"directed flow");
129 fPhiDistribution->SetParName(1,"elliptic flow");
130 fPhiDistribution->SetParName(2,"Reaction Plane");
131 fPhiDistribution->SetParName(3,"harmonic 4"); // to be improved (name)
135 //========================================================================
137 Int_t AliFlowEventSimpleMakerOnTheFly::DetermineMultiplicity()
139 // Determine multiplicity for current event.
141 Int_t iNewMultiplicityOfRP = fMultiplicityOfRP;
143 if(fMultDistrOfRPsIsGauss) {
144 if (fMultiplicitySpreadOfRP>0.0) iNewMultiplicityOfRP = (Int_t)fMyTRandom3->Gaus(fMultiplicityOfRP,fMultiplicitySpreadOfRP);
145 fPtSpectra->SetParameter(0,iNewMultiplicityOfRP);
147 if (fMinMultOfRP != fMaxMultOfRP) {
148 iNewMultiplicityOfRP = (Int_t)fMyTRandom3->Uniform(fMinMultOfRP,fMaxMultOfRP);
149 fPtSpectra->SetParameter(0,iNewMultiplicityOfRP);
151 fPtSpectra->SetParameter(0,fMinMultOfRP);
155 return iNewMultiplicityOfRP;
157 } // end of AliFlowEventSimpleMakerOnTheFly::DetermineMultiplicity()
159 //========================================================================
161 void AliFlowEventSimpleMakerOnTheFly::DetermineV1()
163 // Determine flow harmonics v1 for current event (if v1 is not pt or eta dependent).
165 Double_t dNewV1RP=fV1RP;
166 if(fV1SpreadRP>0.0) {dNewV1RP = fMyTRandom3->Gaus(fV1RP,fV1SpreadRP);}
167 fPhiDistribution->SetParameter(0,dNewV1RP);
169 } // end of void AliFlowEventSimpleMakerOnTheFly::DetermineV1()
171 //========================================================================
173 void AliFlowEventSimpleMakerOnTheFly::DetermineV4()
175 // Determine flow harmonics v4 for current event (if v4 is not pt or eta dependent).
177 Double_t dNewV4RP = fV4RP;
178 if(fV4SpreadRP>0.0) dNewV4RP = fMyTRandom3->Gaus(fV4RP,fV4SpreadRP);
179 fPhiDistribution->SetParameter(3,dNewV4RP);
181 } // end of void AliFlowEventSimpleMakerOnTheFly::DetermineV4()
183 //========================================================================
185 void AliFlowEventSimpleMakerOnTheFly::DetermineV2()
187 // Determine flow harmonics v2 for current event (if v2 is not pt or eta dependent).
189 Double_t dNewV2RP = fV2RP;
191 if(fConstantV2IsSampledFromGauss)
195 dNewV2RP = fMyTRandom3->Gaus(fV2RP,fV2SpreadRP);}
196 fPhiDistribution->SetParameter(1,dNewV2RP);
197 } else if(fMinV2RP < fMaxV2RP)
199 dNewV2RP = fMyTRandom3->Uniform(fMinV2RP,fMaxV2RP);
200 fPhiDistribution->SetParameter(1,dNewV2RP);
201 } else if(fMinV2RP == fMaxV2RP)
204 fPhiDistribution->SetParameter(1,dNewV2RP);
207 } // end of void AliFlowEventSimpleMakerOnTheFly::DetermineV2()
209 //========================================================================
211 Int_t AliFlowEventSimpleMakerOnTheFly::GlauberModel()
213 // Determine multiplicity and flow harmonics for current event from Glauber moder
215 Int_t multiplicity = 0;
220 // Determine multiplicity, v1, v2 and v4 from Glauber model:
222 // multiplicity = ...
227 // Set obtained values as parameters in relevant distributions:
228 fPtSpectra->SetParameter(0,multiplicity);
229 fPhiDistribution->SetParameter(0,v1);
230 fPhiDistribution->SetParameter(1,v2);
231 fPhiDistribution->SetParameter(3,v4);
235 } // end of Int_t AliFlowEventSimpleMakerOnTheFly::GlauberModel()
237 //========================================================================
239 AliFlowEventSimple* AliFlowEventSimpleMakerOnTheFly::CreateEventOnTheFly(AliFlowTrackSimpleCuts *cutsRP, AliFlowTrackSimpleCuts *cutsPOI)
241 // Method to create event on the fly.
243 // Determine multiplicity and flow harmonics (if not pt or eta dependent) for current event:
244 Int_t multiplicityRP = 0;
245 if(!fUseGlauberModel)
247 multiplicityRP = DetermineMultiplicity();
248 if(!(fPtDependentHarmonicV1||fEtaDependentHarmonicV1)) {DetermineV1();}
249 if(!(fPtDependentHarmonicV2||fEtaDependentHarmonicV2)) {DetermineV2();}
250 if(!(fPtDependentHarmonicV4||fEtaDependentHarmonicV4)) {DetermineV4();}
253 // Determine multipliciy and flow harmonics from Glauber model:
254 multiplicityRP = GlauberModel();
257 AliFlowEventSimple* pEvent = new AliFlowEventSimple(multiplicityRP);
259 // set the 'temperature' of RPs
260 fPtSpectra->SetParameter(1,fTemperatureOfRP);
262 // sampling the reaction plane
263 Double_t dMCReactionPlaneAngle = fMyTRandom3->Uniform(0.,TMath::TwoPi());
264 fPhiDistribution->SetParameter(2,dMCReactionPlaneAngle);
267 Double_t dEtaMin = -1.; // to be improved
268 Double_t dEtaMax = 1.; // to be improved
270 Int_t iGoodTracks = 0;
271 Int_t iSelParticlesRP = 0;
272 Int_t iSelParticlesPOI = 0;
273 // parameters of original tracks:
274 Double_t dPhiOriginalTrack = 0.;
275 Double_t dPtOriginalTrack = 0.;
276 Double_t dEtaOriginalTrack = 0.;
277 // parameters of splitted tracks:
278 Double_t dPhiSplittedTrack = 0.;
279 Double_t dPtSplittedTrack = 0.;
280 Double_t dEtaSplittedTrack = 0.;
282 Double_t dTmpV1 = 0.;
283 Double_t dTmpV2 = 0.;
284 Double_t dTmpV4 = 0.;
285 Bool_t bUniformAcceptance = kTRUE;
286 Double_t Pi = TMath::Pi();
288 if(!((fPhiMin1==0.) && (fPhiMax1==0.) && (fPhiMin2==0.) && (fPhiMax2==0.))) {
289 bUniformAcceptance = kFALSE;
291 // loop over original tracks:
292 for(Int_t i=0;i<multiplicityRP;i++)
294 // sample the pt and eta for original track:
295 dPtOriginalTrack = fPtSpectra->GetRandom();
296 dEtaOriginalTrack = fMyTRandom3->Uniform(dEtaMin,dEtaMax);
297 // generate flow harmonics which will determine the azimuthal distribution (to be improved - optimized):
299 if(fPtDependentHarmonicV2 || fEtaDependentHarmonicV2)
301 if(fEtaDependentHarmonicV2)
303 if(fV2vsEtaSpread>0.)
305 dTmpV2 = TMath::Exp(-pow(dEtaOriginalTrack/fV2vsEtaSpread,2.));
307 if(!fPtDependentHarmonicV2)
309 dTmpV2*=fV2vsPtEtaMax;
311 } // end of if(fEtaDependentHarmonicV2)
312 if(fPtDependentHarmonicV2)
314 if(!fEtaDependentHarmonicV2)
316 if(dPtOriginalTrack >= fV2PtCutOff) {dTmpV2 = fV2vsPtEtaMax;}
317 else {dTmpV2 = fV2vsPtEtaMax*(dPtOriginalTrack/fV2PtCutOff);}
320 if(dPtOriginalTrack >= fV2PtCutOff) {dTmpV2 *= fV2vsPtEtaMax;}
321 else {dTmpV2 *= fV2vsPtEtaMax*(dPtOriginalTrack/fV2PtCutOff);}
323 } // end of if(fPtDependentHarmonicV2)
324 // flow harmonic is determined and plugged in as a parameter in the predefined azimuthal distribution:
325 fPhiDistribution->SetParameter(1,dTmpV2);
328 if(fPtDependentHarmonicV1 || fEtaDependentHarmonicV1)
330 if(fEtaDependentHarmonicV1)
332 dTmpV1 = -1.*dEtaOriginalTrack;
333 if(!fPtDependentHarmonicV1)
335 dTmpV1*=fV1vsPtEtaMax;
337 } // end of if(fEtaDependentHarmonicV1)
338 if(fPtDependentHarmonicV1)
340 if(!fEtaDependentHarmonicV1)
342 if(dPtOriginalTrack >= fV1PtCutOff) {dTmpV1 = fV1vsPtEtaMax;}
343 else {dTmpV1 = fV1vsPtEtaMax*(dPtOriginalTrack/fV1PtCutOff);}
346 if(dPtOriginalTrack >= fV1PtCutOff) {dTmpV1 *= fV1vsPtEtaMax;}
347 else {dTmpV1 *= fV1vsPtEtaMax*(dPtOriginalTrack/fV1PtCutOff);}
349 } // end of if(fPtDependentHarmonicV1)
350 // flow harmonic is determined and plugged in as a parameter in the predefined azimuthal distribution:
351 fPhiDistribution->SetParameter(0,dTmpV1);
354 if(fPtDependentHarmonicV4 || fEtaDependentHarmonicV4)
356 dTmpV4 = pow(dTmpV2,2.);
357 fPhiDistribution->SetParameter(3,dTmpV4);
359 // sample the phi angle for original track:
360 dPhiOriginalTrack = fPhiDistribution->GetRandom();
361 // from each original track make fNoOfLoops splitted tracks if the particle is ongoing in
362 // detector's sector ranging from fNonflowSectorMin to fNonflowSectorMax
363 // (simulating nonflow correlations between fNoOfLoops tracks in certain detector's sector):
364 for(Int_t d=0;d<fNoOfLoops;d++)
366 if(d>0 && (dPhiOriginalTrack>=fNonflowSectorMin && dPhiOriginalTrack<fNonflowSectorMax))
368 dPhiSplittedTrack = dPhiOriginalTrack;
369 dPtSplittedTrack = dPtOriginalTrack;
370 dEtaSplittedTrack = dEtaOriginalTrack;
374 dPhiSplittedTrack = fMyTRandom3->Uniform(dPhiOriginalTrack-fPhiRange,dPhiOriginalTrack+fPhiRange);
375 if(dPhiSplittedTrack<0)
377 dPhiSplittedTrack+=TMath::TwoPi(); // to ensure angle is in [0,2Pi>
379 if(dPhiSplittedTrack>=TMath::TwoPi())
381 dPhiSplittedTrack-=TMath::TwoPi(); // to ensure angle is in [0,2Pi>
383 } // end of if(fPhiRange>0.)
387 Double_t minPt = dPtOriginalTrack-fPtRange;
388 Double_t maxPt = dPtOriginalTrack+fPtRange;
391 minPt = 0.; // protection against pt<0 for splitted track
393 dPtSplittedTrack = fMyTRandom3->Uniform(minPt,maxPt);
394 } // end of if(fPtRange>0.)
398 dEtaSplittedTrack = fMyTRandom3->Uniform(dEtaOriginalTrack-fEtaRange,dEtaOriginalTrack+fEtaRange);
399 } // end of if(fEtaRange>0.)
401 Double_t dTmpPhi = -44.;
402 Double_t dTmpPt = -44.;
403 Double_t dTmpEta = -44.;
406 if(dPhiOriginalTrack>=fNonflowSectorMin && dPhiOriginalTrack<fNonflowSectorMax)
408 dTmpPhi = dPhiSplittedTrack;
409 dTmpPt = dPtSplittedTrack;
410 dTmpEta = dEtaSplittedTrack;
414 dTmpPhi = dPhiOriginalTrack;
415 dTmpPt = dPtOriginalTrack;
416 dTmpEta = dEtaOriginalTrack;
418 // make the new track:
419 AliFlowTrackSimple *pTrack = new AliFlowTrackSimple();
420 // uniform acceptance:
421 if(bUniformAcceptance)
423 pTrack->SetPt(dTmpPt);
424 pTrack->SetEta(dTmpEta);
425 pTrack->SetPhi(dTmpPhi);
427 if(cutsRP->PassesCuts(pTrack))
429 pTrack->SetForRPSelection(kTRUE);
432 // assign particles to subevents:
433 if(pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
435 pTrack->SetForSubevent(0);
437 if(pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
439 pTrack->SetForSubevent(1);
441 // checking POI cuts:
442 if(cutsPOI->PassesCuts(pTrack))
444 pTrack->SetForPOISelection(kTRUE);
447 pEvent->AddTrack(pTrack);
449 } // end of if(bUniformAcceptance)
450 // non-uniform acceptance, 1st sector:
451 else if ((dTmpPhi > fPhiMin1*Pi/180) && (dTmpPhi < fPhiMax1*Pi/180))
453 if(fMyTRandom3->Uniform(0,1) > 1 - fProbability1)
455 pTrack->SetPt(dTmpPt);
456 pTrack->SetEta(dTmpEta);
457 pTrack->SetPhi(dTmpPhi);
459 if(cutsRP->PassesCuts(pTrack))
461 pTrack->SetForRPSelection(kTRUE);
464 // assign particles to subevents
465 if (pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
467 pTrack->SetForSubevent(0);
469 if (pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
471 pTrack->SetForSubevent(1);
473 // checking POI cuts:
474 if(cutsPOI->PassesCuts(pTrack))
476 pTrack->SetForPOISelection(kTRUE);
479 pEvent->AddTrack(pTrack);
481 } // end of if(fMyTRandom3->Uniform(0,1) > 1 - fProbability1)
482 } // end of else if ((dTmpPhi > fPhiMin1*Pi/180) && (dTmpPhi < fPhiMax1*Pi/180))
483 // non-uniform acceptance, 2nd sector:
484 else if ((dTmpPhi > fPhiMin2*Pi/180) && (dTmpPhi < fPhiMax2*Pi/180))
486 if(fMyTRandom3->Uniform(0,1) > 1 - fProbability2)
488 pTrack->SetPt(dTmpPt);
489 pTrack->SetEta(dTmpEta);
490 pTrack->SetPhi(dTmpPhi);
492 if(cutsRP->PassesCuts(pTrack))
494 pTrack->SetForRPSelection(kTRUE);
497 // assign particles to subevents
498 if (pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
500 pTrack->SetForSubevent(0);
502 if (pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
504 pTrack->SetForSubevent(1);
506 // checking POI cuts:
507 if(cutsPOI->PassesCuts(pTrack))
509 pTrack->SetForPOISelection(kTRUE);
512 pEvent->AddTrack(pTrack);
514 } // end of if(fMyTRandom3->Uniform(0,1) > 1 - fProbability2)
515 } // end of else if ((dTmpPhi > fPhiMin2*Pi/180) && (dTmpPhi < fPhiMax2*Pi/180))
518 pTrack->SetPt(dTmpPt);
519 pTrack->SetEta(dTmpEta);
520 pTrack->SetPhi(dTmpPhi);
522 if(cutsRP->PassesCuts(pTrack))
524 pTrack->SetForRPSelection(kTRUE);
527 // assign particles to subevents
528 if (pTrack->Eta()>=fEtaMinA && pTrack->Eta()<=fEtaMaxA)
530 pTrack->SetForSubevent(0);
532 if (pTrack->Eta()>=fEtaMinB && pTrack->Eta()<=fEtaMaxB)
534 pTrack->SetForSubevent(1);
536 // checking POI cuts:
537 if(cutsPOI->PassesCuts(pTrack))
539 pTrack->SetForPOISelection(kTRUE);
542 pEvent->AddTrack(pTrack);
545 } // end of for(Int_t d=0;d<fNoOfLoops;d++)
546 } // end of for(Int_t i=0;i<iNewMultiplicityOfRP;i++)
548 // update the event quantities
549 pEvent->SetEventNSelTracksRP(iSelParticlesRP);
550 pEvent->SetMCReactionPlaneAngle(dMCReactionPlaneAngle);
553 if(fPtDependentHarmonicV1 || fEtaDependentHarmonicV1 ||
554 fPtDependentHarmonicV2 || fEtaDependentHarmonicV2 ||
555 fPtDependentHarmonicV4 || fEtaDependentHarmonicV4)
563 if ( (++fCount % cycle) == 0) {
564 if (!dMCReactionPlaneAngle == 0) cout<<" MC Reaction Plane Angle = "<< dMCReactionPlaneAngle << endl;
565 else cout<<" MC Reaction Plane Angle = unknown "<< endl;
566 cout<<" iGoodTracks = "<< iGoodTracks << endl;
567 cout<<" # of RP selected tracks = "<<iSelParticlesRP<<endl;
568 cout<<" # of POI selected tracks = "<<iSelParticlesPOI<<endl;
569 cout << "# " << fCount << " events processed" << endl;
574 } // end of CreateEventOnTheFly()