+Bool_t AliMFTAnalysisTools::ExtrapAODMuonToXY(AliAODTrack *muon, Double_t xy[2], Double_t &zFinal, TLorentzVector &kinem, TMatrixD &cov) {
+
+ // Find the point of closest approach between the muon and the direction parallel to the z-axis defined by the given (x,y)
+ // Provide the z of the above point as weel as the updated kinematics and covariance matrix
+
+ // We look for the above-defined PCA
+
+ Double_t xPCA=0, yPCA=0, zPCA=0;
+
+ AliMUONTrackParam *param = new AliMUONTrackParam();
+ param -> SetNonBendingCoor(muon->XAtDCA());
+ param -> SetBendingCoor(muon->YAtDCA());
+ param -> SetZ(AliMFTConstants::fZEvalKinem);
+ param -> SetNonBendingSlope(muon->Px()/muon->Pz());
+ param -> SetBendingSlope(muon->Py()/muon->Pz());
+ param -> SetInverseBendingMomentum( muon->Charge() * (1./muon->Pz()) / (TMath::Sqrt(1+TMath::Power(muon->Py()/muon->Pz(),2))) );
+
+ // here we want to understand in which direction we have to search the minimum...
+
+ Double_t step = 1.; // initial step, in cm
+ Double_t startPoint = 0.;
+
+ Double_t r[3]={0}, z[3]={startPoint, startPoint+step, startPoint+2*step};
+
+ 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)
+
+ for (Int_t i=0; i<3; i++) {
+ AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
+ points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
+ points[1] = new TVector3(xy[0],xy[1],z[i]);
+ r[i] = GetDistanceBetweenPoints(points,2);
+ for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
+ }
+
+ Int_t researchDirection = 0;
+
+ if (r[0]>r[1] && r[1]>r[2]) researchDirection = +1; // towards z positive
+ else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1; // towards z negative
+ else if (r[0]<r[1] && r[1]>r[2]) {
+ printf("E-AliMFTAnalysisTools::ExtrapAODMuonToXY: Point of closest approach cannot be found (no minima)\n");
+ delete param;
+ delete points;
+ return kFALSE;
+ }
+
+ while (TMath::Abs(researchDirection)>0.5) {
+
+ if (researchDirection>0) {
+ z[0] = z[1];
+ z[1] = z[2];
+ z[2] = z[1]+researchDirection*step;
+ }
+ else {
+ z[2] = z[1];
+ z[1] = z[0];
+ z[0] = z[1]+researchDirection*step;
+ }
+ if (TMath::Abs(z[0])>900.) {
+ printf("E-AliMFTAnalysisTools::ExtrapAODMuonToXY: Point of closest approach cannot be found (no minima in the fiducial region)\n");
+ delete param;
+ delete points;
+ return kFALSE;
+ }
+
+ for (Int_t i=0; i<3; i++) {
+ AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
+ points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
+ points[1] = new TVector3(xy[0],xy[1],z[i]);
+ r[i] = GetDistanceBetweenPoints(points,2);
+ for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
+ }
+
+ researchDirection=0;
+ if (r[0]>r[1] && r[1]>r[2]) researchDirection = +1; // towards z positive
+ else if (r[0]<r[1] && r[1]<r[2]) researchDirection = -1; // towards z negative
+
+ }
+
+ // now we now that the minimum is between z[0] and z[2] and we search for it
+
+ step *= 0.5;
+ while (step>AliMFTConstants::fPrecisionPointOfClosestApproach) {
+ z[0] = z[1]-step;
+ z[2] = z[1]+step;
+ for (Int_t i=0; i<3; i++) {
+ AliMUONTrackExtrap::ExtrapToZ(param, z[i]);
+ points[0] = new TVector3(param->GetNonBendingCoor(),param->GetBendingCoor(),z[i]);
+ points[1] = new TVector3(xy[0],xy[1],z[i]);
+ r[i] = GetDistanceBetweenPoints(points,2);
+ for (Int_t iMu=0; iMu<2; iMu++) delete points[iMu];
+ }
+ if (r[0]<r[1]) z[1] = z[0];
+ else if (r[2]<r[1]) z[1] = z[2];
+ else step *= 0.5;
+ }
+
+ zFinal = z[1];
+
+ Double_t xyMuon[2] = {0};
+ ExtrapAODMuonToZ(muon, zFinal, xyMuon, kinem, cov);
+
+ return kTRUE;
+
+}
+
+//====================================================================================================================================================
+