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"
45 ClassImp(AliFlowEventSimple)
47 //-----------------------------------------------------------------------
48 AliFlowEventSimple::AliFlowEventSimple():
49 fTrackCollection(NULL),
50 fReferenceMultiplicity(0),
53 fMCReactionPlaneAngle(0.),
54 fMCReactionPlaneAngleIsSet(kFALSE),
55 fAfterBurnerPrecision(0.001),
56 fUserModified(kFALSE),
57 fNumberOfTracksWrap(NULL),
58 fNumberOfRPsWrap(NULL),
59 fMCReactionPlaneAngleWrap(NULL)
61 cout << "AliFlowEventSimple: Default constructor to be used only by root for io" << endl;
64 //-----------------------------------------------------------------------
65 AliFlowEventSimple::AliFlowEventSimple( Int_t n,
66 ConstructionMethod method,
72 fTrackCollection(new TObjArray(n)),
73 fReferenceMultiplicity(n),
76 fMCReactionPlaneAngle(0.),
77 fMCReactionPlaneAngleIsSet(kFALSE),
78 fAfterBurnerPrecision(0.001),
79 fUserModified(kFALSE),
80 fNumberOfTracksWrap(NULL),
81 fNumberOfRPsWrap(NULL),
82 fMCReactionPlaneAngleWrap(NULL)
85 // if second argument is set to AliFlowEventSimple::kGenerate
86 // it generates n random tracks with given Pt distribution
87 // (a sane default is provided), phi and eta are uniform
89 if (method==kGenerate)
90 Generate(n,ptDist,phiMin,phiMax,etaMin,etaMax);
93 //-----------------------------------------------------------------------
94 AliFlowEventSimple::AliFlowEventSimple(const AliFlowEventSimple& anEvent):
96 fTrackCollection((TObjArray*)(anEvent.fTrackCollection)->Clone()),
97 fReferenceMultiplicity(anEvent.fReferenceMultiplicity),
98 fNumberOfTracks(anEvent.fNumberOfTracks),
99 fNumberOfRPs(anEvent.fNumberOfRPs),
100 fMCReactionPlaneAngle(anEvent.fMCReactionPlaneAngle),
101 fMCReactionPlaneAngleIsSet(anEvent.fMCReactionPlaneAngleIsSet),
102 fAfterBurnerPrecision(anEvent.fAfterBurnerPrecision),
103 fUserModified(anEvent.fUserModified),
104 fNumberOfTracksWrap(anEvent.fNumberOfTracksWrap),
105 fNumberOfRPsWrap(anEvent.fNumberOfRPsWrap),
106 fMCReactionPlaneAngleWrap(anEvent.fMCReactionPlaneAngleWrap)
111 //-----------------------------------------------------------------------
112 AliFlowEventSimple& AliFlowEventSimple::operator=(const AliFlowEventSimple& anEvent)
114 //assignment operator
115 if (fTrackCollection) fTrackCollection->Delete();
116 delete fTrackCollection;
117 fTrackCollection = (TObjArray*)(anEvent.fTrackCollection)->Clone(); //deep copy
118 fReferenceMultiplicity = anEvent.fReferenceMultiplicity;
119 fNumberOfTracks = anEvent.fNumberOfTracks;
120 fNumberOfRPs = anEvent.fNumberOfRPs;
121 fMCReactionPlaneAngle = anEvent.fMCReactionPlaneAngle;
122 fMCReactionPlaneAngleIsSet = anEvent.fMCReactionPlaneAngleIsSet;
123 fAfterBurnerPrecision = anEvent.fAfterBurnerPrecision;
124 fUserModified=anEvent.fUserModified;
125 fNumberOfTracksWrap = anEvent.fNumberOfTracksWrap;
126 fNumberOfRPsWrap = anEvent.fNumberOfRPsWrap;
127 fMCReactionPlaneAngleWrap=anEvent.fMCReactionPlaneAngleWrap;
131 //-----------------------------------------------------------------------
132 AliFlowEventSimple::~AliFlowEventSimple()
135 if (fTrackCollection) fTrackCollection->Delete();
136 delete fTrackCollection;
137 if (fNumberOfTracksWrap) delete fNumberOfTracksWrap;
138 if (fNumberOfRPsWrap) delete fNumberOfRPsWrap;
139 if (fMCReactionPlaneAngleWrap) delete fMCReactionPlaneAngleWrap;
142 //-----------------------------------------------------------------------
143 void AliFlowEventSimple::Generate(Int_t nParticles,
150 //generate nParticles random tracks uniform in phi and eta
151 //according to the specified pt distribution
154 static TF1 ptdistribution("ptSpectra","x*TMath::Exp(-pow(0.13957*0.13957+x*x,0.5)/0.4)",0.1,10.);
155 ptDist=&ptdistribution;
158 for (Int_t i=0; i<nParticles; i++)
160 AliFlowTrackSimple* track = new AliFlowTrackSimple();
161 track->SetPhi( gRandom->Uniform(phiMin,phiMax) );
162 track->SetEta( gRandom->Uniform(etaMin,etaMax) );
163 track->SetPt( ptDist->GetRandom() );
164 track->SetCharge( (gRandom->Uniform()-0.5<0)?-1:1 );
167 fMCReactionPlaneAngle=gRandom->Uniform(0.0,TMath::TwoPi());
168 fMCReactionPlaneAngleIsSet=kTRUE;
172 //-----------------------------------------------------------------------
173 AliFlowTrackSimple* AliFlowEventSimple::GetTrack(Int_t i)
175 //get track i from collection
176 if (i>=fNumberOfTracks) return NULL;
177 AliFlowTrackSimple* pTrack = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i)) ;
181 //-----------------------------------------------------------------------
182 void AliFlowEventSimple::AddTrack( AliFlowTrackSimple* track )
185 fTrackCollection->AddLast(track);
189 //-----------------------------------------------------------------------
190 AliFlowVector AliFlowEventSimple::GetQ(Int_t n, TList *weightsList, Bool_t usePhiWeights, Bool_t usePtWeights, Bool_t useEtaWeights)
192 // calculate Q-vector in harmonic n without weights (default harmonic n=2)
199 Double_t iUsedTracks = 0;
203 Double_t dWeight = 1.;
205 AliFlowTrackSimple* pTrack = NULL;
208 Double_t dBinWidthPt = 0.;
209 Double_t dPtMin = 0.;
210 Double_t dBinWidthEta = 0.;
211 Double_t dEtaMin = 0.;
213 Double_t wPhi = 1.; // weight Phi
214 Double_t wPt = 1.; // weight Pt
215 Double_t wEta = 1.; // weight Eta
217 TH1F *phiWeights = NULL;
218 TH1D *ptWeights = NULL;
219 TH1D *etaWeights = NULL;
225 phiWeights = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights"));
226 if(phiWeights) nBinsPhi = phiWeights->GetNbinsX();
230 ptWeights = dynamic_cast<TH1D *>(weightsList->FindObject("pt_weights"));
233 dBinWidthPt = ptWeights->GetBinWidth(1); // assuming that all bins have the same width
234 dPtMin = (ptWeights->GetXaxis())->GetXmin();
239 etaWeights = dynamic_cast<TH1D *>(weightsList->FindObject("eta_weights"));
242 dBinWidthEta = etaWeights->GetBinWidth(1); // assuming that all bins have the same width
243 dEtaMin = (etaWeights->GetXaxis())->GetXmin();
246 } // end of if(weightsList)
249 for(Int_t i=0; i<fNumberOfTracks; i++)
251 pTrack = (AliFlowTrackSimple*)fTrackCollection->At(i);
254 if(pTrack->InRPSelection())
256 dPhi = pTrack->Phi();
258 dEta = pTrack->Eta();
259 dWeight = pTrack->Weight();
261 // determine Phi weight: (to be improved, I should here only access it + the treatment of gaps in the if statement)
262 if(phiWeights && nBinsPhi)
264 wPhi = phiWeights->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*nBinsPhi/TMath::TwoPi())));
266 // determine v'(pt) weight:
267 if(ptWeights && dBinWidthPt)
269 wPt=ptWeights->GetBinContent(1+(Int_t)(TMath::Floor((dPt-dPtMin)/dBinWidthPt)));
271 // determine v'(eta) weight:
272 if(etaWeights && dBinWidthEta)
274 wEta=etaWeights->GetBinContent(1+(Int_t)(TMath::Floor((dEta-dEtaMin)/dBinWidthEta)));
277 // building up the weighted Q-vector:
278 dQX += dWeight*wPhi*wPt*wEta*TMath::Cos(iOrder*dPhi);
279 dQY += dWeight*wPhi*wPt*wEta*TMath::Sin(iOrder*dPhi);
281 // weighted multiplicity:
282 iUsedTracks += dWeight*wPhi*wPt*wEta;
284 } // end of if (pTrack->InRPSelection())
285 } // end of if (pTrack)
288 cerr << "no particle!!!"<<endl;
290 } // loop over particles
293 vQ.SetMult(iUsedTracks);
299 //-----------------------------------------------------------------------
300 void AliFlowEventSimple::Get2Qsub(AliFlowVector* Qarray, Int_t n, TList *weightsList, Bool_t usePhiWeights, Bool_t usePtWeights, Bool_t useEtaWeights)
303 // calculate Q-vector in harmonic n without weights (default harmonic n=2)
308 Double_t iUsedTracks = 0;
312 Double_t dWeight = 1.;
314 AliFlowTrackSimple* pTrack = NULL;
316 Int_t iNbinsPhiSub0 = 0;
317 Int_t iNbinsPhiSub1 = 0;
318 Double_t dBinWidthPt = 0.;
319 Double_t dPtMin = 0.;
320 Double_t dBinWidthEta= 0.;
321 Double_t dEtaMin = 0.;
323 Double_t dWphi = 1.; // weight Phi
324 Double_t dWpt = 1.; // weight Pt
325 Double_t dWeta = 1.; // weight Eta
327 TH1F* phiWeightsSub0 = NULL;
328 TH1F* phiWeightsSub1 = NULL;
329 TH1D* ptWeights = NULL;
330 TH1D* etaWeights = NULL;
336 phiWeightsSub0 = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights_sub0"));
337 phiWeightsSub1 = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights_sub1"));
339 iNbinsPhiSub0 = phiWeightsSub0->GetNbinsX();
342 iNbinsPhiSub1 = phiWeightsSub1->GetNbinsX();
347 ptWeights = dynamic_cast<TH1D *>(weightsList->FindObject("pt_weights"));
350 dBinWidthPt = ptWeights->GetBinWidth(1); // assuming that all bins have the same width
351 dPtMin = (ptWeights->GetXaxis())->GetXmin();
356 etaWeights = dynamic_cast<TH1D *>(weightsList->FindObject("eta_weights"));
359 dBinWidthEta = etaWeights->GetBinWidth(1); // assuming that all bins have the same width
360 dEtaMin = (etaWeights->GetXaxis())->GetXmin();
363 } // end of if(weightsList)
365 //loop over the two subevents
366 for (Int_t s=0; s<2; s++)
369 for(Int_t i=0; i<fNumberOfTracks; i++)
371 pTrack = (AliFlowTrackSimple*)fTrackCollection->At(i);
374 if(pTrack->InRPSelection())
376 if (pTrack->InSubevent(s))
378 dPhi = pTrack->Phi();
380 dEta = pTrack->Eta();
381 dWeight = pTrack->Weight();
383 // determine Phi weight: (to be improved, I should here only access it + the treatment of gaps in the if statement)
384 if(s == 0) { //subevent 0
385 if(phiWeightsSub0 && iNbinsPhiSub0){
386 dWphi = phiWeightsSub0->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*iNbinsPhiSub0/TMath::TwoPi())));
389 if(phiWeightsSub1 && iNbinsPhiSub1){
390 dWphi = phiWeightsSub1->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*iNbinsPhiSub1/TMath::TwoPi())));
394 // determine v'(pt) weight:
395 if(ptWeights && dBinWidthPt)
397 dWpt=ptWeights->GetBinContent(1+(Int_t)(TMath::Floor((dPt-dPtMin)/dBinWidthPt)));
400 // determine v'(eta) weight:
401 if(etaWeights && dBinWidthEta)
403 dWeta=etaWeights->GetBinContent(1+(Int_t)(TMath::Floor((dEta-dEtaMin)/dBinWidthEta)));
406 // building up the weighted Q-vector:
407 dQX += dWeight*dWphi*dWpt*dWeta*TMath::Cos(iOrder*dPhi);
408 dQY += dWeight*dWphi*dWpt*dWeta*TMath::Sin(iOrder*dPhi);
410 // weighted multiplicity:
411 iUsedTracks+=dWeight*dWphi*dWpt*dWeta;
414 } // end of if (pTrack->InRPSelection())
415 } // end of if (pTrack)
418 cerr << "no particle!!!"<<endl;
420 } // loop over particles
421 Qarray[s].Set(dQX,dQY);
422 Qarray[s].SetMult(iUsedTracks);
432 //-----------------------------------------------------------------------
433 void AliFlowEventSimple::Print(Option_t *option) const
435 // -*-*-*-*-*Print some global quantities for this histogram collection class *-*-*-*-*-*-*-*
436 // ===============================================
437 // printf( "TH1.Print Name = %s, Entries= %d, Total sum= %g\n",GetName(),Int_t(fEntries),GetSumOfWeights());
438 printf( "Class.Print Name = %s, #tracks= %d, Number of RPs= %d, MC EventPlaneAngle= %f\n",
439 GetName(),fNumberOfTracks, fNumberOfRPs, fMCReactionPlaneAngle );
441 TString optionstr(option);
442 if (!optionstr.Contains("all")) return;
443 if (fTrackCollection)
445 fTrackCollection->Print(option);
449 printf( "Empty track collection \n");
453 //-----------------------------------------------------------------------
454 void AliFlowEventSimple::Browse(TBrowser *b)
457 if (!fNumberOfTracksWrap)
459 fNumberOfTracksWrap = new TParameter<int>("fNumberOfTracks", fNumberOfTracks);
460 b->Add(fNumberOfTracksWrap);
462 if (!fNumberOfRPsWrap)
464 fNumberOfRPsWrap = new TParameter<int>("fNumberOfRPs", fNumberOfRPs);
465 b->Add(fNumberOfRPsWrap);
467 if (!fMCReactionPlaneAngleWrap)
469 fMCReactionPlaneAngleWrap = new TParameter<double>(" fMCReactionPlaneAngle", fMCReactionPlaneAngle);
470 b->Add( fMCReactionPlaneAngleWrap);
472 if (fTrackCollection) b->Add(fTrackCollection,"AliFlowTracksSimple");
475 //-----------------------------------------------------------------------
476 AliFlowEventSimple::AliFlowEventSimple( TTree* inputTree,
477 const AliFlowTrackSimpleCuts* rpCuts,
478 const AliFlowTrackSimpleCuts* poiCuts):
479 fTrackCollection(NULL),
480 fReferenceMultiplicity(0),
483 fMCReactionPlaneAngle(0.),
484 fMCReactionPlaneAngleIsSet(kFALSE),
485 fAfterBurnerPrecision(0.001),
486 fUserModified(kFALSE),
487 fNumberOfTracksWrap(NULL),
488 fNumberOfRPsWrap(NULL),
489 fMCReactionPlaneAngleWrap(NULL)
491 //constructor, fills the event from a TTree of kinematic.root files
492 //applies RP and POI cuts, tags the tracks
494 Int_t numberOfInputTracks = inputTree->GetEntries() ;
495 fTrackCollection = new TObjArray(numberOfInputTracks/2);
497 TParticle* pParticle = new TParticle();
498 inputTree->SetBranchAddress("Particles",&pParticle);
500 Int_t iSelParticlesPOI = 0;
502 for (Int_t i=0; i<numberOfInputTracks; i++)
504 inputTree->GetEntry(i); //get input particle
506 if (!pParticle) continue; //no particle
507 if (!pParticle->IsPrimary()) continue;
509 Bool_t rpOK = rpCuts->PassesCuts(pParticle);
510 Bool_t poiOK = poiCuts->PassesCuts(pParticle);
514 AliFlowTrackSimple* pTrack = new AliFlowTrackSimple(pParticle);
516 //marking the particles used for int. flow:
519 pTrack->SetForRPSelection(kTRUE);
522 //marking the particles used for diff. flow:
525 pTrack->SetForPOISelection(kTRUE);
528 //adding a particles which were used either for int. or diff. flow to the list
535 //_____________________________________________________________________________
536 void AliFlowEventSimple::CloneTracks(Int_t n)
538 //clone every track n times to add non-flow
539 if (n<=0) return; //no use to clone stuff zero or less times
540 Int_t ntracks = fNumberOfTracks;
541 fTrackCollection->Expand((n+1)*fNumberOfTracks);
542 for (Int_t i=0; i<n; i++)
544 for (Int_t itrack=0; itrack<ntracks; itrack++)
546 AliFlowTrackSimple* track = dynamic_cast<AliFlowTrackSimple*>(fTrackCollection->At(itrack));
547 if (!track) continue;
548 AddTrack(static_cast<AliFlowTrackSimple*>(track->Clone()));
554 //_____________________________________________________________________________
555 void AliFlowEventSimple::ResolutionPt(Double_t res)
557 //smear pt of all tracks by gaussian with sigma=res
558 for (Int_t i=0; i<fNumberOfTracks; i++)
560 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
561 if (track) track->ResolutionPt(res);
566 //_____________________________________________________________________________
567 void AliFlowEventSimple::TagSubeventsInEta( Double_t etaMinA,
572 //Flag two subevents in given eta ranges
573 for (Int_t i=0; i<fNumberOfTracks; i++)
575 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
576 Double_t eta=track->Eta();
577 if (eta >= etaMinA && eta <= etaMaxA) track->SetForSubevent(0);
578 if (eta >= etaMinB && eta <= etaMaxB) track->SetForSubevent(1);
582 //_____________________________________________________________________________
583 void AliFlowEventSimple::AddV1( Double_t v1 )
585 //add v2 to all tracks wrt the reaction plane angle
586 for (Int_t i=0; i<fNumberOfTracks; i++)
588 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
589 if (track) track->AddV1(v1, fMCReactionPlaneAngle, fAfterBurnerPrecision);
594 //_____________________________________________________________________________
595 void AliFlowEventSimple::AddV2( Double_t v2 )
597 //add v2 to all tracks wrt the reaction plane angle
598 for (Int_t i=0; i<fNumberOfTracks; i++)
600 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
601 if (track) track->AddV2(v2, fMCReactionPlaneAngle, fAfterBurnerPrecision);
606 //_____________________________________________________________________________
607 void AliFlowEventSimple::AddV3( Double_t v3 )
609 //add v3 to all tracks wrt the reaction plane angle
610 for (Int_t i=0; i<fNumberOfTracks; i++)
612 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
613 if (track) track->AddV3(v3, fMCReactionPlaneAngle, fAfterBurnerPrecision);
618 //_____________________________________________________________________________
619 void AliFlowEventSimple::AddV4( Double_t v4 )
621 //add v4 to all tracks wrt the reaction plane angle
622 for (Int_t i=0; i<fNumberOfTracks; i++)
624 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
625 if (track) track->AddV4(v4, fMCReactionPlaneAngle, fAfterBurnerPrecision);
630 //_____________________________________________________________________________
631 void AliFlowEventSimple::AddFlow( Double_t v1, Double_t v2, Double_t v3, Double_t v4 )
633 //add flow to all tracks wrt the reaction plane angle
634 for (Int_t i=0; i<fNumberOfTracks; i++)
636 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
637 if (track) track->AddFlow(v1,v2,v3,v4,fMCReactionPlaneAngle, fAfterBurnerPrecision);
642 //_____________________________________________________________________________
643 void AliFlowEventSimple::TagRP( AliFlowTrackSimpleCuts* cuts )
645 //tag tracks as reference particles (RPs)
646 for (Int_t i=0; i<fNumberOfTracks; i++)
648 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
649 if (!track) continue;
650 Bool_t pass=cuts->PassesCuts(track);
651 track->SetForRPSelection(pass);
659 //_____________________________________________________________________________
660 void AliFlowEventSimple::TagPOI( AliFlowTrackSimpleCuts* cuts )
662 //tag tracks as particles of interest (POIs)
663 for (Int_t i=0; i<fNumberOfTracks; i++)
665 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
666 if (!track) continue;
667 Bool_t pass=cuts->PassesCuts(track);
668 track->SetForPOISelection(pass);
672 //_____________________________________________________________________________
673 void AliFlowEventSimple::DefineDeadZone( Double_t etaMin,
678 //mark tracks in given eta-phi region as dead
679 //by resetting the flow bits
680 for (Int_t i=0; i<fNumberOfTracks; i++)
682 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
683 Double_t eta = track->Eta();
684 Double_t phi = track->Phi();
685 if (eta>etaMin && eta<etaMax && phi>phiMin && phi<phiMax)
687 if (track->InRPSelection()) fNumberOfRPs--;
688 track->ResetFlowTags();
693 //_____________________________________________________________________________
694 Int_t AliFlowEventSimple::CleanUpDeadTracks()
696 //remove tracks that have no flow tags set and cleanup the container
697 //returns number of cleaned tracks
699 for (Int_t i=0; i<fNumberOfTracks; i++)
701 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
702 if (track->IsDead()) {delete track;ncleaned++;}
704 fTrackCollection->Compress(); //clean up empty slots