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 **************************************************************************/
16 //====================================================================================================================================================
18 // Support class for various common operation on MFT objects
20 // Contact author: antonio.uras@cern.ch
22 //====================================================================================================================================================
24 #include "AliMUONTrackParam.h"
25 #include "AliMUONTrackExtrap.h"
26 #include "AliAODTrack.h"
27 #include "AliAODDimuon.h"
28 #include "TLorentzVector.h"
29 #include "AliMFTConstants.h"
30 #include "TDatabasePDG.h"
33 #include "TObjArray.h"
34 #include "TDecompLU.h"
37 #include "AliMFTAnalysisTools.h"
39 ClassImp(AliMFTAnalysisTools)
41 //====================================================================================================================================================
43 Bool_t AliMFTAnalysisTools::ExtrapAODMuonToZ(AliAODTrack *muon, Double_t z, Double_t xy[2]) {
45 if (!(muon->PzAtDCA()!=0)) return kFALSE;
47 AliMUONTrackParam *param = new AliMUONTrackParam();
49 param -> SetNonBendingCoor(muon->XAtDCA());
50 param -> SetBendingCoor(muon->YAtDCA());
51 param -> SetZ(AliMFTConstants::fZEvalKinem);
52 param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
53 param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
54 param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
56 AliMUONTrackExtrap::ExtrapToZ(param, z);
57 xy[0] = param->GetNonBendingCoor();
58 xy[1] = param->GetBendingCoor();
66 //====================================================================================================================================================
68 Bool_t AliMFTAnalysisTools::ExtrapAODMuonToZ(AliAODTrack *muon, Double_t z, Double_t xy[2], TLorentzVector &kinem) {
70 if (!(muon->PzAtDCA()!=0)) return kFALSE;
72 AliMUONTrackParam *param = new AliMUONTrackParam();
74 param -> SetNonBendingCoor(muon->XAtDCA());
75 param -> SetBendingCoor(muon->YAtDCA());
76 param -> SetZ(AliMFTConstants::fZEvalKinem);
77 param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
78 param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
79 param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
81 AliMUONTrackExtrap::ExtrapToZ(param, z);
82 xy[0] = param->GetNonBendingCoor();
83 xy[1] = param->GetBendingCoor();
85 Double_t massMu = TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
86 Double_t energy = TMath::Sqrt(massMu*massMu + param->Px()*param->Px() + param->Py()*param->Py() + param->Pz()*param->Pz());
88 kinem.SetPxPyPzE(param->Px(), param->Py(), param->Pz(), energy);
96 //====================================================================================================================================================
98 Bool_t AliMFTAnalysisTools::ExtrapAODMuonToZ(AliAODTrack *muon, Double_t z, Double_t xy[2], TLorentzVector &kinem, TMatrixD &cov) {
100 // Extrapolate muon to a given z providing the corresponding (x,y) position and updating kinematics and covariance matrix
102 if (!(muon->PzAtDCA()!=0)) return kFALSE;
104 AliMUONTrackParam *param = new AliMUONTrackParam();
106 param -> SetNonBendingCoor(muon->XAtDCA());
107 param -> SetBendingCoor(muon->YAtDCA());
108 param -> SetZ(AliMFTConstants::fZEvalKinem);
109 param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
110 param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
111 param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
113 param -> SetCovariances(ConvertCovMatrixAOD2MUON(muon));
115 AliMUONTrackExtrap::ExtrapToZCov(param, z);
116 xy[0] = param->GetNonBendingCoor();
117 xy[1] = param->GetBendingCoor();
119 Double_t massMu = TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
120 Double_t energy = TMath::Sqrt(massMu*massMu + param->Px()*param->Px() + param->Py()*param->Py() + param->Pz()*param->Pz());
122 kinem.SetPxPyPzE(param->Px(), param->Py(), param->Pz(), energy);
124 cov = param->GetCovariances();
132 //====================================================================================================================================================
134 Bool_t AliMFTAnalysisTools::ExtrapAODMuonToXY(AliAODTrack *muon, Double_t xy[2], Double_t &zFinal, TLorentzVector &kinem, TMatrixD &cov) {
136 // Find the point of closest approach between the muon and the direction parallel to the z-axis defined by the given (x,y)
137 // Provide the z of the above point as weel as the updated kinematics and covariance matrix
139 // We look for the above-defined PCA
141 AliMUONTrackParam *param = new AliMUONTrackParam();
142 param -> SetNonBendingCoor(muon->XAtDCA());
143 param -> SetBendingCoor(muon->YAtDCA());
144 param -> SetZ(AliMFTConstants::fZEvalKinem);
145 param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
146 param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
147 param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
149 // here we want to understand in which direction we have to search the minimum...
151 Double_t step = 1.; // initial step, in cm
152 Double_t startPoint = 0.;
154 Double_t r[3]={0}, z[3]={startPoint-step, startPoint, startPoint+step};
156 TVector3 **points = new TVector3*[2]; // points[0] for the muon, points[1] for the direction parallel to the z-axis defined by the given (x,y)
158 for (Int_t i=0; i<3; i++) {
159 AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
160 points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
161 points[1] = new TVector3(xy[0],xy[1],z[i]);
162 r[i] = GetDistanceBetweenPoints(points,2);
163 for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
166 Int_t researchDirection = 0;
168 if (r[0]>r[1] && r[1]>r[2]) researchDirection = +1; // towards z positive
169 else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1; // towards z negative
170 else if (r[0]<r[1] && r[1]>r[2]) {
171 printf("E-AliMFTAnalysisTools::ExtrapAODMuonToXY: Point of closest approach cannot be found (no minima)\n");
177 while (TMath::Abs(researchDirection)>0.5) {
179 if (researchDirection>0) {
182 z[2] = z[1]+researchDirection*step;
187 z[0] = z[1]+researchDirection*step;
189 if (TMath::Abs(z[0])>900.) {
190 printf("E-AliMFTAnalysisTools::ExtrapAODMuonToXY: Point of closest approach cannot be found (no minima in the fiducial region)\n");
196 for (Int_t i=0; i<3; i++) {
197 AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
198 points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
199 points[1] = new TVector3(xy[0],xy[1],z[i]);
200 r[i] = GetDistanceBetweenPoints(points,2);
201 for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
205 if (r[0]>r[1] && r[1]>r[2]) researchDirection = +1; // towards z positive
206 else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1; // towards z negative
210 // now we now that the minimum is between z[0] and z[2] and we search for it
213 while (step>AliMFTConstants::fPrecisionPointOfClosestApproach) {
216 for (Int_t i=0; i<3; i++) {
217 AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
218 points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
219 points[1] = new TVector3(xy[0],xy[1],z[i]);
220 r[i] = GetDistanceBetweenPoints(points,2);
221 for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
223 if (r[0]<r[1]) z[1] = z[0];
224 else if (r[2]<r[1]) z[1] = z[2];
230 Double_t xyMuon[2] = {0};
231 ExtrapAODMuonToZ(muon, zFinal, xyMuon, kinem, cov);
237 //====================================================================================================================================================
239 Bool_t AliMFTAnalysisTools::GetAODMuonOffset(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv, Double_t &offset) {
241 Double_t xy[2] = {0};
242 ExtrapAODMuonToZ(muon, zv, xy);
244 offset = TMath::Sqrt((xv-xy[0])*(xv-xy[0]) + (yv-xy[1])*(yv-xy[1]));
250 //====================================================================================================================================================
252 Bool_t AliMFTAnalysisTools::GetAODMuonOffsetSmeared(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv,
253 Double_t smearOffsetX, Double_t smearOffsetY, Double_t &offset) {
255 // Evaluate transverse offset adding to it an additional smearing (independently along the x and y directions)
257 Double_t xy[2] = {0};
258 ExtrapAODMuonToZ(muon, zv, xy);
260 xy[0] = gRandom->Gaus(xy[0], smearOffsetX);
261 xy[1] = gRandom->Gaus(xy[1], smearOffsetY);
263 offset = TMath::Sqrt((xv-xy[0])*(xv-xy[0]) + (yv-xy[1])*(yv-xy[1]));
269 //====================================================================================================================================================
271 Bool_t AliMFTAnalysisTools::GetAODMuonOffsetZ(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv, Double_t &offset) {
273 Double_t xy[2] = {xv, yv};
275 TLorentzVector kinem(0,0,0,0);
278 ExtrapAODMuonToXY(muon, xy, zFinal, kinem, cov);
280 offset = TMath::Abs(zFinal - zv);
286 //====================================================================================================================================================
288 Bool_t AliMFTAnalysisTools::GetAODMuonWeightedOffset(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv, Double_t &offset) {
290 Double_t xy[2] = {0};
291 TLorentzVector kinem(0,0,0,0);
294 ExtrapAODMuonToZ(muon, zv, xy, kinem, cov);
296 TMatrixD covCoordinates(2,2);
297 covCoordinates(0,0) = cov(0,0);
298 covCoordinates(0,1) = cov(0,2);
299 covCoordinates(1,0) = cov(2,0);
300 covCoordinates(1,1) = cov(2,2);
302 if (covCoordinates.Determinant() < covCoordinates.GetTol()) return kFALSE;
304 if (TDecompLU::InvertLU(covCoordinates,covCoordinates.GetTol(),0)) {
306 TMatrixD covCoordinatesInverse = covCoordinates;
307 Double_t dX = xy[0] - xv;
308 Double_t dY = xy[1] - yv;
310 offset = TMath::Sqrt(0.5*(dX*dX*covCoordinatesInverse(0,0) +
311 dY*dY*covCoordinatesInverse(1,1) +
312 2.*dX*dY*covCoordinatesInverse(0,1)));
322 //====================================================================================================================================================
324 Double_t AliMFTAnalysisTools::GetPseudoProperDecayTimeXY(Double_t xVtx, Double_t yVtx,
325 Double_t xDimu, Double_t yDimu,
326 Double_t mDimu, Double_t ptDimu) {
328 // pseudo-proper decay time of a particle produced in the primary vertex and decaying into a dimuon (+ X)
329 // evaluated using the transverse degree of freedom of the decay topology
332 Double_t decayLengthXY = TMath::Sqrt((xVtx-xDimu)*(xVtx-xDimu)+(yVtx-yDimu)*(yVtx-yDimu));
333 return (decayLengthXY * mDimu/ptDimu)/TMath::Ccgs()*1E12; // in ps
340 //====================================================================================================================================================
342 Double_t AliMFTAnalysisTools::GetPseudoProperDecayTimeZ(Double_t zVtx,
344 Double_t mDimu, Double_t pzDimu) {
346 // pseudo-proper decay time of a particle produced in the primary vertex and decaying into a dimuon (+ X)
347 // evaluated using the longitudinal degree of freedom of the decay topology
350 Double_t decayLengthZ = zDimu - zVtx;
351 return (decayLengthZ * mDimu/pzDimu)/TMath::Ccgs()*1E12; // in ps
358 //====================================================================================================================================================
360 Bool_t AliMFTAnalysisTools::CalculatePCA(AliAODDimuon *dimuon, Double_t *pca, Double_t &pcaQuality, TLorentzVector &kinem) {
362 TObjArray *muons = new TObjArray();
363 muons -> Add(dimuon->GetMu(0));
364 muons -> Add(dimuon->GetMu(1));
366 Bool_t result = CalculatePCA(muons, pca, pcaQuality, kinem);
372 //====================================================================================================================================================
374 Bool_t AliMFTAnalysisTools::CalculatePCA(TObjArray *muons, Double_t *pca, Double_t &pcaQuality, TLorentzVector &kinem) {
376 const Int_t nMuons = muons->GetEntriesFast();
377 if (nMuons<2 || nMuons>AliMFTConstants::fNMaxMuonsForPCA) {
378 printf("W-AliMFTAnalysisTools::CalculatePCA: number of muons not valid\n");
382 Double_t fXPointOfClosestApproach=0, fYPointOfClosestApproach=0, fZPointOfClosestApproach=0;
384 AliAODTrack *muon[AliMFTConstants::fNMaxMuonsForPCA] = {0};
385 AliMUONTrackParam *param[AliMFTConstants::fNMaxMuonsForPCA] = {0};
387 // Finding AliMUONTrackParam objects for each muon
389 for (Int_t iMu=0; iMu<nMuons; iMu++) {
390 muon[iMu] = (AliAODTrack*) muons->At(iMu);
391 if (TMath::Abs(muon[iMu]->PzAtDCA())<1.e-6) {
392 for(Int_t i=0;i<iMu;i++) delete param[i];
395 param[iMu] = new AliMUONTrackParam();
396 param[iMu] -> SetNonBendingCoor(muon[iMu]->XAtDCA());
397 param[iMu] -> SetBendingCoor(muon[iMu]->YAtDCA());
398 param[iMu] -> SetZ(AliMFTConstants::fZEvalKinem);
399 param[iMu] -> SetNonBendingSlope(muon[iMu]->PxAtDCA()/muon[iMu]->PzAtDCA());
400 param[iMu] -> SetBendingSlope(muon[iMu]->PyAtDCA()/muon[iMu]->PzAtDCA());
401 param[iMu] -> SetInverseBendingMomentum( muon[iMu]->Charge() * (1./muon[iMu]->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon[iMu]->PyAtDCA()/muon[iMu]->PzAtDCA(),2))) );
404 // here we want to understand in which direction we have to search the minimum...
406 Double_t step = 1.; // initial step, in cm
407 Double_t startPoint = 0.;
409 Double_t r[3]={0}, z[3]={startPoint-step, startPoint, startPoint+step};
411 TVector3 **points = new TVector3*[AliMFTConstants::fNMaxMuonsForPCA];
413 for (Int_t i=0; i<3; i++) {
414 for (Int_t iMu=0; iMu<nMuons; iMu++) {
415 // if (TMath::Abs(param[iMu]->GetInverseBendingMomentum())<1.) {
416 // printf("W-AliMFTAnalysisTools::CalculatePCA: Evoiding floating point exception in PCA finding\n");
419 AliMUONTrackExtrap::ExtrapToZ(param[iMu], z[i]);
420 points[iMu] = new TVector3(param[iMu]->GetNonBendingCoor(),param[iMu]->GetBendingCoor(),z[i]);
422 r[i] = GetDistanceBetweenPoints(points,nMuons);
423 for (Int_t iMu=0; iMu<nMuons; iMu++) delete points[iMu];
426 Int_t researchDirection = 0;
428 if (r[0]>r[1] && r[1]>r[2]) researchDirection = +1; // towards z positive
429 else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1; // towards z negative
430 else if (r[0]<r[1] && r[1]>r[2]) {
431 printf("E-AliMFTAnalysisTools::CalculatePCA: Point of closest approach cannot be found for dimuon (no minima)\n");
432 for (Int_t iMu=0;iMu<nMuons;iMu++) delete param[iMu];
437 while (TMath::Abs(researchDirection)>0.5) {
439 if (researchDirection>0) {
442 z[2] = z[1]+researchDirection*step;
447 z[0] = z[1]+researchDirection*step;
449 if (TMath::Abs(z[0])>900.) {
450 printf("E-AliMFTAnalysisTools::CalculatePCA: Point of closest approach cannot be found for dimuon (no minima in the fiducial region)\n");
451 for (Int_t iMu=0;iMu<nMuons;iMu++) delete param[iMu];
456 for (Int_t i=0; i<3; i++) {
457 for (Int_t iMu=0; iMu<nMuons; iMu++) {
458 AliMUONTrackExtrap::ExtrapToZ(param[iMu], z[i]);
459 points[iMu] = new TVector3(param[iMu]->GetNonBendingCoor(),param[iMu]->GetBendingCoor(),z[i]);
461 r[i] = GetDistanceBetweenPoints(points,nMuons);
462 for (Int_t iMu=0;iMu<nMuons;iMu++) delete points[iMu];
465 if (r[0]>r[1] && r[1]>r[2]) researchDirection = +1; // towards z positive
466 else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1; // towards z negative
470 // now we now that the minimum is between z[0] and z[2] and we search for it
475 while (step>AliMFTConstants::fPrecisionPointOfClosestApproach) {
478 for (Int_t i=0; i<3; i++) {
479 for (Int_t iMu=0; iMu<nMuons; iMu++) {
480 AliMUONTrackExtrap::ExtrapToZ(param[iMu], z[i]);
481 points[iMu] = new TVector3(param[iMu]->GetNonBendingCoor(),param[iMu]->GetBendingCoor(),z[i]);
483 r[i] = GetDistanceBetweenPoints(points,nMuons);
484 for (Int_t iMu=0;iMu<nMuons;iMu++) delete points[iMu];
486 // printf("Step #%d : %f %f %f\n",nSteps,r[0],r[1],r[2]);
487 if (r[0]<r[1]) z[1] = z[0];
488 else if (r[2]<r[1]) z[1] = z[2];
493 // if (TMath::Abs(z[1]-1.)<0.1) {
494 // printf("Minimum found in %f in %d steps. Step = %f. p1->X() = %f, p2->X() = %f, p1->Y() = %f, p2->Y() = %f\n",
495 // z[1], nSteps, step, points[0]->X(), points[1]->X(), points[0]->Y(), points[1]->Y());
496 // printf("m1->X() = %f, m2->X() = %f, m1->Y() = %f, m2->Y() = %f\n",
497 // muon[0]->XAtDCA(),muon[1]->XAtDCA(), muon[0]->YAtDCA(),muon[1]->YAtDCA());
500 // Once z of minimum is found, we evaluate the x and y coordinates by averaging over the contributing tracks
502 fZPointOfClosestApproach = z[1];
503 fXPointOfClosestApproach = 0.;
504 fYPointOfClosestApproach = 0.;
505 for (Int_t iMu=0; iMu<nMuons; iMu++) {
506 AliMUONTrackExtrap::ExtrapToZ(param[iMu], fZPointOfClosestApproach);
507 fXPointOfClosestApproach += param[iMu]->GetNonBendingCoor();
508 fYPointOfClosestApproach += param[iMu]->GetBendingCoor();
510 fXPointOfClosestApproach /= Double_t(nMuons);
511 fYPointOfClosestApproach /= Double_t(nMuons);
513 pca[0] = fXPointOfClosestApproach;
514 pca[1] = fYPointOfClosestApproach;
515 pca[2] = fZPointOfClosestApproach;
517 // Evaluating the kinematics of the N-muon
519 Double_t pTot[3] = {0};
521 Double_t massMu = TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
522 for (Int_t iMu=0; iMu<nMuons; iMu++) {
523 pTot[0] += param[iMu]->Px();
524 pTot[1] += param[iMu]->Py();
525 pTot[2] += param[iMu]->Pz();
526 ene += TMath::Sqrt(massMu*massMu + param[iMu]->Px()*param[iMu]->Px() + param[iMu]->Py()*param[iMu]->Py() + param[iMu]->Pz()*param[iMu]->Pz());
529 kinem.SetPxPyPzE(pTot[0], pTot[1], pTot[2], ene);
531 // Evaluating the PCA quality of the N-muon
533 Double_t sum=0.,squareSum=0.;
534 for (Int_t iMu=0; iMu<nMuons; iMu++) {
535 Double_t wOffset = 0;
536 if (!GetAODMuonWeightedOffset(muon[iMu],fXPointOfClosestApproach, fYPointOfClosestApproach, fZPointOfClosestApproach, wOffset)) {
537 for(Int_t jMu=0;jMu<nMuons;jMu++) delete param[jMu];
541 Double_t f = TMath::Exp(-0.5 * wOffset);
545 if (sum > 0.) pcaQuality = (sum-squareSum/sum) / (nMuons-1);
546 else pcaQuality = 0.;
548 for(Int_t iMu=0;iMu<nMuons;iMu++) delete param[iMu];
554 //=========================================================================================================================
556 Double_t AliMFTAnalysisTools::GetDistanceBetweenPoints(TVector3 **points, Int_t nPoints) {
558 if (nPoints>AliMFTConstants::fNMaxMuonsForPCA) {
559 printf("W-AliMFTAnalysisTools::GetDistanceBetweenPoints: number of points not valid\n");
563 if (nPoints<2) return 0.;
564 if (nPoints<3) return TMath::Sqrt( (points[0]->X()-points[1]->X()) * (points[0]->X()-points[1]->X()) +
565 (points[0]->Y()-points[1]->Y()) * (points[0]->Y()-points[1]->Y()) );
566 // (points[0]->Z()-points[1]->Z()) * (points[0]->Z()-points[1]->Z()) );
568 const Int_t nEdgesMax = ((AliMFTConstants::fNMaxMuonsForPCA) * (AliMFTConstants::fNMaxMuonsForPCA - 1)) / 2;
570 Int_t startID[nEdgesMax] = {0};
571 Int_t stopID[nEdgesMax] = {0};
572 Double_t edgeLength[nEdgesMax] = {0};
574 Bool_t pointStatus[AliMFTConstants::fNMaxMuonsForPCA] = {0};
577 for (Int_t i=0; i<nPoints-1; i++) {
578 for (Int_t j=i+1; j<nPoints; j++) {
579 edgeLength[nEdges] = TMath::Sqrt( (points[i]->X()-points[j]->X()) * (points[i]->X()-points[j]->X()) +
580 (points[i]->Y()-points[j]->Y()) * (points[i]->Y()-points[j]->Y()) +
581 (points[i]->Z()-points[j]->Z()) * (points[i]->Z()-points[j]->Z()) );
593 for (Int_t iEdge=0; iEdge<nEdges-1; iEdge++) {
594 min = edgeLength[iEdge];
596 for (Int_t j=iEdge+1; j<nEdges; j++) {
597 if (edgeLength[j]<min) {
605 Double_t edgeLengthMin = edgeLength[iMin];
606 Int_t startIDmin = startID[iMin];
607 Int_t stopIDmin = stopID[iMin];
609 edgeLength[iMin] = edgeLength[iEdge];
610 startID[iMin] = startID[iEdge];
611 stopID[iMin] = stopID[iEdge];
613 edgeLength[iEdge] = edgeLengthMin;
614 startID[iEdge] = startIDmin;
615 stopID[iEdge] = stopIDmin;
623 Double_t length = 0.;
624 for (Int_t i=0; i<nEdges; i++) {
625 if (!(pointStatus[startID[i]] && pointStatus[stopID[i]])) {
626 pointStatus[startID[i]] = kTRUE;
627 pointStatus[stopID[i]] = kTRUE;
628 length += edgeLength[i];
636 //====================================================================================================================================================
638 void AliMFTAnalysisTools::ConvertCovMatrixMUON2AOD(const TMatrixD& covMUON, Double_t covAOD[21]) {
640 // Converts the cov matrix from the MUON format (TMatrixD) to the AOD one (Double_t[21])
642 // Cov(x,x) ... : cv[0]
643 // Cov(x,slopeX) ... : cv[1] cv[2]
644 // Cov(x,y) ... : cv[3] cv[4] cv[5]
645 // Cov(x,slopeY) ... : cv[6] cv[7] cv[8] cv[9]
646 // Cov(x,invP_yz) ... : cv[10] cv[11] cv[12] cv[13] cv[14]
647 // not-used ... : cv[15] cv[16] cv[17] cv[18] cv[19] cv[20]
649 covAOD[0] = covMUON(0,0);
651 covAOD[1] = covMUON(1,0);
652 covAOD[2] = covMUON(1,1);
654 covAOD[3] = covMUON(2,0);
655 covAOD[4] = covMUON(2,1);
656 covAOD[5] = covMUON(2,2);
658 covAOD[6] = covMUON(3,0);
659 covAOD[7] = covMUON(3,1);
660 covAOD[8] = covMUON(3,2);
661 covAOD[9] = covMUON(3,3);
663 covAOD[10] = covMUON(4,0);
664 covAOD[11] = covMUON(4,1);
665 covAOD[12] = covMUON(4,2);
666 covAOD[13] = covMUON(4,3);
667 covAOD[14] = covMUON(4,4);
678 //====================================================================================================================================================
680 const TMatrixD AliMFTAnalysisTools::ConvertCovMatrixAOD2MUON(AliAODTrack *muon) {
682 Double_t covAOD[21] = {0};
683 muon -> GetCovarianceXYZPxPyPz(covAOD);
685 TMatrixD covMUON(5,5);
687 covMUON(0,0) = covAOD[0];
689 covMUON(1,0) = covAOD[1];
690 covMUON(1,1) = covAOD[2];
692 covMUON(2,0) = covAOD[3];
693 covMUON(2,1) = covAOD[4];
694 covMUON(2,2) = covAOD[5];
696 covMUON(3,0) = covAOD[6];
697 covMUON(3,1) = covAOD[7];
698 covMUON(3,2) = covAOD[8];
699 covMUON(3,3) = covAOD[9];
701 covMUON(4,0) = covAOD[10];
702 covMUON(4,1) = covAOD[11];
703 covMUON(4,2) = covAOD[12];
704 covMUON(4,3) = covAOD[13];
705 covMUON(4,4) = covAOD[14];
711 //====================================================================================================================================================
713 Bool_t AliMFTAnalysisTools::IsCorrectMatch(AliAODTrack *muon) {
715 for (Int_t iPlane=0; iPlane<AliMFTConstants::fNMaxPlanes; iPlane++) if (IsWrongCluster(muon, iPlane)) return kFALSE;
720 //====================================================================================================================================================
722 TString AliMFTAnalysisTools::GetGenerator(Int_t label, AliAODMCHeader* header) {
724 // get the name of the generator that produced a given particle
726 Int_t partCounter = 0;
727 TList *genHeaders = header->GetCocktailHeaders();
728 Int_t nGenHeaders = genHeaders->GetEntries();
730 for (Int_t i=0; i<nGenHeaders; i++){
731 AliGenEventHeader *gh = (AliGenEventHeader*) genHeaders->At(i);
732 TString genName = gh->GetName();
733 Int_t nPart = gh->NProduced();
734 if (label>=partCounter && label<(partCounter+nPart)) return genName;
735 partCounter += nPart;
743 //====================================================================================================================================================
745 void AliMFTAnalysisTools::GetTrackPrimaryGenerator(AliAODTrack *track, AliAODMCHeader *header, TClonesArray *arrayMC, TString &nameGen) {
747 // method to check if a track comes from a given generator
749 Int_t label = TMath::Abs(track->GetLabel());
750 nameGen = GetGenerator(label,header);
752 // In case the particle is not primary nameGen will contain blank spaces. In this case, we search backward for the primary which originated the chain
754 while (nameGen.IsWhitespace()) {
755 AliAODMCParticle *mcPart = (AliAODMCParticle*) arrayMC->At(label);
757 printf("AliMFTAnalysisTools::GetTrackPrimaryGenerator - BREAK: No valid AliAODMCParticle at label %i\n",label);
760 Int_t motherLabel = mcPart->GetMother();
761 if (motherLabel < 0) {
762 printf("AliMFTAnalysisTools::GetTrackPrimaryGenerator - BREAK: Reached primary particle without valid mother\n");
766 nameGen = GetGenerator(label,header);
773 //====================================================================================================================================================
775 Bool_t AliMFTAnalysisTools::IsTrackInjected(AliAODTrack *track, AliAODMCHeader *header, TClonesArray *arrayMC) {
777 // method to check if a track comes from the signal event or from the underlying Hijing event
781 GetTrackPrimaryGenerator(track,header,arrayMC,nameGen);
783 if (nameGen.IsWhitespace() || nameGen.Contains("ijing")) return kFALSE;
789 //====================================================================================================================================================
791 Bool_t AliMFTAnalysisTools::TranslateMuon(AliAODTrack *muon, Double_t vtxInitial[3], Double_t vtxFinal[3]) {
793 if (!(muon->PzAtDCA()!=0)) return kFALSE;
795 AliMUONTrackParam *param = new AliMUONTrackParam();
797 Double_t deltaVtx[3] = {0};
798 for (Int_t i=0; i<3; i++) deltaVtx[i] = vtxInitial[i] - vtxFinal[i];
800 param -> SetNonBendingCoor(muon->XAtDCA());
801 param -> SetBendingCoor(muon->YAtDCA());
802 param -> SetZ(AliMFTConstants::fZEvalKinem);
803 param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
804 param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
805 param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
807 // This will be interpreted as if the track (produced in an event having the primary vertex in vtxInitial)
808 // were produced in an event having the primary vertex in vtxFinal
810 AliMUONTrackExtrap::ExtrapToZ(param, deltaVtx[2]);
811 muon->SetXYAtDCA(param->GetNonBendingCoor() - deltaVtx[0], param->GetBendingCoor() - deltaVtx[1]);
812 muon->SetPxPyPzAtDCA(param->Px(), param->Py(), param->Pz());
820 //====================================================================================================================================================
822 Bool_t AliMFTAnalysisTools::TranslateMuonToOrigin(AliAODTrack *muon, Double_t vtx[3]) {
824 Double_t origin[3] = {0,0,0};
826 return TranslateMuon(muon, vtx, origin);
830 //====================================================================================================================================================
832 Bool_t AliMFTAnalysisTools::IsPDGCharm(Int_t pdgCode) {
834 pdgCode = TMath::Abs(pdgCode/100);
835 if (pdgCode>9) pdgCode /= 10;
836 if (pdgCode == 4 ) return kTRUE;
841 //====================================================================================================================================================
843 Bool_t AliMFTAnalysisTools::IsPDGBeauty(Int_t pdgCode) {
845 pdgCode = TMath::Abs(pdgCode/100);
846 if (pdgCode>9) pdgCode /= 10;
847 if (pdgCode == 5) return kTRUE;
852 //====================================================================================================================================================
854 Bool_t AliMFTAnalysisTools::IsPDGResonance(Int_t pdgCode) {
856 Int_t id = pdgCode%100000;
857 return (!((id-id%10)%110));
861 //====================================================================================================================================================