LCOV - code coverage report
Current view: top level - ITSMFT/MFT/MFTbase - AliMFTAnalysisTools.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 410 0.2 %
Date: 2016-06-14 17:26:59 Functions: 1 25 4.0 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       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 purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : //====================================================================================================================================================
      17             : //
      18             : //      Support class for various common operation on MFT objects
      19             : //
      20             : //      Contact author: antonio.uras@cern.ch
      21             : //
      22             : //====================================================================================================================================================
      23             : 
      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"
      31             : #include "TMath.h"
      32             : #include "AliLog.h"
      33             : #include "TObjArray.h"
      34             : #include "TDecompLU.h"
      35             : #include "TRandom.h"
      36             : 
      37             : #include "AliMFTAnalysisTools.h"
      38             : 
      39          14 : ClassImp(AliMFTAnalysisTools)
      40             : 
      41             : //====================================================================================================================================================
      42             : 
      43             : Bool_t AliMFTAnalysisTools::ExtrapAODMuonToZ(AliAODTrack *muon, Double_t z, Double_t xy[2]) {
      44             : 
      45           0 :   if (!(muon->PzAtDCA()!=0)) return kFALSE;
      46             : 
      47           0 :   AliMUONTrackParam *param = new AliMUONTrackParam();
      48             : 
      49           0 :   param -> SetNonBendingCoor(muon->XAtDCA());
      50           0 :   param -> SetBendingCoor(muon->YAtDCA());
      51           0 :   param -> SetZ(AliMFTConstants::fZEvalKinem);
      52           0 :   param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
      53           0 :   param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
      54           0 :   param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
      55             : 
      56           0 :   AliMUONTrackExtrap::ExtrapToZ(param, z);
      57           0 :   xy[0] = param->GetNonBendingCoor();
      58           0 :   xy[1] = param->GetBendingCoor();
      59             : 
      60           0 :   delete param;
      61             : 
      62             :   return kTRUE;
      63             : 
      64           0 : }
      65             : 
      66             : //====================================================================================================================================================
      67             : 
      68             : Bool_t AliMFTAnalysisTools::ExtrapAODMuonToZ(AliAODTrack *muon, Double_t z, Double_t xy[2], TLorentzVector &kinem) {
      69             : 
      70           0 :   if (!(muon->PzAtDCA()!=0)) return kFALSE;
      71             : 
      72           0 :   AliMUONTrackParam *param = new AliMUONTrackParam();
      73             : 
      74           0 :   param -> SetNonBendingCoor(muon->XAtDCA());
      75           0 :   param -> SetBendingCoor(muon->YAtDCA());
      76           0 :   param -> SetZ(AliMFTConstants::fZEvalKinem);
      77           0 :   param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
      78           0 :   param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
      79           0 :   param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
      80             : 
      81           0 :   AliMUONTrackExtrap::ExtrapToZ(param, z);
      82           0 :   xy[0] = param->GetNonBendingCoor();
      83           0 :   xy[1] = param->GetBendingCoor();
      84             : 
      85           0 :   Double_t massMu = TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
      86           0 :   Double_t energy = TMath::Sqrt(massMu*massMu + param->Px()*param->Px() + param->Py()*param->Py() + param->Pz()*param->Pz());
      87             :   
      88           0 :   kinem.SetPxPyPzE(param->Px(), param->Py(), param->Pz(), energy);
      89             : 
      90           0 :   delete param;
      91             : 
      92             :   return kTRUE;
      93             : 
      94           0 : }
      95             : 
      96             : //====================================================================================================================================================
      97             : 
      98             : Bool_t AliMFTAnalysisTools::ExtrapAODMuonToZ(AliAODTrack *muon, Double_t z, Double_t xy[2], TLorentzVector &kinem, TMatrixD &cov) {
      99             : 
     100             :   // Extrapolate muon to a given z providing the corresponding (x,y) position and updating kinematics and covariance matrix
     101             : 
     102           0 :   if (!(muon->PzAtDCA()!=0)) return kFALSE;
     103             : 
     104           0 :   AliMUONTrackParam *param = new AliMUONTrackParam();
     105             : 
     106           0 :   param -> SetNonBendingCoor(muon->XAtDCA());
     107           0 :   param -> SetBendingCoor(muon->YAtDCA());
     108           0 :   param -> SetZ(AliMFTConstants::fZEvalKinem);
     109           0 :   param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
     110           0 :   param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
     111           0 :   param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
     112             : 
     113           0 :   param -> SetCovariances(ConvertCovMatrixAOD2MUON(muon));
     114             : 
     115           0 :   AliMUONTrackExtrap::ExtrapToZCov(param, z);
     116           0 :   xy[0] = param->GetNonBendingCoor();
     117           0 :   xy[1] = param->GetBendingCoor();
     118             : 
     119           0 :   Double_t massMu = TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
     120           0 :   Double_t energy = TMath::Sqrt(massMu*massMu + param->Px()*param->Px() + param->Py()*param->Py() + param->Pz()*param->Pz());
     121             :   
     122           0 :   kinem.SetPxPyPzE(param->Px(), param->Py(), param->Pz(), energy);
     123             : 
     124           0 :   cov = param->GetCovariances();
     125             : 
     126           0 :   delete param;
     127             : 
     128             :   return kTRUE;
     129             : 
     130           0 : }
     131             : 
     132             : //====================================================================================================================================================
     133             : 
     134             : Bool_t AliMFTAnalysisTools::ExtrapAODMuonToXY(AliAODTrack *muon, Double_t xy[2], Double_t &zFinal, TLorentzVector &kinem, TMatrixD &cov) {
     135             : 
     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
     138             : 
     139             :   // We look for the above-defined PCA
     140             : 
     141           0 :   AliMUONTrackParam *param = new AliMUONTrackParam();
     142           0 :   param -> SetNonBendingCoor(muon->XAtDCA());
     143           0 :   param -> SetBendingCoor(muon->YAtDCA());
     144           0 :   param -> SetZ(AliMFTConstants::fZEvalKinem);
     145           0 :   param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
     146           0 :   param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
     147           0 :   param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
     148             :   
     149             :   // here we want to understand in which direction we have to search the minimum...
     150             :   
     151             :   Double_t step = 1.;  // initial step, in cm
     152             :   Double_t startPoint = 0.;
     153             :   
     154           0 :   Double_t r[3]={0}, z[3]={startPoint-step, startPoint, startPoint+step};
     155             :   
     156           0 :   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)
     157             :   
     158           0 :   for (Int_t i=0; i<3; i++) {
     159           0 :     AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
     160           0 :     points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
     161           0 :     points[1] = new TVector3(xy[0],xy[1],z[i]);
     162           0 :     r[i] = GetDistanceBetweenPoints(points,2);
     163           0 :     for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
     164             :   }
     165             :   
     166             :   Int_t researchDirection = 0;
     167             :   
     168           0 :   if      (r[0]>r[1] && r[1]>r[2]) researchDirection = +1;   // towards z positive
     169           0 :   else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1;   // towards z negative
     170           0 :   else if (r[0]<r[1] && r[1]>r[2]) {
     171           0 :     printf("E-AliMFTAnalysisTools::ExtrapAODMuonToXY: Point of closest approach cannot be found (no minima)\n");
     172           0 :     delete param;
     173           0 :     delete points;
     174           0 :     return kFALSE;
     175             :   }
     176             :   
     177           0 :   while (TMath::Abs(researchDirection)>0.5) {
     178             :       
     179           0 :     if (researchDirection>0) {
     180           0 :       z[0] = z[1];
     181           0 :       z[1] = z[2];
     182           0 :       z[2] = z[1]+researchDirection*step;
     183           0 :     }
     184             :     else {
     185           0 :       z[2] = z[1];
     186           0 :       z[1] = z[0];
     187           0 :       z[0] = z[1]+researchDirection*step;
     188             :     }
     189           0 :     if (TMath::Abs(z[0])>900.) {
     190           0 :       printf("E-AliMFTAnalysisTools::ExtrapAODMuonToXY: Point of closest approach cannot be found (no minima in the fiducial region)\n");
     191           0 :       delete param;
     192           0 :       delete points;
     193           0 :       return kFALSE;
     194             :     }
     195             :     
     196           0 :     for (Int_t i=0; i<3; i++) {
     197           0 :       AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
     198           0 :       points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
     199           0 :       points[1] = new TVector3(xy[0],xy[1],z[i]);
     200           0 :       r[i] = GetDistanceBetweenPoints(points,2);
     201           0 :       for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
     202             :     }
     203             : 
     204             :     researchDirection=0;
     205           0 :     if      (r[0]>r[1] && r[1]>r[2]) researchDirection = +1;   // towards z positive
     206           0 :     else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1;   // towards z negative
     207             :     
     208             :   }
     209             :   
     210             :   // now we now that the minimum is between z[0] and z[2] and we search for it
     211             :   
     212             :   step *= 0.5;
     213           0 :   while (step>AliMFTConstants::fPrecisionPointOfClosestApproach) {
     214           0 :     z[0] = z[1]-step;
     215           0 :     z[2] = z[1]+step;
     216           0 :     for (Int_t i=0; i<3; i++) {
     217           0 :       AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
     218           0 :       points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
     219           0 :       points[1] = new TVector3(xy[0],xy[1],z[i]);
     220           0 :       r[i] = GetDistanceBetweenPoints(points,2);
     221           0 :       for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
     222             :     }
     223           0 :     if      (r[0]<r[1]) z[1] = z[0];
     224           0 :     else if (r[2]<r[1]) z[1] = z[2];
     225           0 :     else step *= 0.5;
     226             :   }
     227             :   
     228           0 :   zFinal = z[1];
     229             : 
     230           0 :   Double_t xyMuon[2] = {0};
     231           0 :   ExtrapAODMuonToZ(muon, zFinal, xyMuon, kinem, cov);
     232             : 
     233             :   return kTRUE;
     234             : 
     235           0 : }
     236             : 
     237             : //====================================================================================================================================================
     238             : 
     239             : Bool_t AliMFTAnalysisTools::GetAODMuonOffset(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv, Double_t &offset) {
     240             : 
     241           0 :   Double_t xy[2] = {0};
     242           0 :   ExtrapAODMuonToZ(muon, zv, xy);
     243             :   
     244           0 :   offset = TMath::Sqrt((xv-xy[0])*(xv-xy[0]) + (yv-xy[1])*(yv-xy[1]));
     245             : 
     246           0 :   return kTRUE;
     247             : 
     248           0 : }
     249             : 
     250             : //====================================================================================================================================================
     251             : 
     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) {
     254             : 
     255             :   // Evaluate transverse offset adding to it an additional smearing (independently along the x and y directions)
     256             :   
     257           0 :   Double_t xy[2] = {0};
     258           0 :   ExtrapAODMuonToZ(muon, zv, xy);
     259             : 
     260           0 :   xy[0] = gRandom->Gaus(xy[0], smearOffsetX);
     261           0 :   xy[1] = gRandom->Gaus(xy[1], smearOffsetY);
     262             :   
     263           0 :   offset = TMath::Sqrt((xv-xy[0])*(xv-xy[0]) + (yv-xy[1])*(yv-xy[1]));
     264             : 
     265           0 :   return kTRUE;
     266             : 
     267           0 : }
     268             : 
     269             : //====================================================================================================================================================
     270             : 
     271             : Bool_t AliMFTAnalysisTools::GetAODMuonOffsetZ(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv, Double_t &offset) {
     272             : 
     273           0 :   Double_t xy[2] = {xv, yv};
     274           0 :   Double_t zFinal = 0;
     275           0 :   TLorentzVector kinem(0,0,0,0);
     276           0 :   TMatrixD cov(5,5);
     277             : 
     278           0 :   ExtrapAODMuonToXY(muon, xy, zFinal, kinem, cov);
     279             : 
     280           0 :   offset = TMath::Abs(zFinal - zv);
     281             : 
     282             :   return kTRUE;
     283             : 
     284           0 : }
     285             : 
     286             : //====================================================================================================================================================
     287             : 
     288             : Bool_t AliMFTAnalysisTools::GetAODMuonWeightedOffset(AliAODTrack *muon, Double_t xv, Double_t yv, Double_t zv, Double_t &offset) {
     289             : 
     290           0 :   Double_t xy[2] = {0};
     291           0 :   TLorentzVector kinem(0,0,0,0);
     292           0 :   TMatrixD cov(5,5);
     293             : 
     294           0 :   ExtrapAODMuonToZ(muon, zv, xy, kinem, cov);
     295             : 
     296           0 :   TMatrixD covCoordinates(2,2);
     297           0 :   covCoordinates(0,0) = cov(0,0);
     298           0 :   covCoordinates(0,1) = cov(0,2);
     299           0 :   covCoordinates(1,0) = cov(2,0);
     300           0 :   covCoordinates(1,1) = cov(2,2);
     301             :   
     302           0 :   if (covCoordinates.Determinant() < covCoordinates.GetTol()) return kFALSE;
     303             : 
     304           0 :   if (TDecompLU::InvertLU(covCoordinates,covCoordinates.GetTol(),0)) {
     305             : 
     306           0 :     TMatrixD covCoordinatesInverse = covCoordinates;
     307           0 :     Double_t dX = xy[0] - xv;
     308           0 :     Double_t dY = xy[1] - yv;
     309             :     
     310           0 :     offset = TMath::Sqrt(0.5*(dX*dX*covCoordinatesInverse(0,0) +
     311           0 :                               dY*dY*covCoordinatesInverse(1,1) +
     312           0 :                               2.*dX*dY*covCoordinatesInverse(0,1)));
     313             :     
     314             :     return kTRUE;
     315             : 
     316           0 :   }
     317             :   
     318           0 :   return kFALSE;
     319             : 
     320           0 : }
     321             : 
     322             : //====================================================================================================================================================
     323             : 
     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) {
     327             :   
     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 
     330             : 
     331           0 :   if (ptDimu != 0) {
     332           0 :     Double_t decayLengthXY = TMath::Sqrt((xVtx-xDimu)*(xVtx-xDimu)+(yVtx-yDimu)*(yVtx-yDimu));
     333           0 :     return (decayLengthXY * mDimu/ptDimu)/TMath::Ccgs()*1E12;   // in ps
     334             :   }
     335             :   
     336           0 :   return -99999999;
     337             :   
     338           0 : }
     339             : 
     340             : //====================================================================================================================================================
     341             : 
     342             : Double_t AliMFTAnalysisTools::GetPseudoProperDecayTimeZ(Double_t zVtx, 
     343             :                                                         Double_t zDimu, 
     344             :                                                         Double_t mDimu, Double_t pzDimu) {
     345             : 
     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 
     348             : 
     349           0 :   if (pzDimu != 0) {
     350           0 :     Double_t decayLengthZ = zDimu - zVtx;
     351           0 :     return (decayLengthZ * mDimu/pzDimu)/TMath::Ccgs()*1E12;  // in ps
     352             :   }
     353             : 
     354           0 :   return -99999999;
     355             : 
     356           0 : }
     357             : 
     358             : //====================================================================================================================================================
     359             : 
     360             : Bool_t AliMFTAnalysisTools::CalculatePCA(AliAODDimuon *dimuon, Double_t *pca, Double_t &pcaQuality, TLorentzVector &kinem) {
     361             : 
     362           0 :   TObjArray *muons = new TObjArray();
     363           0 :   muons -> Add(dimuon->GetMu(0));
     364           0 :   muons -> Add(dimuon->GetMu(1));
     365             :   
     366           0 :   Bool_t result = CalculatePCA(muons, pca, pcaQuality, kinem);
     367           0 :   delete muons;
     368           0 :   return result;
     369             : 
     370           0 : }
     371             : 
     372             : //====================================================================================================================================================
     373             : 
     374             : Bool_t AliMFTAnalysisTools::CalculatePCA(TObjArray *muons, Double_t *pca, Double_t &pcaQuality, TLorentzVector &kinem) {
     375             :   
     376           0 :   const Int_t nMuons = muons->GetEntriesFast();
     377           0 :   if (nMuons<2 || nMuons>AliMFTConstants::fNMaxMuonsForPCA) {
     378           0 :     printf("W-AliMFTAnalysisTools::CalculatePCA: number of muons not valid\n");
     379           0 :     return kFALSE;
     380             :   }
     381             : 
     382             :   Double_t fXPointOfClosestApproach=0, fYPointOfClosestApproach=0, fZPointOfClosestApproach=0;
     383             : 
     384           0 :   AliAODTrack *muon[AliMFTConstants::fNMaxMuonsForPCA]        = {0};
     385           0 :   AliMUONTrackParam *param[AliMFTConstants::fNMaxMuonsForPCA] = {0};
     386             : 
     387             :   // Finding AliMUONTrackParam objects for each muon
     388             :   
     389           0 :   for (Int_t iMu=0; iMu<nMuons; iMu++) {
     390           0 :     muon[iMu] = (AliAODTrack*) muons->At(iMu);
     391           0 :     if (TMath::Abs(muon[iMu]->PzAtDCA())<1.e-6) {
     392           0 :       for(Int_t i=0;i<iMu;i++) delete param[i];
     393           0 :       return kFALSE;
     394             :     }
     395           0 :     param[iMu] = new AliMUONTrackParam();
     396           0 :     param[iMu] -> SetNonBendingCoor(muon[iMu]->XAtDCA());
     397           0 :     param[iMu] -> SetBendingCoor(muon[iMu]->YAtDCA());
     398           0 :     param[iMu] -> SetZ(AliMFTConstants::fZEvalKinem);
     399           0 :     param[iMu] -> SetNonBendingSlope(muon[iMu]->PxAtDCA()/muon[iMu]->PzAtDCA());
     400           0 :     param[iMu] -> SetBendingSlope(muon[iMu]->PyAtDCA()/muon[iMu]->PzAtDCA());
     401           0 :     param[iMu] -> SetInverseBendingMomentum( muon[iMu]->Charge() * (1./muon[iMu]->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon[iMu]->PyAtDCA()/muon[iMu]->PzAtDCA(),2))) );
     402             :   }
     403             :   
     404             :   // here we want to understand in which direction we have to search the minimum...
     405             :   
     406             :   Double_t step = 1.;  // initial step, in cm
     407             :   Double_t startPoint = 0.;
     408             :   
     409           0 :   Double_t r[3]={0}, z[3]={startPoint-step, startPoint, startPoint+step};
     410             :   
     411           0 :   TVector3 **points = new TVector3*[AliMFTConstants::fNMaxMuonsForPCA];
     412             :   
     413           0 :   for (Int_t i=0; i<3; i++) {
     414           0 :     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");
     417             :       //        return kFALSE;
     418             :       // }
     419           0 :       AliMUONTrackExtrap::ExtrapToZ(param[iMu], z[i]);
     420           0 :       points[iMu] = new TVector3(param[iMu]->GetNonBendingCoor(),param[iMu]->GetBendingCoor(),z[i]);
     421             :     }
     422           0 :     r[i] = GetDistanceBetweenPoints(points,nMuons);
     423           0 :     for (Int_t iMu=0; iMu<nMuons; iMu++) delete points[iMu]; 
     424             :   }
     425             :   
     426             :   Int_t researchDirection = 0;
     427             :   
     428           0 :   if      (r[0]>r[1] && r[1]>r[2]) researchDirection = +1;   // towards z positive
     429           0 :   else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1;   // towards z negative
     430           0 :   else if (r[0]<r[1] && r[1]>r[2]) {
     431           0 :     printf("E-AliMFTAnalysisTools::CalculatePCA: Point of closest approach cannot be found for dimuon (no minima)\n");
     432           0 :     for (Int_t iMu=0;iMu<nMuons;iMu++) delete param[iMu];
     433           0 :     delete points;
     434           0 :     return kFALSE;
     435             :   }     
     436             :   
     437           0 :   while (TMath::Abs(researchDirection)>0.5) {
     438             :       
     439           0 :     if (researchDirection>0) {
     440           0 :       z[0] = z[1];
     441           0 :       z[1] = z[2];
     442           0 :       z[2] = z[1]+researchDirection*step;
     443           0 :     }
     444             :     else {
     445           0 :       z[2] = z[1];
     446           0 :       z[1] = z[0];
     447           0 :       z[0] = z[1]+researchDirection*step;
     448             :     }
     449           0 :     if (TMath::Abs(z[0])>900.) {
     450           0 :       printf("E-AliMFTAnalysisTools::CalculatePCA: Point of closest approach cannot be found for dimuon (no minima in the fiducial region)\n");
     451           0 :       for (Int_t iMu=0;iMu<nMuons;iMu++) delete param[iMu];
     452           0 :       delete points;
     453           0 :       return kFALSE;
     454             :     }
     455             :     
     456           0 :     for (Int_t i=0; i<3; i++) {
     457           0 :       for (Int_t iMu=0; iMu<nMuons; iMu++) {
     458           0 :         AliMUONTrackExtrap::ExtrapToZ(param[iMu], z[i]);
     459           0 :         points[iMu] = new TVector3(param[iMu]->GetNonBendingCoor(),param[iMu]->GetBendingCoor(),z[i]);
     460             :       }      
     461           0 :       r[i] = GetDistanceBetweenPoints(points,nMuons);
     462           0 :       for (Int_t iMu=0;iMu<nMuons;iMu++) delete points[iMu];
     463             :     }
     464             :     researchDirection=0;
     465           0 :     if      (r[0]>r[1] && r[1]>r[2]) researchDirection = +1;   // towards z positive
     466           0 :     else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1;   // towards z negative
     467             :     
     468             :   }
     469             :   
     470             :   // now we now that the minimum is between z[0] and z[2] and we search for it
     471             :   
     472             :   Int_t nSteps = 0;
     473             : 
     474             :   step *= 0.5;
     475           0 :   while (step>AliMFTConstants::fPrecisionPointOfClosestApproach) {
     476           0 :     z[0] = z[1]-step;
     477           0 :     z[2] = z[1]+step;
     478           0 :     for (Int_t i=0; i<3; i++) {
     479           0 :       for (Int_t iMu=0; iMu<nMuons; iMu++) {
     480           0 :         AliMUONTrackExtrap::ExtrapToZ(param[iMu], z[i]);
     481           0 :         points[iMu] = new TVector3(param[iMu]->GetNonBendingCoor(),param[iMu]->GetBendingCoor(),z[i]);
     482             :       }      
     483           0 :       r[i] = GetDistanceBetweenPoints(points,nMuons);
     484           0 :       for (Int_t iMu=0;iMu<nMuons;iMu++) delete points[iMu];
     485             :     }
     486             :     //    printf("Step #%d : %f  %f  %f\n",nSteps,r[0],r[1],r[2]);
     487           0 :     if      (r[0]<r[1]) z[1] = z[0];
     488           0 :     else if (r[2]<r[1]) z[1] = z[2];
     489           0 :     else step *= 0.5;
     490           0 :     nSteps++;
     491             :   }
     492             : 
     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());
     498             :   // }
     499             : 
     500             :   // Once z of minimum is found, we evaluate the x and y coordinates by averaging over the contributing tracks
     501             :   
     502             :   fZPointOfClosestApproach = z[1];
     503             :   fXPointOfClosestApproach = 0.;
     504             :   fYPointOfClosestApproach = 0.;
     505           0 :   for (Int_t iMu=0; iMu<nMuons; iMu++) {
     506           0 :     AliMUONTrackExtrap::ExtrapToZ(param[iMu], fZPointOfClosestApproach);
     507           0 :     fXPointOfClosestApproach += param[iMu]->GetNonBendingCoor();
     508           0 :     fYPointOfClosestApproach += param[iMu]->GetBendingCoor();
     509             :   }
     510           0 :   fXPointOfClosestApproach /= Double_t(nMuons);
     511           0 :   fYPointOfClosestApproach /= Double_t(nMuons);
     512             :   
     513           0 :   pca[0] = fXPointOfClosestApproach;
     514           0 :   pca[1] = fYPointOfClosestApproach;
     515           0 :   pca[2] = fZPointOfClosestApproach;
     516             :   
     517             :   // Evaluating the kinematics of the N-muon
     518             :   
     519             :   Double_t pTot[3] = {0};
     520             :   Double_t ene = 0.;
     521           0 :   Double_t massMu = TDatabasePDG::Instance()->GetParticle("mu-")->Mass();
     522           0 :   for (Int_t iMu=0; iMu<nMuons; iMu++) {
     523           0 :     pTot[0] += param[iMu]->Px();
     524           0 :     pTot[1] += param[iMu]->Py();
     525           0 :     pTot[2] += param[iMu]->Pz();
     526           0 :     ene += TMath::Sqrt(massMu*massMu + param[iMu]->Px()*param[iMu]->Px() + param[iMu]->Py()*param[iMu]->Py() + param[iMu]->Pz()*param[iMu]->Pz());
     527             :   }
     528             :   
     529           0 :   kinem.SetPxPyPzE(pTot[0], pTot[1], pTot[2], ene);
     530             :   
     531             :   // Evaluating the PCA quality of the N-muon
     532             :   
     533             :   Double_t sum=0.,squareSum=0.;
     534           0 :   for (Int_t iMu=0; iMu<nMuons; iMu++) {
     535           0 :     Double_t wOffset = 0;
     536           0 :     if (!GetAODMuonWeightedOffset(muon[iMu],fXPointOfClosestApproach, fYPointOfClosestApproach, fZPointOfClosestApproach, wOffset)) {
     537           0 :       for(Int_t jMu=0;jMu<nMuons;jMu++) delete param[jMu];
     538           0 :       delete points;
     539           0 :       return kFALSE;
     540             :     }
     541           0 :     Double_t f = TMath::Exp(-0.5 * wOffset);
     542           0 :     sum += f;
     543           0 :     squareSum += f*f;
     544           0 :   }
     545           0 :   if (sum > 0.) pcaQuality =  (sum-squareSum/sum) / (nMuons-1);
     546           0 :   else pcaQuality = 0.;
     547             :   
     548           0 :   for(Int_t iMu=0;iMu<nMuons;iMu++) delete param[iMu];
     549           0 :   delete points;
     550           0 :   return kTRUE;
     551             :   
     552           0 : }
     553             : 
     554             : //=========================================================================================================================
     555             : 
     556             : Double_t AliMFTAnalysisTools::GetDistanceBetweenPoints(TVector3 **points, Int_t nPoints) {
     557             :   
     558           0 :   if (nPoints>AliMFTConstants::fNMaxMuonsForPCA) {
     559           0 :     printf("W-AliMFTAnalysisTools::GetDistanceBetweenPoints: number of points not valid\n");
     560           0 :     return 1.e9;
     561             :   }
     562             :   
     563           0 :   if (nPoints<2) return 0.;
     564           0 :   if (nPoints<3) return TMath::Sqrt( (points[0]->X()-points[1]->X()) * (points[0]->X()-points[1]->X()) +
     565           0 :                                      (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()) );
     567             : 
     568             :   const Int_t nEdgesMax = ((AliMFTConstants::fNMaxMuonsForPCA) * (AliMFTConstants::fNMaxMuonsForPCA - 1)) / 2;
     569             :   
     570           0 :   Int_t startID[nEdgesMax]       = {0};
     571           0 :   Int_t stopID[nEdgesMax]        = {0};
     572           0 :   Double_t edgeLength[nEdgesMax] = {0};
     573             : 
     574           0 :   Bool_t pointStatus[AliMFTConstants::fNMaxMuonsForPCA] = {0};
     575             :   
     576             :   Int_t nEdges=0;
     577           0 :   for (Int_t i=0; i<nPoints-1; i++) {
     578           0 :     for (Int_t j=i+1; j<nPoints; j++) {
     579           0 :       edgeLength[nEdges] = TMath::Sqrt( (points[i]->X()-points[j]->X()) * (points[i]->X()-points[j]->X()) +
     580           0 :                                         (points[i]->Y()-points[j]->Y()) * (points[i]->Y()-points[j]->Y()) +
     581           0 :                                         (points[i]->Z()-points[j]->Z()) * (points[i]->Z()-points[j]->Z()) );
     582           0 :       stopID[nEdges]  = i;
     583           0 :       startID[nEdges] = j;
     584           0 :       nEdges++;
     585             :     }
     586             :   }
     587             :  
     588             :   // Order Edges
     589             : 
     590             :   Double_t min = 0;
     591             :   Int_t   iMin = 0;
     592             : 
     593           0 :   for (Int_t iEdge=0; iEdge<nEdges-1; iEdge++) {
     594           0 :     min  = edgeLength[iEdge];
     595             :     iMin = iEdge;
     596           0 :     for (Int_t j=iEdge+1; j<nEdges; j++) {
     597           0 :       if (edgeLength[j]<min) {
     598             :         min  = edgeLength[j];
     599             :         iMin = j;
     600           0 :       }
     601             :     }
     602             :     
     603           0 :     if (iMin != iEdge) {
     604             : 
     605           0 :       Double_t edgeLengthMin = edgeLength[iMin];
     606           0 :       Int_t startIDmin = startID[iMin];
     607           0 :       Int_t stopIDmin  = stopID[iMin];
     608             :       
     609           0 :       edgeLength[iMin] = edgeLength[iEdge];
     610           0 :       startID[iMin]    = startID[iEdge];
     611           0 :       stopID[iMin]     = stopID[iEdge];
     612             : 
     613           0 :       edgeLength[iEdge] = edgeLengthMin;
     614           0 :       startID[iEdge]    = startIDmin;
     615           0 :       stopID[iEdge]     = stopIDmin;
     616             : 
     617           0 :     }
     618             :     
     619             :   }
     620             :   
     621             :   // Connect
     622             : 
     623             :   Double_t length = 0.;
     624           0 :   for (Int_t i=0; i<nEdges; i++) {
     625           0 :     if (!(pointStatus[startID[i]] && pointStatus[stopID[i]])) {
     626           0 :       pointStatus[startID[i]] = kTRUE;
     627           0 :       pointStatus[stopID[i]]  = kTRUE;
     628           0 :       length += edgeLength[i];
     629           0 :     }
     630             :   }
     631             :   
     632             :   return length;
     633             :   
     634           0 : }
     635             : 
     636             : //====================================================================================================================================================
     637             : 
     638             : void AliMFTAnalysisTools::ConvertCovMatrixMUON2AOD(const TMatrixD& covMUON, Double_t covAOD[21]) {
     639             : 
     640             :   // Converts the cov matrix from the MUON format (TMatrixD) to the AOD one (Double_t[21])
     641             :   // 
     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]
     648             : 
     649           0 :   covAOD[0]  = covMUON(0,0);
     650             : 
     651           0 :   covAOD[1]  = covMUON(1,0);
     652           0 :   covAOD[2]  = covMUON(1,1);
     653             : 
     654           0 :   covAOD[3]  = covMUON(2,0);  
     655           0 :   covAOD[4]  = covMUON(2,1);  
     656           0 :   covAOD[5]  = covMUON(2,2);  
     657             : 
     658           0 :   covAOD[6]  = covMUON(3,0);  
     659           0 :   covAOD[7]  = covMUON(3,1);  
     660           0 :   covAOD[8]  = covMUON(3,2);  
     661           0 :   covAOD[9]  = covMUON(3,3);  
     662             : 
     663           0 :   covAOD[10] = covMUON(4,0);  
     664           0 :   covAOD[11] = covMUON(4,1);  
     665           0 :   covAOD[12] = covMUON(4,2);  
     666           0 :   covAOD[13] = covMUON(4,3);  
     667           0 :   covAOD[14] = covMUON(4,4);  
     668             : 
     669           0 :   covAOD[15] = 0;  
     670           0 :   covAOD[16] = 0;  
     671           0 :   covAOD[17] = 0;  
     672           0 :   covAOD[18] = 0;  
     673           0 :   covAOD[19] = 0;  
     674           0 :   covAOD[20] = 0;  
     675             : 
     676           0 : }
     677             : 
     678             : //====================================================================================================================================================
     679             : 
     680             : const TMatrixD AliMFTAnalysisTools::ConvertCovMatrixAOD2MUON(AliAODTrack *muon) {
     681             : 
     682           0 :   Double_t covAOD[21] = {0};
     683           0 :   muon -> GetCovarianceXYZPxPyPz(covAOD);
     684             : 
     685           0 :   TMatrixD covMUON(5,5);
     686             : 
     687           0 :   covMUON(0,0) = covAOD[0];
     688             :                                 
     689           0 :   covMUON(1,0) = covAOD[1];
     690           0 :   covMUON(1,1) = covAOD[2];
     691             :                                 
     692           0 :   covMUON(2,0) = covAOD[3];  
     693           0 :   covMUON(2,1) = covAOD[4];  
     694           0 :   covMUON(2,2) = covAOD[5];  
     695             :                                 
     696           0 :   covMUON(3,0) = covAOD[6];  
     697           0 :   covMUON(3,1) = covAOD[7];  
     698           0 :   covMUON(3,2) = covAOD[8];  
     699           0 :   covMUON(3,3) = covAOD[9];  
     700             :                                 
     701           0 :   covMUON(4,0) = covAOD[10];  
     702           0 :   covMUON(4,1) = covAOD[11];  
     703           0 :   covMUON(4,2) = covAOD[12];  
     704           0 :   covMUON(4,3) = covAOD[13];  
     705           0 :   covMUON(4,4) = covAOD[14]; 
     706             : 
     707             :   return covMUON;
     708             : 
     709           0 : }
     710             : 
     711             : //====================================================================================================================================================
     712             : 
     713             : Bool_t AliMFTAnalysisTools::IsCorrectMatch(AliAODTrack *muon) {
     714             : 
     715           0 :   for (Int_t iPlane=0; iPlane<AliMFTConstants::fNMaxPlanes; iPlane++) if (IsWrongCluster(muon, iPlane)) return kFALSE;
     716           0 :   return kTRUE;
     717             : 
     718           0 : }
     719             : 
     720             : //====================================================================================================================================================
     721             : 
     722             : TString AliMFTAnalysisTools::GetGenerator(Int_t label, AliAODMCHeader* header) {
     723             : 
     724             :   // get the name of the generator that produced a given particle
     725             : 
     726             :   Int_t partCounter = 0;
     727           0 :   TList *genHeaders = header->GetCocktailHeaders();
     728           0 :   Int_t nGenHeaders = genHeaders->GetEntries();
     729             : 
     730           0 :   for (Int_t i=0; i<nGenHeaders; i++){
     731           0 :     AliGenEventHeader *gh = (AliGenEventHeader*) genHeaders->At(i);
     732           0 :     TString genName = gh->GetName();
     733           0 :     Int_t nPart = gh->NProduced();
     734           0 :     if (label>=partCounter && label<(partCounter+nPart)) return genName;
     735           0 :     partCounter += nPart;
     736           0 :   }
     737             : 
     738           0 :   TString empty="";
     739           0 :   return empty;
     740             : 
     741           0 : }
     742             : 
     743             : //====================================================================================================================================================
     744             : 
     745             : void AliMFTAnalysisTools::GetTrackPrimaryGenerator(AliAODTrack *track, AliAODMCHeader *header, TClonesArray *arrayMC, TString &nameGen) {
     746             : 
     747             :   // method to check if a track comes from a given generator
     748             : 
     749           0 :   Int_t label = TMath::Abs(track->GetLabel());
     750           0 :   nameGen = GetGenerator(label,header);
     751             :   
     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
     753             :   
     754           0 :   while (nameGen.IsWhitespace()) {
     755           0 :     AliAODMCParticle *mcPart = (AliAODMCParticle*) arrayMC->At(label);
     756           0 :     if (!mcPart) {
     757           0 :       printf("AliMFTAnalysisTools::GetTrackPrimaryGenerator - BREAK: No valid AliAODMCParticle at label %i\n",label);
     758           0 :       break;
     759             :     }
     760           0 :     Int_t motherLabel = mcPart->GetMother();
     761           0 :     if (motherLabel < 0) {
     762           0 :       printf("AliMFTAnalysisTools::GetTrackPrimaryGenerator - BREAK: Reached primary particle without valid mother\n");
     763           0 :       break;
     764             :     }
     765             :     label = motherLabel;
     766           0 :     nameGen = GetGenerator(label,header);
     767           0 :   }
     768             :   
     769             :   return;
     770             : 
     771           0 : }
     772             : 
     773             : //====================================================================================================================================================
     774             : 
     775             : Bool_t AliMFTAnalysisTools::IsTrackInjected(AliAODTrack *track, AliAODMCHeader *header, TClonesArray *arrayMC) {
     776             : 
     777             :   // method to check if a track comes from the signal event or from the underlying Hijing event
     778             : 
     779           0 :   TString nameGen;
     780             : 
     781           0 :   GetTrackPrimaryGenerator(track,header,arrayMC,nameGen);
     782             :   
     783           0 :   if (nameGen.IsWhitespace() || nameGen.Contains("ijing")) return kFALSE;
     784             :   
     785           0 :   return kTRUE;
     786             : 
     787           0 : }
     788             : 
     789             : //====================================================================================================================================================
     790             : 
     791             : Bool_t AliMFTAnalysisTools::TranslateMuon(AliAODTrack *muon, Double_t vtxInitial[3], Double_t vtxFinal[3]) {
     792             : 
     793           0 :   if (!(muon->PzAtDCA()!=0)) return kFALSE;
     794             : 
     795           0 :   AliMUONTrackParam *param = new AliMUONTrackParam();
     796             : 
     797           0 :   Double_t deltaVtx[3] = {0};
     798           0 :   for (Int_t i=0; i<3; i++) deltaVtx[i] = vtxInitial[i] - vtxFinal[i];
     799             : 
     800           0 :   param -> SetNonBendingCoor(muon->XAtDCA());
     801           0 :   param -> SetBendingCoor(muon->YAtDCA());
     802           0 :   param -> SetZ(AliMFTConstants::fZEvalKinem);
     803           0 :   param -> SetNonBendingSlope(muon->PxAtDCA()/muon->PzAtDCA());
     804           0 :   param -> SetBendingSlope(muon->PyAtDCA()/muon->PzAtDCA());
     805           0 :   param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->PzAtDCA()) / (TMath::Sqrt(1+TMath::Power(muon->PyAtDCA()/muon->PzAtDCA(),2))) );
     806             : 
     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
     809             : 
     810           0 :   AliMUONTrackExtrap::ExtrapToZ(param, deltaVtx[2]);
     811           0 :   muon->SetXYAtDCA(param->GetNonBendingCoor() - deltaVtx[0], param->GetBendingCoor() - deltaVtx[1]);
     812           0 :   muon->SetPxPyPzAtDCA(param->Px(), param->Py(), param->Pz());
     813             : 
     814           0 :   delete param;
     815             : 
     816             :   return kTRUE;
     817             : 
     818           0 : }
     819             : 
     820             : //====================================================================================================================================================
     821             : 
     822             : Bool_t AliMFTAnalysisTools::TranslateMuonToOrigin(AliAODTrack *muon, Double_t vtx[3]) {
     823             : 
     824           0 :   Double_t origin[3] = {0,0,0};
     825             : 
     826           0 :   return TranslateMuon(muon, vtx, origin);
     827             : 
     828           0 : }
     829             : 
     830             : //====================================================================================================================================================
     831             : 
     832             : Bool_t AliMFTAnalysisTools::IsPDGCharm(Int_t pdgCode) {
     833             : 
     834           0 :   pdgCode = TMath::Abs(pdgCode/100);
     835           0 :   if (pdgCode>9) pdgCode /= 10;
     836           0 :   if (pdgCode == 4 ) return kTRUE;
     837           0 :   else return kFALSE;
     838             :   
     839           0 : }
     840             : 
     841             : //====================================================================================================================================================
     842             : 
     843             : Bool_t AliMFTAnalysisTools::IsPDGBeauty(Int_t pdgCode) {
     844             : 
     845           0 :   pdgCode = TMath::Abs(pdgCode/100);
     846           0 :   if (pdgCode>9) pdgCode /= 10;
     847           0 :   if (pdgCode == 5) return kTRUE;
     848           0 :   else return kFALSE;
     849             : 
     850           0 : }
     851             : 
     852             : //====================================================================================================================================================
     853             : 
     854             : Bool_t AliMFTAnalysisTools::IsPDGResonance(Int_t pdgCode) {
     855             : 
     856           0 :   Int_t id = pdgCode%100000;
     857           0 :   return (!((id-id%10)%110));
     858             : 
     859             : } 
     860             : 
     861             : //====================================================================================================================================================

Generated by: LCOV version 1.11