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 **************************************************************************/
19 Class for dimuon analysis and fast dimuon simulation.
20 It provides single and dimuon iterators, cuts, weighting, kinematic
21 It uses the AliRun particle tree.
22 Comments and suggestions to
23 andreas.morsch@cern.ch
26 #include <TClonesArray.h>
27 #include <TParticle.h>
32 #include "AliDimuCombinator.h"
36 ClassImp(AliDimuCombinator)
37 AliDimuCombinator::AliDimuCombinator()
40 fNParticle = (Int_t) (gAlice->TreeK())->GetEntries();
56 AliDimuCombinator::AliDimuCombinator(const AliDimuCombinator & combinator)
59 // Dummy copy constructor
60 combinator.Copy(*this);
67 TParticle* AliDimuCombinator::Particle(Int_t i)
69 return gAlice->Particle(i);
72 TParticle* AliDimuCombinator::FirstMuon()
74 // Single muon iterator: initialisation
76 fMuon1 = Particle(fImuon1);
77 while(Type(fMuon1) != kMuonPlus && Type(fMuon1) != kMuonMinus) {
79 if (fImuon1 >= fImax1) {fMuon1 = 0; break;}
80 fMuon1 = Particle(fImuon1);
85 TParticle* AliDimuCombinator::FirstMuonSelected()
87 // Single selected muon iterator: initialisation
88 TParticle* muon = FirstMuon();
89 while(muon != 0 && !Selected(muon)) {muon = NextMuon();}
94 TParticle* AliDimuCombinator::NextMuon()
96 // Single muon iterator: increment
98 if (fImuon1 >= fNParticle) {fMuon1 = 0; return fMuon1;}
100 fMuon1 = Particle(fImuon1);
101 while(Type(fMuon1) != kMuonPlus && Type(fMuon1) != kMuonMinus) {
103 if (fImuon1 >= fImax1) {fMuon1 = 0; break;}
104 fMuon1 = Particle(fImuon1);
109 TParticle* AliDimuCombinator::NextMuonSelected()
111 // Single selected muon iterator: increment
112 TParticle * muon = NextMuon();
113 while(muon !=0 && !Selected(muon)) {muon = NextMuon();}
118 void AliDimuCombinator::FirstPartner()
120 // Helper for dimuon iterator: initialisation
121 if (fImin1 == fImin2) {
126 if (fImuon2 >= fImax2) {fMuon2 = 0; return;}
127 fMuon2 = Particle(fImuon2);
128 while(Type(fMuon2) != kMuonPlus && Type(fMuon2) != kMuonMinus) {
130 if (fImuon2 >= fImax2) {fMuon2 = 0; break;}
131 fMuon2 = Particle(fImuon2);
135 void AliDimuCombinator::FirstPartnerSelected()
137 // Helper for selected dimuon iterator: initialisation
139 while(fMuon2 !=0 && !Selected(fMuon2)) {NextPartner();}
143 void AliDimuCombinator::NextPartner()
145 // Helper for dimuon iterator: increment
147 if (fImuon2 >= fImax2) {fMuon2 = 0; return;}
150 fMuon2 = Particle(fImuon2);
152 while(Type(fMuon2) != kMuonPlus && Type(fMuon2) != kMuonMinus) {
154 if (fImuon2 >= fImax2) {fMuon2 = 0; break;}
155 fMuon2 = Particle(fImuon2);
159 void AliDimuCombinator::NextPartnerSelected()
161 // Helper for selected dimuon iterator: increment
163 while(fMuon2 !=0 && !Selected(fMuon2)) {NextPartner();}
167 TParticle* AliDimuCombinator::Partner()
169 // Returns current partner for muon to form a dimuon
173 void AliDimuCombinator::FirstMuonPair(TParticle* & muon1, TParticle* & muon2)
175 // Dimuon iterator: initialisation
182 void AliDimuCombinator::NextMuonPair(TParticle* & muon1, TParticle* & muon2)
184 // Dimuon iterator: increment
193 void AliDimuCombinator::FirstMuonPairSelected(TParticle* & muon1,
196 // Selected dimuon iterator: initialisation
198 FirstPartnerSelected();
203 void AliDimuCombinator::NextMuonPairSelected(TParticle* & muon1,
206 // Selected dimuon iterator: increment
207 NextPartnerSelected();
210 FirstPartnerSelected();
216 void AliDimuCombinator::ResetRange()
218 // Reset index ranges for single muons
220 fImax1 = fImax2 = fNParticle;
223 void AliDimuCombinator::SetFirstRange(Int_t from, Int_t to)
225 // Reset index range for first muon
228 if (fImax1 > fNParticle) fImax1 = fNParticle;
231 void AliDimuCombinator::SetSecondRange(Int_t from, Int_t to)
233 // Reset index range for second muon
236 if (fImax2 > fNParticle) fImax2 = fNParticle;
242 Bool_t AliDimuCombinator::Selected(TParticle* part)
244 // Selection cut for single muon
246 if (part == 0) {return 0;}
248 if (part->Pt() > fPtMin && part->Eta() > fEtaMin && part->Eta() < fEtaMax) {
255 Bool_t AliDimuCombinator::Selected(TParticle* part1, TParticle* part2)
257 // Selection cut for dimuons
259 return Selected(part1)*Selected(part2);
264 Float_t AliDimuCombinator::Mass(TParticle* part1, TParticle* part2)
269 px = part1->Px()+part2->Px();
270 py = part1->Py()+part2->Py();
271 pz = part1->Pz()+part2->Pz();
272 e = part1->Energy()+part2->Energy();
273 Float_t p = px*px+py*py+pz*pz;
277 return TMath::Sqrt(e*e-p);
281 Float_t AliDimuCombinator::PT(TParticle* part1, TParticle* part2)
283 // Transverse momentum of dimuons
286 px = part1->Px()+part2->Px();
287 py = part1->Py()+part2->Py();
288 return TMath::Sqrt(px*px+py*py);
291 Float_t AliDimuCombinator::Pz(TParticle* part1, TParticle* part2)
293 // Pz of dimuon system
295 return part1->Pz()+part2->Pz();
298 Float_t AliDimuCombinator::Y(TParticle* part1, TParticle* part2)
300 // Rapidity of dimuon system
303 pz = part1->Pz()+part2->Pz();
304 e = part1->Energy()+part2->Energy();
305 return 0.5*TMath::Log((e+pz)/(e-pz));
309 void AliDimuCombinator::SmearGauss(Float_t width, Float_t & value)
311 // Apply gaussian smearing
313 value+=gRandom->Gaus(0, width);
318 Float_t AliDimuCombinator::DecayProbability(TParticle* part)
320 // Calculate decay probability for muons from pion and kaon decays
323 Float_t d, h, theta, cTau;
324 TParticle* parent = Parent(part);
325 Int_t ipar = Type(parent);
326 if (ipar == kPiPlus || ipar == kPiMinus) {
328 } else if (ipar == kKPlus || ipar == kKMinus) {
335 Float_t gammaBeta=(parent->P())/(parent->GetMass());
337 // this part is still very ALICE muon-arm specific
341 theta = parent->Theta();
342 h = 90*TMath::Tan(theta);
345 d=4/TMath::Sin(theta);
347 d=90/TMath::Cos(theta);
351 return 1-TMath::Exp(-d/cTau/gammaBeta);
359 <p> In the the code above :
360 <P>If h is less than 4 cm, pions or kaons go in the beam pipe and can have a long way
361 <BR>If h is greater than 4 cm, pions or kaons crash into the front absorber
362 <P><IMG SRC="absorbeur.jpg" HEIGHT=292 WIDTH=819>
367 Float_t AliDimuCombinator::Weight(TParticle* part1, TParticle* part2)
371 Float_t wgt = (part1->GetWeight())*(part2->GetWeight());
373 if (Correlated(part1, part2)) {
374 if ( part1->GetFirstMother() == part2->GetFirstMother()) {
375 return part1->GetWeight()*fRate1;
377 return wgt/(Parent(part1)->GetWeight())*fRate1;
380 return wgt*fRate1*fRate2;
386 <p>Some clarifications on the calculation of the dimuons weight :
387 <P>We must keep in mind that if we force the meson decay in muons and we put
388 lot of mesons (J/psi, upsilon, ...) to have a good statistic we are
389 obliged to calculate different weights to correct the number
393 <BR>The particle weight is given by w=R*M*Br
394 <BR> with :
395 <UL>R = the rate by event. This number gives the number
396 of produced J/psi, upsilon, pion ... in a collision.
397 <BR>It corresponds of the weight 0.06 given for example in gener->AddGenerator(jpsi,"J/Psi",
398 0.06); from the config.C macro.
399 <BR>In this example R=0.06
401 <P>M = the rate of the mother production. This number depend on :
402 <BR> - the number of generated events --> fParentWeight=1./Float_t(fNpart) in AliGenPythia.cxx . This
403 is a normalization to 1 of the number of generated particles.
404 <BR> - the kinematic bias coming
405 from the y and Pt cuts. Method AliGenPythia::AdjustWeights() in AliGenPythia.cxx
406 <BR>(in AliGenParam.cxx this 2 things are taken into account in fParentWeight
407 = fYWgt*fPtWgt*phiWgt/fNpart )
409 <P>Br = the branching ratio in muon from the mother decay</UL>
411 <P><BR>In this method, part->GetWeight() = M*Br
414 <BR>The weight of the dimuon depends on the correlation between muons
416 <UL>If the muons are correlated and come from a resonance (for example
417 J/psi -> mu+ mu-) , the weight of the dimuon is the weight of one muon then
418 <BR>w12= R*M*Br = w1* R1 (in this method this gives part1->GetWeight()*fRate1)
420 <P>If the muons are correlated and come from a charm or a bottom pair then
421 w12 = M*R*Br1*Br2 = w1*w2*R1/M1
422 <BR>(in this method this gives wgt/(Parent(part1)->GetWeight())*fRate1).
423 Indeed the 2 muons come from the same mother so the
424 <BR>weight of a DD~ or BB~ is M*Br and they are no correlation in the decay
427 <P>If the muons are not correlated w12 = M1*M2*R1*R2*Br1*Br2 = w1*w2*R1*R2
428 (in this method this gives wgt*fRate1*fRate2)
434 Float_t AliDimuCombinator::Weight(TParticle* part)
436 // Single muon weight
437 return (part->GetWeight())*(Parent(part)->GetWeight())*fRate1;
440 Bool_t AliDimuCombinator::Correlated(TParticle* part1, TParticle* part2)
442 // Check if muons are correlated
444 if ((Origin(part1) >= 0) && Origin(part1) == Origin(part2)) {
446 printf("\n origin %d %d ",
447 Type(Particle(Origin(part1))),
448 Type(Particle(Origin(part2))));
449 printf("\n parent %d %d \n \n ",
451 Type(Parent(part2)));
459 TParticle* AliDimuCombinator::Parent(TParticle* part)
461 // Return pointer to parent
463 return Particle(part->GetFirstMother());
466 Int_t AliDimuCombinator::Origin(TParticle* part)
468 // Return pointer to primary particle
470 Int_t iparent= part->GetFirstMother();
471 if (iparent < 0) return iparent;
474 ip = (Particle(iparent))->GetFirstMother();
484 Int_t AliDimuCombinator::Type(TParticle *part)
486 // Return particle type for
487 return part->GetPdgCode();
490 AliDimuCombinator& AliDimuCombinator::operator=(const AliDimuCombinator& rhs)
492 // Assignment operator
498 void AliDimuCombinator::Copy(AliDimuCombinator&) const
503 Fatal("Copy","Not implemented!\n");