]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTrackLight.cxx
Move contents of EVE/Alieve to EVE/EveDet as most code will remain there.
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackLight.cxx
CommitLineData
55fd51b0 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
b88403f3 3 * SigmaEffect_thetadegrees *
55fd51b0 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
3d1463c8 18//-----------------------------------------------------------------------------
55fd51b0 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
3d1463c8 27//
28// This class was prepared by INFN Cagliari, July 2006
29// (authors: H.Woehri, A.de Falco)
30//-----------------------------------------------------------------------------
55fd51b0 31
9bdda5f6 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
55fd51b0 39#include "AliMUONTrackLight.h"
40#include "AliMUONTrack.h"
41#include "AliMUONConstants.h"
bd5eb041 42#include "AliMUONVTrackStore.h"
9bdda5f6 43#include "AliMUONTrackExtrap.h"
55fd51b0 44
45#include "AliESDMuonTrack.h"
46#include "AliRunLoader.h"
47#include "AliStack.h"
48#include "AliHeader.h"
49
50#include "TDatabasePDG.h"
55fd51b0 51#include "TParticle.h"
52#include "TString.h"
53
54ClassImp(AliMUONTrackLight)
55
56//===================================================================
57
58AliMUONTrackLight::AliMUONTrackLight()
59 : TObject(),
60 fPrec(),
61 fIsTriggered(kFALSE),
62 fCharge(-999),
b88403f3 63 fChi2(-1),
55fd51b0 64 fCentr(-1),
65 fPgen(),
66 fTrackPythiaLine(-999),
67 fTrackPDGCode(-999),
68 fOscillation(kFALSE),
b88403f3 69 fNParents(0),
70 fWeight(1)
55fd51b0 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//============================================
87AliMUONTrackLight::AliMUONTrackLight(const AliMUONTrackLight &muonCopy)
88 : TObject(muonCopy),
89 fPrec(muonCopy.fPrec),
90 fIsTriggered(muonCopy.fIsTriggered),
91 fCharge(muonCopy.fCharge),
b88403f3 92 fChi2(muonCopy.fChi2),
55fd51b0 93 fCentr(muonCopy.fCentr),
94 fPgen(muonCopy.fPgen),
95 fTrackPythiaLine(muonCopy.fTrackPythiaLine),
96 fTrackPDGCode(muonCopy.fTrackPDGCode),
97 fOscillation(muonCopy.fOscillation),
b88403f3 98 fNParents(muonCopy.fNParents),
99 fWeight(muonCopy.fWeight)
55fd51b0 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//============================================
114AliMUONTrackLight::AliMUONTrackLight(AliESDMuonTrack* muonTrack)
115 : TObject(),
116 fPrec(),
117 fIsTriggered(kFALSE),
118 fCharge(-999),
b88403f3 119 fChi2(-1),
55fd51b0 120 fCentr(-1),
121 fPgen(),
122 fTrackPythiaLine(-999),
123 fTrackPDGCode(-999),
124 fOscillation(kFALSE),
b88403f3 125 fNParents(0),
126 fWeight(1)
55fd51b0 127{
128 /// constructor
129 //AliMUONTrackLight();
b88403f3 130 FillFromESD(muonTrack);
55fd51b0 131}
132
133//============================================
b88403f3 134AliMUONTrackLight::~AliMUONTrackLight()
135{
136/// Destructor
137}
138
139//============================================
140
141void AliMUONTrackLight::FillFromAliMUONTrack(AliMUONTrack *trackReco,Double_t zvert){
142 /// this method sets the muon reconstructed momentum according to the value given by AliMUONTrack
61fed964 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 }
b88403f3 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(),
61fed964 155 trPar.GetZ()};
156 if (zvert!=-9999) xyz[2] = zvert;
b88403f3 157 this->SetVertex(xyz);
158}
159
160//============================================
161void AliMUONTrackLight::FillFromESD(AliESDMuonTrack* muonTrack,Double_t zvert){
55fd51b0 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);
b88403f3 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();
55fd51b0 183}
184
185//============================================
186void 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//============================================
bd5eb041 194TParticle* AliMUONTrackLight::FindRefTrack(
195 AliMUONTrack* trackReco, AliMUONVTrackStore* trackRefArray,
61fed964 196 AliStack* stack)
bd5eb041 197{
9bdda5f6 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.
9bdda5f6 204
55fd51b0 205 TParticle *part = 0;
61fed964 206 const Double_t kSigmaCut = 4; // 4 sigmas cut
bd5eb041 207 Int_t compPart = 0;
61fed964 208 Bool_t compTrack;
209
bd5eb041 210 TIter next(trackRefArray->CreateIterator());
211 AliMUONTrack* trackRef;
212 while ( (trackRef = static_cast<AliMUONTrack*>(next())) ) {
55fd51b0 213 // check if trackRef is compatible with trackReco:
61fed964 214 compTrack = kFALSE;
9bdda5f6 215
61fed964 216 if (trackReco->GetNClusters() > 1) {
217
218 // check cluster by cluster if trackReco contain info at each cluster
219 Bool_t *compTrackArray = trackRef->CompatibleTrack(trackReco,kSigmaCut);
220 if (TrackCheck(compTrackArray) == 4) compTrack = kTRUE;
221
222 } else {
223
224 // otherwise check only parameters at the z position of the first trackRef
225 AliMUONTrackParam *refParam = (AliMUONTrackParam*) trackRef->GetTrackParamAtCluster()->First();
226 AliMUONTrackParam recoParam(*((AliMUONTrackParam*) trackReco->GetTrackParamAtCluster()->First()));
227 AliMUONTrackExtrap::ExtrapToZCov(&recoParam, refParam->GetZ());
228 Double_t chi2;
229 if (refParam->CompatibleTrackParam(recoParam, kSigmaCut, chi2)) compTrack = kTRUE;
230
231 }
232
233 if (compTrack) {
bd5eb041 234 compPart++;
55fd51b0 235 Int_t trackID = trackRef->GetTrackID();
236 this->SetTrackPythiaLine(trackID);
bd5eb041 237 part = stack->Particle(trackID);
55fd51b0 238 fTrackPDGCode = part->GetPdgCode();
239 }
240 }
bd5eb041 241 if (compPart>1) {
9bdda5f6 242 AliFatal("More than one particle compatible with the reconstructed track.");
55fd51b0 243 }
bd5eb041 244 return part;
55fd51b0 245}
246
247//============================================
248Int_t AliMUONTrackLight::TrackCheck(Bool_t *compTrack){
249 /// Apply reconstruction requirements
250 /// Return number of validated conditions
251 /// If all the tests are verified then TrackCheck = 4 (good track)
9bdda5f6 252
55fd51b0 253 Int_t iTrack = 0;
254 Int_t hitsInLastStations = 0;
255
256 // apply reconstruction requirements
257 if (compTrack[0] || compTrack[1]) iTrack++; // at least one hit in st. 0
258 if (compTrack[2] || compTrack[3]) iTrack++; // at least one hit in st. 1
259 if (compTrack[4] || compTrack[5]) iTrack++; // at least one hit in st. 2
260 for (Int_t ch = 6; ch < AliMUONConstants::NTrackingCh(); ch++) {
261 if (compTrack[ch]) hitsInLastStations++;
262 }
263 if (hitsInLastStations > 2) iTrack++; // at least 3 hits in st. 3 & 4
264 return iTrack;
265}
266
b88403f3 267//============================================
268void AliMUONTrackLight::FillMuonHistory(AliStack *stack, TParticle *part){
55fd51b0 269 /// scans the muon history to determine parents pdg code and pythia line
270 Int_t countP = -1;
271 Int_t parents[10], parLine[10];
272 Int_t lineM = part->GetFirstMother();//line in the Pythia output of the particle's mother
273
55fd51b0 274 TParticle *mother;
275 Int_t status=-1, pdg=-1;
276 while(lineM >= 0){
b88403f3 277
55fd51b0 278 mother = stack->Particle(lineM); //direct mother of rec. track
279 pdg = mother->GetPdgCode();//store PDG code of first mother
b88403f3 280 // break if a string, gluon, quark or diquark is found
281 if(pdg == 92 || pdg == 21 || TMath::Abs(pdg) < 10 || IsDiquark(pdg)) break;
55fd51b0 282 parents[++countP] = pdg;
283 parLine[countP] = lineM;
284 status = mother->GetStatusCode();//get its status code to check if oscillation occured
285 if(IsB0(parents[countP]) && status == 12) this->SetOscillation(kTRUE);
286 lineM = mother->GetFirstMother();
287 }
288 //store all the fragmented parents in an array:
289 for(int i = 0; i <= countP; i++){
290 this->SetParentPDGCode(i,parents[countP-i]);
291 this->SetParentPythiaLine(i,parLine[countP-i]);
292 }
55fd51b0 293 fNParents = countP+1;
294 countP = -1;
b88403f3 295
55fd51b0 296 //and store the lines of the string and further quarks in another array:
297 while(lineM >= 0){
298 mother = stack->Particle(lineM);
299 pdg = mother->GetPdgCode();
300 //now, get information before the fragmentation
301 this->SetQuarkPythiaLine(++countP, lineM);//store the line of the string in index 0
302 this->SetQuarkPDGCode(countP, pdg);//store the pdg of the quarks in index 1,2
303 lineM = mother->GetFirstMother();
304 }
b88403f3 305
55fd51b0 306 //check if in case of HF production, the string points to the correct end
307 //and correct it in case of need:
308 countP = 1;
b88403f3 309 for(int par = 0; par < 4; par++){
310 if(TMath::Abs(this->GetQuarkPDGCode(par)) < 6){
311 countP = par; //get the quark just before hadronisation
312 break;
313 }
314 }
55fd51b0 315 if(this->GetQuarkPythiaLine(countP) > -1 && (this->GetParentFlavour(0)==4 || this->GetParentFlavour(0)==5)){
316 if(this->GetParentFlavour(0) != TMath::Abs(this->GetQuarkPDGCode(countP))){
317
9bdda5f6 318 AliWarning(Form("quark flavour of parent and that of quark do not correspond: %d %d --> correcting\n",
319 this->GetParentFlavour(0), TMath::Abs(this->GetQuarkPDGCode(countP)))
320 );
321
b88403f3 322 Int_t pdg = this->GetQuarkPDGCode(countP), line = this->GetQuarkPythiaLine(countP);
55fd51b0 323 this->ResetQuarkInfo();
324 while(TMath::Abs(pdg) != this->GetParentFlavour(0)){//pdg of q,g in Pythia listing following the wrong string end
325 //must coincide with the flavour of the last fragmented mother
326
327 pdg = stack->Particle(++line)->GetPdgCode();
328 }
329 //now, we have the correct string end and the correct line
330 //continue to fill again all parents and corresponding lines
331 while(line >= 0){
332 mother = stack->Particle(line);//get again the mother
333 pdg = mother->GetPdgCode();
334 this->SetQuarkPythiaLine(countP, line);
335 this->SetQuarkPDGCode(countP++, pdg);
336 line = mother->GetFirstMother();
337 }
b88403f3 338 this->PrintInfo("h");
339 }//mismatch
55fd51b0 340 }
341}
b88403f3 342
55fd51b0 343//====================================
344void AliMUONTrackLight::ResetQuarkInfo(){
345 /// resets parton information
346 for(int pos = 1; pos < 4; pos++){//[0] is the string
347 this->SetQuarkPDGCode(pos,-1);
348 this->SetQuarkPythiaLine(pos,-1);
349 }
350}
351
352//====================================
353Bool_t AliMUONTrackLight::IsB0(Int_t intTest) const {
354 /// checks if the particle is a B0
355 Int_t bMes0[2] = {511,531};//flavour code of B0d and B0s
356 Bool_t answer = kFALSE;
357 for(int i = 0; i < 2; i++){
358 if(TMath::Abs(intTest) == bMes0[i]){
359 answer = kTRUE;
360 break;
361 }
362 }
363 return answer;
364}
365//====================================
366Bool_t AliMUONTrackLight::IsMotherAResonance(Int_t index) const {
367 /// checks if mother is a resonance
368 Int_t intTest = GetParentPDGCode(index);
369 // the resonance pdg code is built this way
370 // x00ffn where x=0,1,.. (1S,2S... states), f=quark flavour
371 Int_t id=intTest%100000;
372 return (!((id-id%10)%110));
373}
374//====================================
375Int_t AliMUONTrackLight::GetParentFlavour(Int_t idParent) const {
376 /// returns the flavour of parent idParent (idParent=0 is the oldest
377 /// hadronized parent)
378 Int_t pdg = GetParentPDGCode(idParent);
379 Int_t quark = TMath::Abs(pdg/100);
380 if(quark > 9) quark = quark/10;
381 return quark;
382}
383
384//====================================
385void AliMUONTrackLight::PrintInfo(Option_t* opt){
386 /// prints information about the track:
387 /// - "H" muon's decay history
388 /// - "K" muon kinematics
389 /// - "A" all variables
390 TString options(opt);
391 options.ToUpper();
392
393 if(options.Contains("H") || options.Contains("A")){ //muon decay history
394 char *name= new char[100];
395 TString pdg = "", line = "";
396 for(int i = 3; i >= 0; i--){
397 if(this->GetQuarkPythiaLine(i)>= 0){
398 sprintf(name, "%4d --> ", this->GetQuarkPythiaLine(i));
399 line += name;
400 sprintf(name, "%4d --> ", this->GetQuarkPDGCode(i));
401 pdg += name;
402 }
403 }
404 for(int i = 0; i < fNParents; i++){
405 if(this->GetParentPythiaLine(i)>= 0){
406 sprintf(name, "%7d --> ", this->GetParentPythiaLine(i));
407 line += name;
408 sprintf(name, "%7d --> ", this->GetParentPDGCode(i));
409 pdg += name;
410 }
411 }
412 sprintf(name, "%4d", this->GetTrackPythiaLine()); line += name;
413 sprintf(name, "%4d", this->GetTrackPDGCode()); pdg += name;
414
415 printf("\nmuon's decay history:\n");
416 printf(" PDG: %s\n", pdg.Data());
417 printf("line: %s\n", line.Data());
418 }
419 if(options.Contains("K") || options.Contains("A")){ //muon kinematic
420
421 Int_t charge = this->GetCharge();
422 Double_t *vtx = this->GetVertex();
423 TLorentzVector momRec = this->GetPRec();
424 TLorentzVector momGen = this->GetPGen();
425 printf("the track's charge is %d\n", charge);
426 printf("Primary vertex: Vx = %1.3f, Vy = %1.3f, Vz = %1.3f\n", vtx[0], vtx[1], vtx[2]);
427 printf("Generated: Px = %1.3f, Py = %1.3f, Pz = %1.3f\n", momGen.Px(), momGen.Py(), momGen.Pz());
428 printf("Reconstructed: Px = %1.3f, Py = %1.3f, Pz = %1.3f\n", momRec.Px(), momRec.Py(), momRec.Pz());
429 printf("Rec. variables: pT %1.3f, pseudo-rapidity %1.3f, theta %1.3f (%1.3f degree), phi %1.3f (%1.3f degree)\n",
430 momRec.Pt(), momRec.Eta(), momRec.Theta(), 180./TMath::Pi() * momRec.Theta(),
431 momRec.Phi(), 180./TMath::Pi() * momRec.Phi());
432 }
433}
b88403f3 434//====================================
435Bool_t AliMUONTrackLight::IsParentPionOrKaon(Int_t idparent){
436 /// checks if a muon comes from a pion or kaon or a particle that decays into one of these two
437 Int_t pdg = this->GetParentPDGCode(idparent);
438 if (TMath::Abs(pdg)==211 || //pi+
439 TMath::Abs(pdg)==321 || //K+
440 TMath::Abs(pdg)==213 || //rho+
441 TMath::Abs(pdg)==311 || //K0
442 TMath::Abs(pdg)==313 || //K*0
443 TMath::Abs(pdg)==323 //K*+
444 ) {
445 return kTRUE;
446 }
447 else return kFALSE;
448}
449//====================================
450Bool_t AliMUONTrackLight::IsDiquark(Int_t pdg){
451 /// check if the provided pdg code corresponds to a diquark
452 pdg = TMath::Abs(pdg);
453 if((pdg > 1000) && (pdg%100 < 10)) return kTRUE;
454 else return kFALSE;
455}