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"
37 ClassImp(AliDimuCombinator)
38 AliDimuCombinator::AliDimuCombinator()
41 fNParticle = (Int_t) (gAlice->TreeK())->GetEntries();
57 AliDimuCombinator::AliDimuCombinator(const AliDimuCombinator & combinator)
60 // Dummy copy constructor
61 combinator.Copy(*this);
68 TParticle* AliDimuCombinator::Particle(Int_t i)
70 return gAlice->GetMCApp()->Particle(i);
73 TParticle* AliDimuCombinator::FirstMuon()
75 // Single muon iterator: initialisation
77 fMuon1 = Particle(fImuon1);
78 while(Type(fMuon1) != kMuonPlus && Type(fMuon1) != kMuonMinus) {
80 if (fImuon1 >= fImax1) {fMuon1 = 0; break;}
81 fMuon1 = Particle(fImuon1);
86 TParticle* AliDimuCombinator::FirstMuonSelected()
88 // Single selected muon iterator: initialisation
89 TParticle* muon = FirstMuon();
90 while(muon != 0 && !Selected(muon)) {muon = NextMuon();}
95 TParticle* AliDimuCombinator::NextMuon()
97 // Single muon iterator: increment
99 if (fImuon1 >= fNParticle) {fMuon1 = 0; return fMuon1;}
101 fMuon1 = Particle(fImuon1);
102 while(Type(fMuon1) != kMuonPlus && Type(fMuon1) != kMuonMinus) {
104 if (fImuon1 >= fImax1) {fMuon1 = 0; break;}
105 fMuon1 = Particle(fImuon1);
110 TParticle* AliDimuCombinator::NextMuonSelected()
112 // Single selected muon iterator: increment
113 TParticle * muon = NextMuon();
114 while(muon !=0 && !Selected(muon)) {muon = NextMuon();}
119 void AliDimuCombinator::FirstPartner()
121 // Helper for dimuon iterator: initialisation
122 if (fImin1 == fImin2) {
127 if (fImuon2 >= fImax2) {fMuon2 = 0; return;}
128 fMuon2 = Particle(fImuon2);
129 while(Type(fMuon2) != kMuonPlus && Type(fMuon2) != kMuonMinus) {
131 if (fImuon2 >= fImax2) {fMuon2 = 0; break;}
132 fMuon2 = Particle(fImuon2);
136 void AliDimuCombinator::FirstPartnerSelected()
138 // Helper for selected dimuon iterator: initialisation
140 while(fMuon2 !=0 && !Selected(fMuon2)) {NextPartner();}
144 void AliDimuCombinator::NextPartner()
146 // Helper for dimuon iterator: increment
148 if (fImuon2 >= fImax2) {fMuon2 = 0; return;}
151 fMuon2 = Particle(fImuon2);
153 while(Type(fMuon2) != kMuonPlus && Type(fMuon2) != kMuonMinus) {
155 if (fImuon2 >= fImax2) {fMuon2 = 0; break;}
156 fMuon2 = Particle(fImuon2);
160 void AliDimuCombinator::NextPartnerSelected()
162 // Helper for selected dimuon iterator: increment
164 while(fMuon2 !=0 && !Selected(fMuon2)) {NextPartner();}
168 TParticle* AliDimuCombinator::Partner()
170 // Returns current partner for muon to form a dimuon
174 void AliDimuCombinator::FirstMuonPair(TParticle* & muon1, TParticle* & muon2)
176 // Dimuon iterator: initialisation
183 void AliDimuCombinator::NextMuonPair(TParticle* & muon1, TParticle* & muon2)
185 // Dimuon iterator: increment
194 void AliDimuCombinator::FirstMuonPairSelected(TParticle* & muon1,
197 // Selected dimuon iterator: initialisation
199 FirstPartnerSelected();
204 void AliDimuCombinator::NextMuonPairSelected(TParticle* & muon1,
207 // Selected dimuon iterator: increment
208 NextPartnerSelected();
211 FirstPartnerSelected();
217 void AliDimuCombinator::ResetRange()
219 // Reset index ranges for single muons
221 fImax1 = fImax2 = fNParticle;
224 void AliDimuCombinator::SetFirstRange(Int_t from, Int_t to)
226 // Reset index range for first muon
229 if (fImax1 > fNParticle) fImax1 = fNParticle;
232 void AliDimuCombinator::SetSecondRange(Int_t from, Int_t to)
234 // Reset index range for second muon
237 if (fImax2 > fNParticle) fImax2 = fNParticle;
243 Bool_t AliDimuCombinator::Selected(TParticle* part)
245 // Selection cut for single muon
247 if (part == 0) {return 0;}
249 if (part->Pt() > fPtMin && part->Eta() > fEtaMin && part->Eta() < fEtaMax) {
256 Bool_t AliDimuCombinator::Selected(TParticle* part1, TParticle* part2)
258 // Selection cut for dimuons
260 return Selected(part1)*Selected(part2);
265 Float_t AliDimuCombinator::Mass(TParticle* part1, TParticle* part2)
270 px = part1->Px()+part2->Px();
271 py = part1->Py()+part2->Py();
272 pz = part1->Pz()+part2->Pz();
273 e = part1->Energy()+part2->Energy();
274 Float_t p = px*px+py*py+pz*pz;
278 return TMath::Sqrt(e*e-p);
282 Float_t AliDimuCombinator::PT(TParticle* part1, TParticle* part2)
284 // Transverse momentum of dimuons
287 px = part1->Px()+part2->Px();
288 py = part1->Py()+part2->Py();
289 return TMath::Sqrt(px*px+py*py);
292 Float_t AliDimuCombinator::Pz(TParticle* part1, TParticle* part2)
294 // Pz of dimuon system
296 return part1->Pz()+part2->Pz();
299 Float_t AliDimuCombinator::Y(TParticle* part1, TParticle* part2)
301 // Rapidity of dimuon system
304 pz = part1->Pz()+part2->Pz();
305 e = part1->Energy()+part2->Energy();
306 return 0.5*TMath::Log((e+pz)/(e-pz));
310 void AliDimuCombinator::SmearGauss(Float_t width, Float_t & value)
312 // Apply gaussian smearing
314 value+=gRandom->Gaus(0, width);
319 Float_t AliDimuCombinator::DecayProbability(TParticle* part)
321 // Calculate decay probability for muons from pion and kaon decays
324 Float_t d, h, theta, cTau;
325 TParticle* parent = Parent(part);
326 Int_t ipar = Type(parent);
327 if (ipar == kPiPlus || ipar == kPiMinus) {
329 } else if (ipar == kKPlus || ipar == kKMinus) {
336 Float_t gammaBeta=(parent->P())/(parent->GetMass());
338 // this part is still very ALICE muon-arm specific
342 theta = parent->Theta();
343 h = 90*TMath::Tan(theta);
346 d=4/TMath::Sin(theta);
348 d=90/TMath::Cos(theta);
352 return 1-TMath::Exp(-d/cTau/gammaBeta);
360 <p> In the the code above :
361 <P>If h is less than 4 cm, pions or kaons go in the beam pipe and can have a long way
362 <BR>If h is greater than 4 cm, pions or kaons crash into the front absorber
363 <P><IMG SRC="absorbeur.jpg" HEIGHT=292 WIDTH=819>
368 Float_t AliDimuCombinator::Weight(TParticle* part1, TParticle* part2)
372 Float_t wgt = (part1->GetWeight())*(part2->GetWeight());
374 if (Correlated(part1, part2)) {
375 if ( part1->GetFirstMother() == part2->GetFirstMother()) {
376 return part1->GetWeight()*fRate1;
378 return wgt/(Parent(part1)->GetWeight())*fRate1;
381 return wgt*fRate1*fRate2;
387 <p>Some clarifications on the calculation of the dimuons weight :
388 <P>We must keep in mind that if we force the meson decay in muons and we put
389 lot of mesons (J/psi, upsilon, ...) to have a good statistic we are
390 obliged to calculate different weights to correct the number
394 <BR>The particle weight is given by w=R*M*Br
395 <BR> with :
396 <UL>R = the rate by event. This number gives the number
397 of produced J/psi, upsilon, pion ... in a collision.
398 <BR>It corresponds of the weight 0.06 given for example in gener->AddGenerator(jpsi,"J/Psi",
399 0.06); from the config.C macro.
400 <BR>In this example R=0.06
402 <P>M = the rate of the mother production. This number depend on :
403 <BR> - the number of generated events --> fParentWeight=1./Float_t(fNpart) in AliGenPythia.cxx . This
404 is a normalization to 1 of the number of generated particles.
405 <BR> - the kinematic bias coming
406 from the y and Pt cuts. Method AliGenPythia::AdjustWeights() in AliGenPythia.cxx
407 <BR>(in AliGenParam.cxx this 2 things are taken into account in fParentWeight
408 = fYWgt*fPtWgt*phiWgt/fNpart )
410 <P>Br = the branching ratio in muon from the mother decay</UL>
412 <P><BR>In this method, part->GetWeight() = M*Br
415 <BR>The weight of the dimuon depends on the correlation between muons
417 <UL>If the muons are correlated and come from a resonance (for example
418 J/psi -> mu+ mu-) , the weight of the dimuon is the weight of one muon then
419 <BR>w12= R*M*Br = w1* R1 (in this method this gives part1->GetWeight()*fRate1)
421 <P>If the muons are correlated and come from a charm or a bottom pair then
422 w12 = M*R*Br1*Br2 = w1*w2*R1/M1
423 <BR>(in this method this gives wgt/(Parent(part1)->GetWeight())*fRate1).
424 Indeed the 2 muons come from the same mother so the
425 <BR>weight of a DD~ or BB~ is M*Br and they are no correlation in the decay
428 <P>If the muons are not correlated w12 = M1*M2*R1*R2*Br1*Br2 = w1*w2*R1*R2
429 (in this method this gives wgt*fRate1*fRate2)
435 Float_t AliDimuCombinator::Weight(TParticle* part)
437 // Single muon weight
438 return (part->GetWeight())*(Parent(part)->GetWeight())*fRate1;
441 Bool_t AliDimuCombinator::Correlated(TParticle* part1, TParticle* part2)
443 // Check if muons are correlated
445 if ((Origin(part1) >= 0) && Origin(part1) == Origin(part2)) {
447 printf("\n origin %d %d ",
448 Type(Particle(Origin(part1))),
449 Type(Particle(Origin(part2))));
450 printf("\n parent %d %d \n \n ",
452 Type(Parent(part2)));
460 TParticle* AliDimuCombinator::Parent(TParticle* part)
462 // Return pointer to parent
464 return Particle(part->GetFirstMother());
467 Int_t AliDimuCombinator::Origin(TParticle* part)
469 // Return pointer to primary particle
471 Int_t iparent= part->GetFirstMother();
472 if (iparent < 0) return iparent;
475 ip = (Particle(iparent))->GetFirstMother();
485 Int_t AliDimuCombinator::Type(TParticle *part)
487 // Return particle type for
488 return part->GetPdgCode();
491 AliDimuCombinator& AliDimuCombinator::operator=(const AliDimuCombinator& rhs)
493 // Assignment operator
499 void AliDimuCombinator::Copy(AliDimuCombinator&) const
504 Fatal("Copy","Not implemented!\n");