]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrackLight.cxx
Coding rule violations fixed.
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackLight.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *      SigmaEffect_thetadegrees                                          *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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 purpeateose. It is      *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 //-----------------------------------------------------------------------------
19 // Compact information for the muon generated tracks in the MUON arm 
20 // useful at the last stage of the analysis chain
21 // provides a link between the reconstructed track and the generated particle 
22 // stores kinematical information at gen. and rec. level and 
23 // the decay history of the muon, allowing the identification of the 
24 // mother process 
25 // 
26 // To be used together with AliMUONPairLight
27 //
28 // This class was prepared by INFN Cagliari, July 2006
29 // (authors: H.Woehri, A.de Falco)
30 //-----------------------------------------------------------------------------
31
32 // 13 Nov 2007:
33 // Added a temporary fix to FindRefTrack to be able to handle reconstructed tracks
34 // generated from ESD muon track information. The problem is that the ESD data at
35 // the moment only contains the first hit on chamber 1. Hopefully in the near future
36 // this will be fixed and all hit information will be available.
37 //  - Artur Szostak <artursz@iafrica.com>
38
39 #include "AliMUONTrackLight.h"
40 #include "AliMUONTrack.h"
41 #include "AliMUONConstants.h"
42 #include "AliMUONVTrackStore.h"
43 #include "AliMUONTrackExtrap.h"
44
45 #include "AliESDMuonTrack.h"
46 #include "AliRunLoader.h"
47 #include "AliStack.h"
48 #include "AliHeader.h"
49
50 #include "TDatabasePDG.h"
51 #include "TParticle.h"
52 #include "TString.h"
53
54 ClassImp(AliMUONTrackLight) 
55
56 //===================================================================
57
58 AliMUONTrackLight::AliMUONTrackLight() 
59   : TObject(), 
60     fPrec(), 
61     fIsTriggered(kFALSE),
62     fCharge(-999), 
63     fChi2(-1), 
64     fCentr(-1),
65     fPgen(), 
66     fTrackPythiaLine(-999),
67     fTrackPDGCode(-999),
68     fOscillation(kFALSE), 
69     fNParents(0),
70     fWeight(1)    
71 {
72   /// default constructor
73   fPgen.SetPxPyPzE(0.,0.,0.,0.); 
74   fPrec.SetPxPyPzE(0.,0.,0.,0.); 
75   for (Int_t i=0; i<3; i++) fXYZ[i]=-999; 
76   for (Int_t npar = 0; npar < fgkNParentsMax; npar++){
77     fParentPDGCode[npar] = -1; 
78     fParentPythiaLine[npar] = -1;
79   }
80   for (Int_t i = 0; i < 4; i++){
81     fQuarkPDGCode[i] = -1; 
82     fQuarkPythiaLine[i] = -1; 
83   }
84 }
85
86 //============================================
87 AliMUONTrackLight::AliMUONTrackLight(const AliMUONTrackLight &muonCopy) 
88   : TObject(muonCopy), 
89     fPrec(muonCopy.fPrec), 
90     fIsTriggered(muonCopy.fIsTriggered),
91     fCharge(muonCopy.fCharge), 
92     fChi2(muonCopy.fChi2), 
93     fCentr(muonCopy.fCentr),
94     fPgen(muonCopy.fPgen), 
95     fTrackPythiaLine(muonCopy.fTrackPythiaLine),
96     fTrackPDGCode(muonCopy.fTrackPDGCode),
97     fOscillation(muonCopy.fOscillation), 
98     fNParents(muonCopy.fNParents),
99     fWeight(muonCopy.fWeight)
100 {
101   /// copy constructor
102   for (Int_t i=0; i<3; i++) fXYZ[i]=muonCopy.fXYZ[i]; 
103   for (Int_t npar = 0; npar < fgkNParentsMax; npar++){
104     fParentPDGCode[npar] = muonCopy.fParentPDGCode[npar]; 
105     fParentPythiaLine[npar] = muonCopy.fParentPythiaLine[npar];
106   }
107   for (Int_t i = 0; i < 4; i++){
108     fQuarkPDGCode[i] = muonCopy.fQuarkPDGCode[i]; 
109     fQuarkPythiaLine[i] = muonCopy.fQuarkPythiaLine[i]; 
110   }
111 }
112
113 //============================================
114 AliMUONTrackLight::AliMUONTrackLight(AliESDMuonTrack* muonTrack)
115   : TObject(), 
116     fPrec(), 
117     fIsTriggered(kFALSE),
118     fCharge(-999), 
119     fChi2(-1),
120     fCentr(-1),
121     fPgen(), 
122     fTrackPythiaLine(-999),
123     fTrackPDGCode(-999),
124     fOscillation(kFALSE), 
125     fNParents(0),
126     fWeight(1)
127
128   /// constructor
129   //AliMUONTrackLight(); 
130   FillFromESD(muonTrack); 
131 }
132
133 //============================================
134 AliMUONTrackLight::~AliMUONTrackLight()
135 {
136 /// Destructor
137
138
139 //============================================
140
141 void AliMUONTrackLight::FillFromAliMUONTrack(AliMUONTrack *trackReco,Double_t zvert){
142   /// this method sets the muon reconstructed momentum according to the value given by AliMUONTrack
143   AliMUONTrackParam trPar;
144   if (trackReco->GetTrackParamAtVertex()) trPar = *(trackReco->GetTrackParamAtVertex());
145   else {
146     trPar = *((AliMUONTrackParam*) trackReco->GetTrackParamAtCluster()->First());
147     AliMUONTrackExtrap::ExtrapToVertex(&trPar,0.,0.,0.,0.,0.);
148   }
149   this->SetCharge(Int_t(TMath::Sign(1.,trPar.GetInverseBendingMomentum())));
150   this->SetPxPyPz(trPar.Px(),trPar.Py(), trPar.Pz()); 
151   this->SetTriggered(trackReco->GetMatchTrigger()); 
152   
153   Double_t xyz[3] = { trPar.GetNonBendingCoor(), 
154                       trPar.GetBendingCoor(),
155                       trPar.GetZ()};
156   if (zvert!=-9999) xyz[2] = zvert;
157   this->SetVertex(xyz); 
158 }
159
160 //============================================
161 void AliMUONTrackLight::FillFromESD(AliESDMuonTrack* muonTrack,Double_t zvert){
162   /// computes prec and charge from ESD track
163   Double_t mumass = TDatabasePDG::Instance()->GetParticle(13)->Mass(); 
164   Double_t thetaX = muonTrack->GetThetaX();
165   Double_t thetaY = muonTrack->GetThetaY();
166   Double_t tanthx = TMath::Tan(thetaX);
167   Double_t tanthy = TMath::Tan(thetaY);
168   Double_t pYZ    =  1./TMath::Abs(muonTrack->GetInverseBendingMomentum());
169   Double_t pz     = - pYZ / TMath::Sqrt(1.0 + tanthy * tanthy);
170   Double_t px     = pz * tanthx;
171   Double_t py     = pz * tanthy;
172   fCharge   = Int_t(TMath::Sign(1.,muonTrack->GetInverseBendingMomentum()));
173   Double_t energy = TMath::Sqrt(mumass * mumass + px*px + py*py + pz*pz);
174   fPrec.SetPxPyPzE(px,py,pz,energy);
175   // get the position
176   fXYZ[0] = muonTrack->GetNonBendingCoor();
177   fXYZ[1] = muonTrack->GetBendingCoor();
178   if (zvert==-9999) fXYZ[2] = muonTrack->GetZ();
179   else fXYZ[2] = zvert;
180   // get the chi2 per d.o.f.
181   fChi2 = muonTrack->GetChi2()/ (2.0 * muonTrack->GetNHit() - 5);
182   fIsTriggered = muonTrack->GetMatchTrigger();
183 }
184
185 //============================================
186 void AliMUONTrackLight::SetPxPyPz(Double_t px, Double_t py, Double_t pz){ 
187   /// set the reconstructed 4-momentum, assuming the particle is a muon
188   Double_t mumass = TDatabasePDG::Instance()->GetParticle(13)->Mass(); 
189   Double_t energy = TMath::Sqrt(mumass * mumass + px*px + py*py + pz*pz);
190   fPrec.SetPxPyPzE(px,py,pz,energy);
191 }
192
193 //============================================
194 TParticle* AliMUONTrackLight::FindRefTrack(
195                 AliMUONTrack* trackReco, AliMUONVTrackStore* trackRefArray,
196                 AliStack* stack)
197 {
198   /// Find the Monte Carlo (MC) particle that corresponds to a given reconstructed track.
199   /// @param trackReco  This is the reconstructed track for which we want to find a
200   ///           corresponding MC particle.
201   /// @param trackRefArray  The list of MC reference tracks as generated by
202   ///           AliMUONRecoCheck::ReconstructedTracks for example.
203   /// @param stack  The MC stack of simulated particles.
204   
205   TParticle *part = 0; 
206   const Double_t kSigmaCut = 4;  // 4 sigmas cut
207   Int_t compPart = 0;
208   Bool_t compTrack;
209   
210   TIter next(trackRefArray->CreateIterator());
211   AliMUONTrack* trackRef;
212   while ( (trackRef = static_cast<AliMUONTrack*>(next())) ) {
213     // check if trackRef is compatible with trackReco:
214     compTrack = kFALSE;
215     
216     if (trackReco->GetNClusters() > 1) {
217       
218       // check cluster by cluster if trackReco contain info at each cluster
219       Bool_t compTrackArray[10];
220       trackRef->CompatibleTrack(trackReco,kSigmaCut,compTrackArray);
221       if (TrackCheck(compTrackArray) == 4) compTrack = kTRUE;
222       
223     } else {
224       
225       // otherwise check only parameters at the z position of the first trackRef
226       AliMUONTrackParam *refParam = (AliMUONTrackParam*) trackRef->GetTrackParamAtCluster()->First();
227       AliMUONTrackParam recoParam(*((AliMUONTrackParam*) trackReco->GetTrackParamAtCluster()->First()));
228       AliMUONTrackExtrap::ExtrapToZCov(&recoParam, refParam->GetZ());
229       Double_t chi2;
230       if (refParam->CompatibleTrackParam(recoParam, kSigmaCut, chi2)) compTrack = kTRUE;
231       
232     }
233       
234     if (compTrack) {
235       compPart++;
236       Int_t trackID = trackRef->GetTrackID();
237       this->SetTrackPythiaLine(trackID);
238       part = stack->Particle(trackID);
239       fTrackPDGCode = part->GetPdgCode();
240     }
241   }
242   if (compPart>1) {
243     AliFatal("More than one particle compatible with the reconstructed track.");
244   } 
245   return part;
246 }
247
248 //============================================
249 Int_t AliMUONTrackLight::TrackCheck(Bool_t *compTrack){
250   /// Apply reconstruction requirements
251   /// Return number of validated conditions 
252   /// If all the tests are verified then TrackCheck = 4 (good track)
253   
254   Int_t iTrack = 0;
255   Int_t hitsInLastStations = 0;
256   
257   // apply reconstruction requirements
258   if (compTrack[0] || compTrack[1]) iTrack++; // at least one hit in st. 0
259   if (compTrack[2] || compTrack[3]) iTrack++; // at least one hit in st. 1
260   if (compTrack[4] || compTrack[5]) iTrack++; // at least one hit in st. 2
261   for (Int_t ch = 6; ch < AliMUONConstants::NTrackingCh(); ch++) {
262     if (compTrack[ch]) hitsInLastStations++; 
263   }
264   if (hitsInLastStations > 2) iTrack++; // at least 3 hits in st. 3 & 4
265   return iTrack;
266 }
267
268 //============================================
269 void AliMUONTrackLight::FillMuonHistory(AliStack *stack, TParticle *part){
270   /// scans the muon history to determine parents pdg code and pythia line
271   Int_t countP = -1;
272   Int_t parents[10], parLine[10];
273   Int_t lineM = part->GetFirstMother();//line in the Pythia output of the particle's mother
274
275   TParticle *mother;
276   Int_t status=-1, pdg=-1;
277   while(lineM >= 0){
278     
279     mother = stack->Particle(lineM); //direct mother of rec. track
280     pdg = mother->GetPdgCode();//store PDG code of first mother
281     // break if a string, gluon, quark or diquark is found 
282     if(pdg == 92 || pdg == 21 || TMath::Abs(pdg) < 10 || IsDiquark(pdg)) break;
283     parents[++countP] = pdg;
284     parLine[countP] = lineM;
285     status = mother->GetStatusCode();//get its status code to check if oscillation occured
286     if(IsB0(parents[countP]) && status == 12) this->SetOscillation(kTRUE);
287     lineM = mother->GetFirstMother();
288   }
289   //store all the fragmented parents in an array:
290   for(int i = 0; i <= countP; i++){
291     this->SetParentPDGCode(i,parents[countP-i]);
292     this->SetParentPythiaLine(i,parLine[countP-i]);
293   }
294   fNParents = countP+1;
295   countP = -1;
296
297   //and store the lines of the string and further quarks in another array:
298   while(lineM >= 0){
299     mother = stack->Particle(lineM);
300     pdg = mother->GetPdgCode();
301     //now, get information before the fragmentation
302     this->SetQuarkPythiaLine(++countP, lineM);//store the line of the string in index 0
303     this->SetQuarkPDGCode(countP, pdg);//store the pdg of the quarks in index 1,2
304     lineM = mother->GetFirstMother();
305   }
306   
307   //check if in case of HF production, the string points to the correct end
308   //and correct it in case of need:
309   countP = 1;
310   for(int par = 0; par < 4; par++){
311     if(TMath::Abs(this->GetQuarkPDGCode(par)) < 6){
312       countP = par; //get the quark just before hadronisation
313       break;
314     }
315   }
316   if(this->GetQuarkPythiaLine(countP) > -1 && (this->GetParentFlavour(0)==4 || this->GetParentFlavour(0)==5)){
317     if(this->GetParentFlavour(0) != TMath::Abs(this->GetQuarkPDGCode(countP))){
318
319       AliWarning(Form("quark flavour of parent and that of quark do not correspond: %d %d --> correcting\n",
320           this->GetParentFlavour(0), TMath::Abs(this->GetQuarkPDGCode(countP)))
321         );
322       
323       pdg = this->GetQuarkPDGCode(countP);
324       Int_t line = this->GetQuarkPythiaLine(countP);
325       this->ResetQuarkInfo();
326       while(TMath::Abs(pdg) != this->GetParentFlavour(0)){//pdg of q,g in Pythia listing following the wrong string end
327                                                         //must coincide with the flavour of the last fragmented mother
328
329         pdg = stack->Particle(++line)->GetPdgCode();    
330       }
331       //now, we have the correct string end and the correct line
332       //continue to fill again all parents and corresponding lines
333       while(line >= 0){
334         mother = stack->Particle(line);//get again the mother
335         pdg = mother->GetPdgCode();
336         this->SetQuarkPythiaLine(countP, line);
337         this->SetQuarkPDGCode(countP++, pdg);
338         line = mother->GetFirstMother();
339       }
340       this->PrintInfo("h");
341     }//mismatch
342   }
343 }
344
345 //====================================
346 void AliMUONTrackLight::ResetQuarkInfo(){
347   /// resets parton information
348   for(int pos = 1; pos < 4; pos++){//[0] is the string
349     this->SetQuarkPDGCode(pos,-1);
350     this->SetQuarkPythiaLine(pos,-1);
351   }
352 }
353
354 //====================================
355 Bool_t AliMUONTrackLight::IsB0(Int_t intTest) const {
356   /// checks if the particle is a B0 
357   Int_t bMes0[2] = {511,531};//flavour code of B0d and B0s
358   Bool_t answer = kFALSE;
359   for(int i = 0; i < 2; i++){
360     if(TMath::Abs(intTest) == bMes0[i]){
361       answer = kTRUE;
362       break;
363     }
364   }
365   return answer;
366 }
367 //====================================
368 Bool_t AliMUONTrackLight::IsMotherAResonance(Int_t index) const {
369   /// checks if mother is a resonance
370   Int_t intTest = GetParentPDGCode(index); 
371   // the resonance pdg code is built this way
372   // x00ffn where x=0,1,.. (1S,2S... states), f=quark flavour 
373   Int_t id=intTest%100000; 
374   return (!((id-id%10)%110));
375 }
376 //====================================
377 Int_t AliMUONTrackLight::GetParentFlavour(Int_t idParent) const {
378   /// returns the flavour of parent idParent (idParent=0 is the oldest 
379   /// hadronized parent)
380   Int_t pdg = GetParentPDGCode(idParent); 
381   Int_t quark = TMath::Abs(pdg/100);
382   if(quark > 9) quark = quark/10;
383   return quark;
384 }
385
386 //====================================
387 void AliMUONTrackLight::PrintInfo(Option_t* opt){
388   /// prints information about the track: 
389   /// - "H" muon's decay history
390   /// - "K" muon kinematics
391   /// - "A" all variables
392   TString options(opt);
393   options.ToUpper();
394
395   if(options.Contains("H") || options.Contains("A")){ //muon decay history
396     char *name= new char[100];
397     TString pdg = "", line = "";
398     for(int i = 3; i >= 0; i--){
399       if(this->GetQuarkPythiaLine(i)>= 0){
400         sprintf(name, "%4d --> ", this->GetQuarkPythiaLine(i));
401         line += name;
402         sprintf(name, "%4d --> ", this->GetQuarkPDGCode(i));
403         pdg += name;
404       }
405     }
406     for(int i = 0; i < fNParents; i++){ 
407       if(this->GetParentPythiaLine(i)>= 0){
408         sprintf(name, "%7d --> ", this->GetParentPythiaLine(i));
409         line += name;
410         sprintf(name, "%7d --> ", this->GetParentPDGCode(i));
411         pdg += name;
412       }
413     }
414     sprintf(name, "%4d", this->GetTrackPythiaLine()); line += name;
415     sprintf(name, "%4d", this->GetTrackPDGCode()); pdg += name;
416
417     printf("\nmuon's decay history:\n");
418     printf(" PDG: %s\n", pdg.Data());
419     printf("line: %s\n", line.Data());
420   }
421   if(options.Contains("K") || options.Contains("A")){ //muon kinematic
422
423     Int_t charge = this->GetCharge();
424     Double_t *vtx = this->GetVertex();
425     TLorentzVector momRec = this->GetPRec();
426     TLorentzVector momGen = this->GetPGen();
427     printf("the track's charge is %d\n", charge);
428     printf("Primary vertex: Vx = %1.3f, Vy = %1.3f, Vz = %1.3f\n", vtx[0], vtx[1], vtx[2]);
429     printf("Generated:     Px = %1.3f, Py = %1.3f, Pz = %1.3f\n", momGen.Px(), momGen.Py(), momGen.Pz());
430     printf("Reconstructed: Px = %1.3f, Py = %1.3f, Pz = %1.3f\n", momRec.Px(), momRec.Py(), momRec.Pz());
431     printf("Rec. variables: pT %1.3f, pseudo-rapidity %1.3f, theta %1.3f (%1.3f degree), phi %1.3f (%1.3f degree)\n", 
432            momRec.Pt(), momRec.Eta(), momRec.Theta(), 180./TMath::Pi() * momRec.Theta(), 
433            momRec.Phi(), 180./TMath::Pi() * momRec.Phi());
434   }
435 }
436 //====================================
437 Bool_t AliMUONTrackLight::IsParentPionOrKaon(Int_t idparent){
438   /// checks if a muon comes from a pion or kaon or a particle that decays into one of these two
439   Int_t pdg = this->GetParentPDGCode(idparent); 
440   if (TMath::Abs(pdg)==211 || //pi+
441       TMath::Abs(pdg)==321 || //K+
442       TMath::Abs(pdg)==213 || //rho+
443       TMath::Abs(pdg)==311 || //K0
444       TMath::Abs(pdg)==313 || //K*0
445       TMath::Abs(pdg)==323    //K*+
446       ) { 
447     return kTRUE;
448   }
449   else return kFALSE;
450 }
451 //====================================
452 Bool_t AliMUONTrackLight::IsDiquark(Int_t pdg){
453   /// check if the provided pdg code corresponds to a diquark 
454   pdg = TMath::Abs(pdg);
455   if((pdg > 1000) && (pdg%100 < 10)) return kTRUE;
456   else return kFALSE;
457 }