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)
58 // Dummy copy constructor
65 TParticle* AliDimuCombinator::Particle(Int_t i)
67 return gAlice->Particle(i);
70 TParticle* AliDimuCombinator::FirstMuon()
72 // Single muon iterator: initialisation
74 fMuon1 = Particle(fImuon1);
75 while(Type(fMuon1) != kMuonPlus && Type(fMuon1) != kMuonMinus) {
77 if (fImuon1 >= fImax1) {fMuon1 = 0; break;}
78 fMuon1 = Particle(fImuon1);
83 TParticle* AliDimuCombinator::FirstMuonSelected()
85 // Single selected muon iterator: initialisation
86 TParticle* muon = FirstMuon();
87 while(muon != 0 && !Selected(muon)) {muon = NextMuon();}
92 TParticle* AliDimuCombinator::NextMuon()
94 // Single muon iterator: increment
96 if (fImuon1 >= fNParticle) {fMuon1 = 0; return fMuon1;}
98 fMuon1 = Particle(fImuon1);
99 while(Type(fMuon1) != kMuonPlus && Type(fMuon1) != kMuonMinus) {
101 if (fImuon1 >= fImax1) {fMuon1 = 0; break;}
102 fMuon1 = Particle(fImuon1);
107 TParticle* AliDimuCombinator::NextMuonSelected()
109 // Single selected muon iterator: increment
110 TParticle * muon = NextMuon();
111 while(muon !=0 && !Selected(muon)) {muon = NextMuon();}
116 void AliDimuCombinator::FirstPartner()
118 // Helper for dimuon iterator: initialisation
119 if (fImin1 == fImin2) {
124 if (fImuon2 >= fImax2) {fMuon2 = 0; return;}
125 fMuon2 = Particle(fImuon2);
126 while(Type(fMuon2) != kMuonPlus && Type(fMuon2) != kMuonMinus) {
128 if (fImuon2 >= fImax2) {fMuon2 = 0; break;}
129 fMuon2 = Particle(fImuon2);
133 void AliDimuCombinator::FirstPartnerSelected()
135 // Helper for selected dimuon iterator: initialisation
137 while(fMuon2 !=0 && !Selected(fMuon2)) {NextPartner();}
141 void AliDimuCombinator::NextPartner()
143 // Helper for dimuon iterator: increment
145 if (fImuon2 >= fImax2) {fMuon2 = 0; return;}
148 fMuon2 = Particle(fImuon2);
150 while(Type(fMuon2) != kMuonPlus && Type(fMuon2) != kMuonMinus) {
152 if (fImuon2 >= fImax2) {fMuon2 = 0; break;}
153 fMuon2 = Particle(fImuon2);
157 void AliDimuCombinator::NextPartnerSelected()
159 // Helper for selected dimuon iterator: increment
161 while(fMuon2 !=0 && !Selected(fMuon2)) {NextPartner();}
165 TParticle* AliDimuCombinator::Partner()
167 // Returns current partner for muon to form a dimuon
171 void AliDimuCombinator::FirstMuonPair(TParticle* & muon1, TParticle* & muon2)
173 // Dimuon iterator: initialisation
180 void AliDimuCombinator::NextMuonPair(TParticle* & muon1, TParticle* & muon2)
182 // Dimuon iterator: increment
191 void AliDimuCombinator::FirstMuonPairSelected(TParticle* & muon1,
194 // Selected dimuon iterator: initialisation
196 FirstPartnerSelected();
201 void AliDimuCombinator::NextMuonPairSelected(TParticle* & muon1,
204 // Selected dimuon iterator: increment
205 NextPartnerSelected();
208 FirstPartnerSelected();
214 void AliDimuCombinator::ResetRange()
216 // Reset index ranges for single muons
218 fImax1 = fImax2 = fNParticle;
221 void AliDimuCombinator::SetFirstRange(Int_t from, Int_t to)
223 // Reset index range for first muon
226 if (fImax1 > fNParticle) fImax1 = fNParticle;
229 void AliDimuCombinator::SetSecondRange(Int_t from, Int_t to)
231 // Reset index range for second muon
234 if (fImax2 > fNParticle) fImax2 = fNParticle;
240 Bool_t AliDimuCombinator::Selected(TParticle* part)
242 // Selection cut for single muon
244 if (part == 0) {return 0;}
246 if (part->Pt() > fPtMin && part->Eta() > fEtaMin && part->Eta() < fEtaMax) {
253 Bool_t AliDimuCombinator::Selected(TParticle* part1, TParticle* part2)
255 // Selection cut for dimuons
257 return Selected(part1)*Selected(part2);
262 Float_t AliDimuCombinator::Mass(TParticle* part1, TParticle* part2)
267 px = part1->Px()+part2->Px();
268 py = part1->Py()+part2->Py();
269 pz = part1->Pz()+part2->Pz();
270 e = part1->Energy()+part2->Energy();
271 Float_t p = px*px+py*py+pz*pz;
275 return TMath::Sqrt(e*e-p);
279 Float_t AliDimuCombinator::PT(TParticle* part1, TParticle* part2)
281 // Transverse momentum of dimuons
284 px = part1->Px()+part2->Px();
285 py = part1->Py()+part2->Py();
286 return TMath::Sqrt(px*px+py*py);
289 Float_t AliDimuCombinator::Pz(TParticle* part1, TParticle* part2)
291 // Pz of dimuon system
293 return part1->Pz()+part2->Pz();
296 Float_t AliDimuCombinator::Y(TParticle* part1, TParticle* part2)
298 // Rapidity of dimuon system
301 pz = part1->Pz()+part2->Pz();
302 e = part1->Energy()+part2->Energy();
303 return 0.5*TMath::Log((e+pz)/(e-pz));
307 void AliDimuCombinator::SmearGauss(Float_t width, Float_t & value)
309 // Apply gaussian smearing
311 value+=gRandom->Gaus(0, width);
316 Float_t AliDimuCombinator::DecayProbability(TParticle* part)
318 // Calculate decay probability for muons from pion and kaon decays
321 Float_t d, h, theta, cTau;
322 TParticle* parent = Parent(part);
323 Int_t ipar = Type(parent);
324 if (ipar == kPiPlus || ipar == kPiMinus) {
326 } else if (ipar == kKPlus || ipar == kKMinus) {
333 Float_t gammaBeta=(parent->P())/(parent->GetMass());
335 // this part is still very ALICE muon-arm specific
339 theta = parent->Theta();
340 h = 90*TMath::Tan(theta);
343 d=4/TMath::Sin(theta);
345 d=90/TMath::Cos(theta);
349 return 1-TMath::Exp(-d/cTau/gammaBeta);
357 <p> In the the code above :
358 <P>If h is less than 4 cm, pions or kaons go in the beam pipe and can have a long way
359 <BR>If h is greater than 4 cm, pions or kaons crash into the front absorber
360 <P><IMG SRC="absorbeur.jpg" HEIGHT=292 WIDTH=819>
365 Float_t AliDimuCombinator::Weight(TParticle* part1, TParticle* part2)
369 Float_t wgt = (part1->GetWeight())*(part2->GetWeight());
371 if (Correlated(part1, part2)) {
372 if ( part1->GetFirstMother() == part2->GetFirstMother()) {
373 return part1->GetWeight()*fRate1;
375 return wgt/(Parent(part1)->GetWeight())*fRate1;
378 return wgt*fRate1*fRate2;
384 <p>Some clarifications on the calculation of the dimuons weight :
385 <P>We must keep in mind that if we force the meson decay in muons and we put
386 lot of mesons (J/psi, upsilon, ...) to have a good statistic we are
387 obliged to calculate different weights to correct the number
391 <BR>The particle weight is given by w=R*M*Br
392 <BR> with :
393 <UL>R = the rate by event. This number gives the number
394 of produced J/psi, upsilon, pion ... in a collision.
395 <BR>It corresponds of the weight 0.06 given for example in gener->AddGenerator(jpsi,"J/Psi",
396 0.06); from the config.C macro.
397 <BR>In this example R=0.06
399 <P>M = the rate of the mother production. This number depend on :
400 <BR> - the number of generated events --> fParentWeight=1./Float_t(fNpart) in AliGenPythia.cxx . This
401 is a normalization to 1 of the number of generated particles.
402 <BR> - the kinematic bias coming
403 from the y and Pt cuts. Method AliGenPythia::AdjustWeights() in AliGenPythia.cxx
404 <BR>(in AliGenParam.cxx this 2 things are taken into account in fParentWeight
405 = fYWgt*fPtWgt*phiWgt/fNpart )
407 <P>Br = the branching ratio in muon from the mother decay</UL>
409 <P><BR>In this method, part->GetWeight() = M*Br
412 <BR>The weight of the dimuon depends on the correlation between muons
414 <UL>If the muons are correlated and come from a resonance (for example
415 J/psi -> mu+ mu-) , the weight of the dimuon is the weight of one muon then
416 <BR>w12= R*M*Br = w1* R1 (in this method this gives part1->GetWeight()*fRate1)
418 <P>If the muons are correlated and come from a charm or a bottom pair then
419 w12 = M*R*Br1*Br2 = w1*w2*R1/M1
420 <BR>(in this method this gives wgt/(Parent(part1)->GetWeight())*fRate1).
421 Indeed the 2 muons come from the same mother so the
422 <BR>weight of a DD~ or BB~ is M*Br and they are no correlation in the decay
425 <P>If the muons are not correlated w12 = M1*M2*R1*R2*Br1*Br2 = w1*w2*R1*R2
426 (in this method this gives wgt*fRate1*fRate2)
432 Float_t AliDimuCombinator::Weight(TParticle* part)
434 // Single muon weight
435 return (part->GetWeight())*(Parent(part)->GetWeight())*fRate1;
438 Bool_t AliDimuCombinator::Correlated(TParticle* part1, TParticle* part2)
440 // Check if muons are correlated
442 if ((Origin(part1) >= 0) && Origin(part1) == Origin(part2)) {
444 printf("\n origin %d %d ",
445 Type(Particle(Origin(part1))),
446 Type(Particle(Origin(part2))));
447 printf("\n parent %d %d \n \n ",
449 Type(Parent(part2)));
457 TParticle* AliDimuCombinator::Parent(TParticle* part)
459 // Return pointer to parent
461 return Particle(part->GetFirstMother());
464 Int_t AliDimuCombinator::Origin(TParticle* part)
466 // Return pointer to primary particle
468 Int_t iparent= part->GetFirstMother();
469 if (iparent < 0) return iparent;
472 ip = (Particle(iparent))->GetFirstMother();
482 Int_t AliDimuCombinator::Type(TParticle *part)
484 // Return particle type for
485 return part->GetPdgCode();
488 AliDimuCombinator& AliDimuCombinator::operator=(const AliDimuCombinator& rhs)
490 // Assignment operator
495 void AliDimuCombinator::Copy(AliDimuCombinator &combi) const
498 // Copy *this onto lego -- not implemented
500 Fatal("Copy","Not implemented!\n");