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 fNumberOfTracksWrap(NULL),
57 fNumberOfRPsWrap(NULL),
58 fMCReactionPlaneAngleWrap(NULL)
60 cout << "AliFlowEventSimple: Default constructor to be used only by root for io" << endl;
63 //-----------------------------------------------------------------------
64 AliFlowEventSimple::AliFlowEventSimple(Int_t aLength):
65 fTrackCollection(new TObjArray(aLength)),
66 fReferenceMultiplicity(0),
69 fMCReactionPlaneAngle(0.),
70 fMCReactionPlaneAngleIsSet(kFALSE),
71 fAfterBurnerPrecision(0.001),
72 fNumberOfTracksWrap(NULL),
73 fNumberOfRPsWrap(NULL),
74 fMCReactionPlaneAngleWrap(NULL)
79 //-----------------------------------------------------------------------
80 AliFlowEventSimple::AliFlowEventSimple( Int_t nParticles,
86 fTrackCollection(new TObjArray(nParticles)),
87 fReferenceMultiplicity(nParticles),
90 fMCReactionPlaneAngle(0.),
91 fMCReactionPlaneAngleIsSet(kFALSE),
92 fAfterBurnerPrecision(0.001),
93 fNumberOfTracksWrap(NULL),
94 fNumberOfRPsWrap(NULL),
95 fMCReactionPlaneAngleWrap(NULL)
97 //ctor. generates nParticles random tracks with given Pt distribution
98 //phi and eta are uniform
99 Generate(nParticles,ptDist,phiMin,phiMax,etaMin,etaMax);
102 //-----------------------------------------------------------------------
103 AliFlowEventSimple::AliFlowEventSimple(const AliFlowEventSimple& anEvent):
105 fTrackCollection((TObjArray*)(anEvent.fTrackCollection)->Clone()),
106 fReferenceMultiplicity(anEvent.fReferenceMultiplicity),
107 fNumberOfTracks(anEvent.fNumberOfTracks),
108 fNumberOfRPs(anEvent.fNumberOfRPs),
109 fMCReactionPlaneAngle(anEvent.fMCReactionPlaneAngle),
110 fMCReactionPlaneAngleIsSet(anEvent.fMCReactionPlaneAngleIsSet),
111 fAfterBurnerPrecision(anEvent.fAfterBurnerPrecision),
112 fNumberOfTracksWrap(anEvent.fNumberOfTracksWrap),
113 fNumberOfRPsWrap(anEvent.fNumberOfRPsWrap),
114 fMCReactionPlaneAngleWrap(anEvent.fMCReactionPlaneAngleWrap)
119 //-----------------------------------------------------------------------
120 AliFlowEventSimple& AliFlowEventSimple::operator=(const AliFlowEventSimple& anEvent)
122 //assignment operator
123 if (fTrackCollection) fTrackCollection->Delete();
124 delete fTrackCollection;
125 fTrackCollection = (TObjArray*)(anEvent.fTrackCollection)->Clone(); //deep copy
126 fReferenceMultiplicity = anEvent.fReferenceMultiplicity;
127 fNumberOfTracks = anEvent.fNumberOfTracks;
128 fNumberOfRPs = anEvent.fNumberOfRPs;
129 fMCReactionPlaneAngle = anEvent.fMCReactionPlaneAngle;
130 fMCReactionPlaneAngleIsSet = anEvent.fMCReactionPlaneAngleIsSet;
131 fAfterBurnerPrecision = anEvent.fAfterBurnerPrecision;
132 fNumberOfTracksWrap = anEvent.fNumberOfTracksWrap;
133 fNumberOfRPsWrap = anEvent.fNumberOfRPsWrap;
134 fMCReactionPlaneAngleWrap=anEvent.fMCReactionPlaneAngleWrap;
138 //-----------------------------------------------------------------------
139 AliFlowEventSimple::~AliFlowEventSimple()
142 if (fTrackCollection) fTrackCollection->Delete();
143 delete fTrackCollection;
144 if (fNumberOfTracksWrap) delete fNumberOfTracksWrap;
145 if (fNumberOfRPsWrap) delete fNumberOfRPsWrap;
146 if (fMCReactionPlaneAngleWrap) delete fMCReactionPlaneAngleWrap;
149 //-----------------------------------------------------------------------
150 void AliFlowEventSimple::Generate(Int_t nParticles,
157 //generate nParticles random tracks uniform in phi and eta
158 //according to the specified pt distribution
159 for (Int_t i=0; i<nParticles; i++)
161 AliFlowTrackSimple* track = new AliFlowTrackSimple();
162 track->SetPhi( gRandom->Uniform(phiMin,phiMax) );
163 track->SetEta( gRandom->Uniform(etaMin,etaMax) );
164 track->SetPt( ptDist->GetRandom() );
165 track->SetCharge( (gRandom->Uniform()-0.5<0)?-1:1 );
170 //-----------------------------------------------------------------------
171 AliFlowTrackSimple* AliFlowEventSimple::GetTrack(Int_t i)
173 //get track i from collection
174 if (i>=fNumberOfTracks) return NULL;
175 AliFlowTrackSimple* pTrack = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i)) ;
179 //-----------------------------------------------------------------------
180 void AliFlowEventSimple::AddTrack( AliFlowTrackSimple* track )
183 fTrackCollection->AddLast(track);
187 //-----------------------------------------------------------------------
188 AliFlowVector AliFlowEventSimple::GetQ(Int_t n, TList *weightsList, Bool_t usePhiWeights, Bool_t usePtWeights, Bool_t useEtaWeights)
190 // calculate Q-vector in harmonic n without weights (default harmonic n=2)
197 Double_t iUsedTracks = 0;
201 Double_t dWeight = 1.;
203 AliFlowTrackSimple* pTrack = NULL;
206 Double_t dBinWidthPt = 0.;
207 Double_t dPtMin = 0.;
208 Double_t dBinWidthEta = 0.;
209 Double_t dEtaMin = 0.;
211 Double_t wPhi = 1.; // weight Phi
212 Double_t wPt = 1.; // weight Pt
213 Double_t wEta = 1.; // weight Eta
215 TH1F *phiWeights = NULL;
216 TH1D *ptWeights = NULL;
217 TH1D *etaWeights = NULL;
223 phiWeights = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights"));
224 if(phiWeights) nBinsPhi = phiWeights->GetNbinsX();
228 ptWeights = dynamic_cast<TH1D *>(weightsList->FindObject("pt_weights"));
231 dBinWidthPt = ptWeights->GetBinWidth(1); // assuming that all bins have the same width
232 dPtMin = (ptWeights->GetXaxis())->GetXmin();
237 etaWeights = dynamic_cast<TH1D *>(weightsList->FindObject("eta_weights"));
240 dBinWidthEta = etaWeights->GetBinWidth(1); // assuming that all bins have the same width
241 dEtaMin = (etaWeights->GetXaxis())->GetXmin();
244 } // end of if(weightsList)
247 for(Int_t i=0; i<fNumberOfTracks; i++)
249 pTrack = (AliFlowTrackSimple*)fTrackCollection->At(i);
252 if(pTrack->InRPSelection())
254 dPhi = pTrack->Phi();
256 dEta = pTrack->Eta();
257 dWeight = pTrack->Weight();
259 // determine Phi weight: (to be improved, I should here only access it + the treatment of gaps in the if statement)
260 if(phiWeights && nBinsPhi)
262 wPhi = phiWeights->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*nBinsPhi/TMath::TwoPi())));
264 // determine v'(pt) weight:
265 if(ptWeights && dBinWidthPt)
267 wPt=ptWeights->GetBinContent(1+(Int_t)(TMath::Floor((dPt-dPtMin)/dBinWidthPt)));
269 // determine v'(eta) weight:
270 if(etaWeights && dBinWidthEta)
272 wEta=etaWeights->GetBinContent(1+(Int_t)(TMath::Floor((dEta-dEtaMin)/dBinWidthEta)));
275 // building up the weighted Q-vector:
276 dQX += dWeight*wPhi*wPt*wEta*TMath::Cos(iOrder*dPhi);
277 dQY += dWeight*wPhi*wPt*wEta*TMath::Sin(iOrder*dPhi);
279 // weighted multiplicity:
280 iUsedTracks += dWeight*wPhi*wPt*wEta;
282 } // end of if (pTrack->InRPSelection())
283 } // end of if (pTrack)
286 cerr << "no particle!!!"<<endl;
288 } // loop over particles
291 vQ.SetMult(iUsedTracks);
297 //-----------------------------------------------------------------------
298 void AliFlowEventSimple::Get2Qsub(AliFlowVector* Qarray, Int_t n, TList *weightsList, Bool_t usePhiWeights, Bool_t usePtWeights, Bool_t useEtaWeights)
301 // calculate Q-vector in harmonic n without weights (default harmonic n=2)
306 Double_t iUsedTracks = 0;
310 Double_t dWeight = 1.;
312 AliFlowTrackSimple* pTrack = NULL;
314 Int_t iNbinsPhiSub0 = 0;
315 Int_t iNbinsPhiSub1 = 0;
316 Double_t dBinWidthPt = 0.;
317 Double_t dPtMin = 0.;
318 Double_t dBinWidthEta= 0.;
319 Double_t dEtaMin = 0.;
321 Double_t dWphi = 1.; // weight Phi
322 Double_t dWpt = 1.; // weight Pt
323 Double_t dWeta = 1.; // weight Eta
325 TH1F* phiWeightsSub0 = NULL;
326 TH1F* phiWeightsSub1 = NULL;
327 TH1D* ptWeights = NULL;
328 TH1D* etaWeights = NULL;
334 phiWeightsSub0 = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights_sub0"));
335 phiWeightsSub1 = dynamic_cast<TH1F *>(weightsList->FindObject("phi_weights_sub1"));
337 iNbinsPhiSub0 = phiWeightsSub0->GetNbinsX();
340 iNbinsPhiSub1 = phiWeightsSub1->GetNbinsX();
345 ptWeights = dynamic_cast<TH1D *>(weightsList->FindObject("pt_weights"));
348 dBinWidthPt = ptWeights->GetBinWidth(1); // assuming that all bins have the same width
349 dPtMin = (ptWeights->GetXaxis())->GetXmin();
354 etaWeights = dynamic_cast<TH1D *>(weightsList->FindObject("eta_weights"));
357 dBinWidthEta = etaWeights->GetBinWidth(1); // assuming that all bins have the same width
358 dEtaMin = (etaWeights->GetXaxis())->GetXmin();
361 } // end of if(weightsList)
363 //loop over the two subevents
364 for (Int_t s=0; s<2; s++)
367 for(Int_t i=0; i<fNumberOfTracks; i++)
369 pTrack = (AliFlowTrackSimple*)fTrackCollection->At(i);
372 if(pTrack->InRPSelection())
374 if (pTrack->InSubevent(s))
376 dPhi = pTrack->Phi();
378 dEta = pTrack->Eta();
379 dWeight = pTrack->Weight();
381 // determine Phi weight: (to be improved, I should here only access it + the treatment of gaps in the if statement)
382 if(s == 0) { //subevent 0
383 if(phiWeightsSub0 && iNbinsPhiSub0){
384 dWphi = phiWeightsSub0->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*iNbinsPhiSub0/TMath::TwoPi())));
387 if(phiWeightsSub1 && iNbinsPhiSub1){
388 dWphi = phiWeightsSub1->GetBinContent(1+(Int_t)(TMath::Floor(dPhi*iNbinsPhiSub1/TMath::TwoPi())));
392 // determine v'(pt) weight:
393 if(ptWeights && dBinWidthPt)
395 dWpt=ptWeights->GetBinContent(1+(Int_t)(TMath::Floor((dPt-dPtMin)/dBinWidthPt)));
398 // determine v'(eta) weight:
399 if(etaWeights && dBinWidthEta)
401 dWeta=etaWeights->GetBinContent(1+(Int_t)(TMath::Floor((dEta-dEtaMin)/dBinWidthEta)));
404 // building up the weighted Q-vector:
405 dQX += dWeight*dWphi*dWpt*dWeta*TMath::Cos(iOrder*dPhi);
406 dQY += dWeight*dWphi*dWpt*dWeta*TMath::Sin(iOrder*dPhi);
408 // weighted multiplicity:
409 iUsedTracks+=dWeight*dWphi*dWpt*dWeta;
412 } // end of if (pTrack->InRPSelection())
413 } // end of if (pTrack)
416 cerr << "no particle!!!"<<endl;
418 } // loop over particles
419 Qarray[s].Set(dQX,dQY);
420 Qarray[s].SetMult(iUsedTracks);
430 //-----------------------------------------------------------------------
431 void AliFlowEventSimple::Print(Option_t *option) const
433 // -*-*-*-*-*Print some global quantities for this histogram collection class *-*-*-*-*-*-*-*
434 // ===============================================
435 // printf( "TH1.Print Name = %s, Entries= %d, Total sum= %g\n",GetName(),Int_t(fEntries),GetSumOfWeights());
436 printf( "Class.Print Name = %s, #tracks= %d, Number of RPs= %d, MC EventPlaneAngle= %f\n",
437 GetName(),fNumberOfTracks, fNumberOfRPs, fMCReactionPlaneAngle );
439 TString optionstr(option);
440 if (!optionstr.Contains("all")) return;
441 if (fTrackCollection)
443 fTrackCollection->Print(option);
447 printf( "Empty track collection \n");
451 //-----------------------------------------------------------------------
452 void AliFlowEventSimple::Browse(TBrowser *b)
455 if (!fNumberOfTracksWrap)
457 fNumberOfTracksWrap = new TParameter<int>("fNumberOfTracks", fNumberOfTracks);
458 b->Add(fNumberOfTracksWrap);
460 if (!fNumberOfRPsWrap)
462 fNumberOfRPsWrap = new TParameter<int>("fNumberOfRPs", fNumberOfRPs);
463 b->Add(fNumberOfRPsWrap);
465 if (!fMCReactionPlaneAngleWrap)
467 fMCReactionPlaneAngleWrap = new TParameter<double>(" fMCReactionPlaneAngle", fMCReactionPlaneAngle);
468 b->Add( fMCReactionPlaneAngleWrap);
470 if (fTrackCollection) b->Add(fTrackCollection,"AliFlowTracksSimple");
473 //-----------------------------------------------------------------------
474 AliFlowEventSimple::AliFlowEventSimple( TTree* inputTree,
475 const AliFlowTrackSimpleCuts* rpCuts,
476 const AliFlowTrackSimpleCuts* poiCuts):
477 fTrackCollection(NULL),
478 fReferenceMultiplicity(0),
481 fMCReactionPlaneAngle(0.),
482 fMCReactionPlaneAngleIsSet(kFALSE),
483 fAfterBurnerPrecision(0.001),
484 fNumberOfTracksWrap(NULL),
485 fNumberOfRPsWrap(NULL),
486 fMCReactionPlaneAngleWrap(NULL)
488 //constructor, fills the event from a TTree of kinematic.root files
489 //applies RP and POI cuts, tags the tracks
491 Int_t numberOfInputTracks = inputTree->GetEntries() ;
492 fTrackCollection = new TObjArray(numberOfInputTracks/2);
494 TParticle* pParticle = new TParticle();
495 inputTree->SetBranchAddress("Particles",&pParticle);
497 Int_t iSelParticlesPOI = 0;
499 for (Int_t i=0; i<numberOfInputTracks; i++)
501 inputTree->GetEntry(i); //get input particle
503 if (!pParticle) continue; //no particle
504 if (!pParticle->IsPrimary()) continue;
506 Bool_t rpOK = rpCuts->PassesCuts(pParticle);
507 Bool_t poiOK = poiCuts->PassesCuts(pParticle);
511 AliFlowTrackSimple* pTrack = new AliFlowTrackSimple(pParticle);
513 //marking the particles used for int. flow:
516 pTrack->SetForRPSelection(kTRUE);
519 //marking the particles used for diff. flow:
522 pTrack->SetForPOISelection(kTRUE);
525 //adding a particles which were used either for int. or diff. flow to the list
532 //_____________________________________________________________________________
533 void AliFlowEventSimple::CloneTracks(Int_t n)
535 //clone every track n times to add non-flow
536 if (n<=0) return; //no use to clone stuff zero or less times
537 Int_t ntracks = fNumberOfTracks;
538 fTrackCollection->Expand((n+1)*fNumberOfTracks);
539 for (Int_t i=0; i<n; i++)
541 for (Int_t itrack=0; itrack<ntracks; itrack++)
543 AliFlowTrackSimple* track = dynamic_cast<AliFlowTrackSimple*>(fTrackCollection->At(itrack));
544 if (!track) continue;
545 AddTrack(static_cast<AliFlowTrackSimple*>(track->Clone()));
550 //_____________________________________________________________________________
551 void AliFlowEventSimple::ResolutionPt(Double_t res)
553 //smear pt of all tracks by gaussian with sigma=res
554 for (Int_t i=0; i<fNumberOfTracks; i++)
556 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
557 if (track) track->ResolutionPt(res);
561 //_____________________________________________________________________________
562 void AliFlowEventSimple::TagSubeventsInEta( Double_t etaMinA,
567 //Flag two subevents in given eta ranges
568 for (Int_t i=0; i<fNumberOfTracks; i++)
570 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
571 Double_t eta=track->Eta();
572 if (eta >= etaMinA && eta <= etaMaxA) track->SetForSubevent(0);
573 if (eta >= etaMinB && eta <= etaMaxB) track->SetForSubevent(1);
577 //_____________________________________________________________________________
578 void AliFlowEventSimple::AddV1( Double_t v1 )
580 //add v2 to all tracks wrt the reaction plane angle
581 for (Int_t i=0; i<fNumberOfTracks; i++)
583 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
584 if (track) track->AddV1(v1, fMCReactionPlaneAngle, fAfterBurnerPrecision);
588 //_____________________________________________________________________________
589 void AliFlowEventSimple::AddV2( Double_t v2 )
591 //add v2 to all tracks wrt the reaction plane angle
592 for (Int_t i=0; i<fNumberOfTracks; i++)
594 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
595 if (track) track->AddV2(v2, fMCReactionPlaneAngle, fAfterBurnerPrecision);
599 //_____________________________________________________________________________
600 void AliFlowEventSimple::AddV4( Double_t v4 )
602 //add v4 to all tracks wrt the reaction plane angle
603 for (Int_t i=0; i<fNumberOfTracks; i++)
605 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
606 if (track) track->AddV4(v4, fMCReactionPlaneAngle, fAfterBurnerPrecision);
610 //_____________________________________________________________________________
611 void AliFlowEventSimple::AddFlow( Double_t v1, Double_t v2, Double_t v3, Double_t v4 )
613 //add flow to all tracks wrt the reaction plane angle
614 for (Int_t i=0; i<fNumberOfTracks; i++)
616 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
617 if (track) track->AddFlow(v1,v2,v3,v4,fMCReactionPlaneAngle, fAfterBurnerPrecision);
621 //_____________________________________________________________________________
622 void AliFlowEventSimple::TagRP( AliFlowTrackSimpleCuts* cuts )
624 //tag tracks as reference particles (RPs)
625 for (Int_t i=0; i<fNumberOfTracks; i++)
627 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
628 if (!track) continue;
629 Bool_t pass=cuts->PassesCuts(track);
630 track->SetForRPSelection(pass);
638 //_____________________________________________________________________________
639 void AliFlowEventSimple::TagPOI( AliFlowTrackSimpleCuts* cuts )
641 //tag tracks as particles of interest (POIs)
642 for (Int_t i=0; i<fNumberOfTracks; i++)
644 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
645 if (!track) continue;
646 Bool_t pass=cuts->PassesCuts(track);
647 track->SetForPOISelection(pass);
651 //_____________________________________________________________________________
652 void AliFlowEventSimple::DefineDeadZone( Double_t etaMin,
657 //mark tracks in given eta-phi region as dead
658 //by resetting the flow bits
659 for (Int_t i=0; i<fNumberOfTracks; i++)
661 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
662 Double_t eta = track->Eta();
663 Double_t phi = track->Phi();
664 if (eta>etaMin && eta<etaMax && phi>phiMin && phi<phiMax)
666 if (track->InRPSelection()) fNumberOfRPs--;
667 track->ResetFlowTags();
672 //_____________________________________________________________________________
673 Int_t AliFlowEventSimple::CleanUpDeadTracks()
675 //remove tracks that have no flow tags set and cleanup the container
676 //returns number of cleaned tracks
678 for (Int_t i=0; i<fNumberOfTracks; i++)
680 AliFlowTrackSimple* track = static_cast<AliFlowTrackSimple*>(fTrackCollection->At(i));
681 if (track->IsDead()) {delete track;ncleaned++;}
683 fTrackCollection->Compress(); //clean up empty slots