]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - STEER/AliTrackFitterRieman.cxx
Use default errors in case the vertexer didn't find any
[u/mrichter/AliRoot.git] / STEER / AliTrackFitterRieman.cxx
index 793d77bbb1abbe6ed3d9a5d86d5e01fa6b3aecc2..35f9b2f358e3ecec7fde37e4d988bf30b69b0d47 100644 (file)
@@ -1,9 +1,46 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Class to the track points on the Riemann sphere. Inputs are
+// the set of id's (volids) of the volumes in which residuals are
+// calculated to construct a chi2 function to be minimized during 
+// the alignment procedures. For the moment the track extrapolation is 
+// taken at the space-point reference plane. The reference plane is
+// found using the covariance matrix of the point
+// (assuming sigma(x)=0 at the reference coordinate system.
+//
+// Internal usage of AliRieman class for minimization
+//
+//////////////////////////////////////////////////////////////////////////////
+
 #include "TMatrixDSym.h"
 #include "TMatrixD.h"
+#include "TArrayI.h"
 #include "AliTrackFitterRieman.h"
+#include "AliLog.h"
+#include "TTreeStream.h"
+#include "AliRieman.h"
+#include "AliLog.h"
 
 ClassImp(AliTrackFitterRieman)
 
+
 AliTrackFitterRieman::AliTrackFitterRieman():
   AliTrackFitter()
 {
@@ -11,9 +48,10 @@ AliTrackFitterRieman::AliTrackFitterRieman():
   // default constructor
   //
   fAlpha = 0.;
-  for (Int_t i=0;i<9;i++) fSumXY[i] = 0;
-  for (Int_t i=0;i<9;i++) fSumXZ[i] = 0;
+  fNUsed = 0;
   fConv = kFALSE;
+  fDebugStream = new TTreeSRedirector("RiemanAlignDebug.root");
+  fRieman = new AliRieman(10000);  // allocate rieman
 }
 
 
@@ -24,9 +62,10 @@ AliTrackFitterRieman::AliTrackFitterRieman(AliTrackPointArray *array, Bool_t own
   // Constructor
   //
   fAlpha = 0.;
-  for (Int_t i=0;i<9;i++) fSumXY[i] = 0;
-  for (Int_t i=0;i<9;i++) fSumXZ[i] = 0;
+  fNUsed = 0;
   fConv = kFALSE;
+  if (AliLog::GetDebugLevel("","AliTrackFitterRieman")) fDebugStream = new TTreeSRedirector("RiemanAlignDebug.root");
+  fRieman = new AliRieman(10000);  //allocate rieman
 }
 
 AliTrackFitterRieman::AliTrackFitterRieman(const AliTrackFitterRieman &rieman):
@@ -36,103 +75,133 @@ AliTrackFitterRieman::AliTrackFitterRieman(const AliTrackFitterRieman &rieman):
   // copy constructor
   //
   fAlpha = rieman.fAlpha;
-  for (Int_t i=0;i<9;i++) fSumXY[i]  = rieman.fSumXY[i];
-  for (Int_t i=0;i<9;i++) fSumXZ[i]  = rieman.fSumXZ[i];
+  fNUsed = rieman.fNUsed;
   fConv = rieman.fConv;
+  fRieman = new AliRieman(*(rieman.fRieman));
 }
 
 //_____________________________________________________________________________
 AliTrackFitterRieman &AliTrackFitterRieman::operator =(const AliTrackFitterRieman& rieman)
 {
-  // assignment operator
+  //
+  // Assignment operator
   //
   if(this==&rieman) return *this;
   ((AliTrackFitter *)this)->operator=(rieman);
 
-  fAlpha = rieman.fAlpha;
-  for (Int_t i=0;i<9;i++) fSumXY[i]  = rieman.fSumXY[i];
-  for (Int_t i=0;i<9;i++) fSumXZ[i]  = rieman.fSumXZ[i];
-  fConv = rieman.fConv;
-
+  fAlpha  = rieman.fAlpha;
+  fNUsed  = rieman.fNUsed;
+  fConv   = rieman.fConv;
+  fRieman = new AliRieman(*(rieman.fRieman));
   return *this;
 }
 
-AliTrackFitterRieman::~AliTrackFitterRieman()
-{
-  // destructor
+
+AliTrackFitterRieman::~AliTrackFitterRieman(){
+  //
+  //
   //
+  delete fRieman;
+  delete fDebugStream;
 }
 
 void AliTrackFitterRieman::Reset()
 {
   // Reset the track parameters and
   // rieman sums
+  //
   AliTrackFitter::Reset();
+  fRieman->Reset();
   fAlpha = 0.;
-  for (Int_t i=0;i<9;i++) fSumXY[i] = 0;
-  for (Int_t i=0;i<9;i++) fSumXZ[i] = 0;
+  fNUsed = 0;
   fConv =kFALSE;
 }
 
-Bool_t AliTrackFitterRieman::Fit(UShort_t volId,
-                                AliTrackPointArray *pVolId, AliTrackPointArray *pTrack,
+Bool_t AliTrackFitterRieman::Fit(const TArrayI *volIds,const TArrayI *volIdsFit,
                                 AliAlignObj::ELayerID layerRangeMin,
-                                AliAlignObj::ELayerID layerRangeMax)
+                        AliAlignObj::ELayerID layerRangeMax)
 {
   // Fit the track points. The method takes as an input
-  // the id (volid) of the volume to be skipped from fitting.
-  // The following two parameters are used to define the
+  // the set of id's (volids) of the volumes in which
+  // one wants to calculate the residuals.
+  // The following parameters are used to define the
   // range of volumes to be used in the fitting
   // As a result two AliTrackPointArray's obects are filled.
   // The first one contains the space points with
-  // volume id = volid. The second array of points represents
-  // the track extrapolation corresponding to the space points
+  // volume id's from volids list. The second array of points represents
+  // the track extrapolations corresponding to the space points
   // in the first array. The two arrays can be used to find
-  // the residuals in the volid and consequently construct a
+  // the residuals in the volids and consequently construct a
   // chi2 function to be minimized during the alignment
   // procedures. For the moment the track extrapolation is taken
-  // as follows: in XY plane - at the CDA between track circle
-  // and the space point; in Z - the track extrapolation on the Z
-  // plane defined by the space point.
-
-  pVolId = pTrack = 0x0;
-  fConv = kFALSE;
+  // at the space-point reference plane. The reference plane is
+  // found using the covariance matrix of the point
+  // (assuming sigma(x)=0 at the reference coordinate system.
 
+  Reset();
   Int_t npoints = fPoints->GetNPoints();
+  if (fPoints && AliLog::GetDebugLevel("","AliTrackFitterRieman")>1){
+    Int_t nVol    = volIds->GetSize();
+    Int_t nVolFit = volIdsFit->GetSize();
+    Int_t volId  = volIds->At(0);    
+    (*fDebugStream)<<"PInput"<<
+      "NPoints="<<npoints<<    // number of points
+      "VolId="<<volId<<        // first vol ID
+      "NVol="<<nVol<<          // number of volumes 
+      "NvolFit="<<nVolFit<<    // number of volumes to fit
+      "fPoints.="<<fPoints<<   // input points
+      "\n";
+  }
   if (npoints < 3) return kFALSE;
 
-  AliTrackPoint p;
-  fPoints->GetPoint(p,0);
-  fAlpha = TMath::ATan2(p.GetY(),p.GetX());
-  Double_t sin = TMath::Sin(fAlpha);
-  Double_t cos = TMath::Cos(fAlpha);
+  Bool_t isAlphaCalc = kFALSE;
+  AliTrackPoint p,plocal;
+//   fPoints->GetPoint(p,0);
+//   fAlpha = TMath::ATan2(p.GetY(),p.GetX());
 
   Int_t npVolId = 0;
-  Int_t npused = 0;
+  fNUsed = 0;
   Int_t *pindex = new Int_t[npoints];
   for (Int_t ipoint = 0; ipoint < npoints; ipoint++)
     {
       fPoints->GetPoint(p,ipoint);
       UShort_t iVolId = p.GetVolumeID();
-      if (iVolId == volId) {
+      if (FindVolId(volIds,iVolId)) {
        pindex[npVolId] = ipoint;
        npVolId++;
       }
-      if (iVolId < AliAlignObj::LayerToVolUID(layerRangeMin,0) ||
-         iVolId >= AliAlignObj::LayerToVolUID(layerRangeMax,0)) continue;
-      Float_t x = p.GetX()*cos + p.GetY()*sin;
-      Float_t y = p.GetY()*cos - p.GetX()*sin;
-      AddPoint(x,y,p.GetZ(),1,1);
-      npused++;
+      if (volIdsFit != 0x0) {
+       if (!FindVolId(volIdsFit,iVolId)) continue;
+      }
+      else {
+       if (iVolId < AliAlignObj::LayerToVolUID(layerRangeMin,0) ||
+           iVolId > AliAlignObj::LayerToVolUID(layerRangeMax,
+                                               AliAlignObj::LayerSize(layerRangeMax))) continue;
+      }
+      if (!isAlphaCalc) {
+       fAlpha = p.GetAngle();
+       isAlphaCalc = kTRUE;
+      }
+      plocal = p.Rotate(fAlpha);
+      if (TMath::Abs(plocal.GetX())>500 || TMath::Abs(plocal.GetX())<2){
+       printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</n");
+       p.Dump();
+       plocal.Dump();
+       printf("Problematic point\n");  
+       printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<</n");
+      }
+      AddPoint(plocal.GetX(),plocal.GetY(),plocal.GetZ(),
+              TMath::Sqrt(plocal.GetCov()[3]),TMath::Sqrt(plocal.GetCov()[5]));
+      // fNUsed++;  AddPoint should be responsible
     }
 
-  if (npused < 3) {
+  if (npVolId == 0 || fNUsed < fMinNPoints) {
     delete [] pindex;
     return kFALSE;
   }
 
   Update();
-
   if (!fConv) {
     delete [] pindex;
     return kFALSE;
@@ -144,231 +213,128 @@ Bool_t AliTrackFitterRieman::Fit(UShort_t volId,
     return kFALSE;
   }
 
-  pVolId = new AliTrackPointArray(npVolId);
-  pTrack = new AliTrackPointArray(npVolId);
+
+  if (fNUsed < fMinNPoints) {
+    delete [] pindex;
+    return kFALSE;
+  }
+
+  fPVolId = new AliTrackPointArray(npVolId);
+  fPTrack = new AliTrackPointArray(npVolId);
   AliTrackPoint p2;
   for (Int_t ipoint = 0; ipoint < npVolId; ipoint++)
     {
       Int_t index = pindex[ipoint];
       fPoints->GetPoint(p,index);
       if (GetPCA(p,p2)) {
-       pVolId->AddPoint(ipoint,&p);
-       pTrack->AddPoint(ipoint,&p2);
+       Float_t xyz[3],xyz2[3];
+       p.GetXYZ(xyz); p2.GetXYZ(xyz2);
+       //      printf("residuals %f %d %d %f %f %f %f %f %f\n",fChi2,fNUsed,fConv,xyz[0],xyz[1],xyz[2],xyz2[0]-xyz[0],xyz2[1]-xyz[1],xyz2[2]-xyz[2]);
+       fPVolId->AddPoint(ipoint,&p);
+       fPTrack->AddPoint(ipoint,&p2);
+      }else{
+       // what should be default bahavior -  
+       delete [] pindex;
+       delete fPVolId;
+       delete fPTrack;
+       fPVolId =0;
+       fPTrack =0;
+       return kFALSE;
       }
     }  
+  
+  if (AliLog::GetDebugLevel("","AliTrackFitterRieman")>0){
+    //
+    // Debug Info
+    //
+    AliTrackPointArray *lPVolId = new AliTrackPointArray(npVolId);
+    AliTrackPointArray *lPTrack = new AliTrackPointArray(npVolId);
+    AliRieman * residual = fRieman->MakeResiduals();
+    AliTrackPoint p2local;
+    for (Int_t ipoint = 0; ipoint < npVolId; ipoint++){
+      Int_t index = pindex[ipoint];
+      fPoints->GetPoint(p,index); 
+      if (GetPCA(p,p2)) {
+       plocal = p.Rotate(fAlpha);
+       //      plocal.Rotate(fAlpha);
+       Float_t xyz[3],xyz2[3];
+       p2local = plocal;
+       plocal.GetXYZ(xyz); 
+       xyz2[0] = xyz[0];
+       xyz2[1] = GetYat(xyz[0]); 
+       xyz2[2] = GetZat(xyz[0]); 
+       p2local.SetXYZ(xyz2);
+       lPVolId->AddPoint(ipoint,&plocal);
+       lPTrack->AddPoint(ipoint,&p2local);
+      }
+    }      
+    //
+    // debug info
+    //
+    Int_t nVol    = volIds->GetSize();
+    Int_t nVolFit = volIdsFit->GetSize();
+    Int_t volId   = volIds->At(0);   
+    Int_t modId   =0;
+    Int_t layer   =  AliAlignObj::VolUIDToLayer(volId,modId);
+    
+    (*fDebugStream)<<"Fit"<<
+      "VolId="<<volId<<        // volume ID
+      "Layer="<<layer<<        // layer ID
+      "Module="<<modId<<       // module ID
+      "NVol="<<nVol<<          // number of volumes 
+      "NvolFit="<<nVolFit<<    // number of volumes to fit
+      "Points0.="<<fPVolId<<    // original points
+      "Points1.="<<fPTrack<<    // fitted points 
+      "LPoints0.="<<lPVolId<<   // original points - local frame
+      "LPoints1.="<<lPTrack<<   // fitted points   - local frame      
+      "Rieman.="<<this<<        // original rieman fit
+      "Res.="<<residual<<       // residuals of rieman fit  
+      "\n";
+    delete lPVolId;
+    delete lPTrack;
+    delete residual;
+  }
 
   delete [] pindex;
-
   return kTRUE;
 }
 
+
 void AliTrackFitterRieman::AddPoint(Float_t x, Float_t y, Float_t z, Float_t sy, Float_t sz)
 {
   //
-  //  Rieman update
-  //
-  //------------------------------------------------------
-  // XY direction
-  //
-  //  (x-x0)^2+(y-y0)^2-R^2=0 ===>
-  //
-  //  (x^2+y^2 -2*x*x0 - 2*y*y0+ x0^2 -y0^2 -R^2 =0;  ==>
-  //
-  //   substitution t = 1/(x^2+y^2),   u = 2*x*t, y = 2*y*t,  D0 = R^2 - x0^2- y0^2
-  //
-  //  1 - u*x0 - v*y0 - t *D0 =0 ;  - linear equation
-  //     
-  //  next substition   a = 1/y0    b = -x0/y0   c = -D0/y0
+  // add point to rieman fitter
   //
-  //  final linear equation :   a + u*b +t*c - v =0;
-  //
-  // Minimization :
-  //
-  // sum( (a + ui*b +ti*c - vi)^2)/(sigmai)^2 = min;
-  //
-  // where sigmai is the error of  maesurement  (a + ui*b +ti*c - vi)
-  //
-  // neglecting error of xi, and supposing  xi>>yi    sigmai ~ sigmaVi ~ 2*sigmay*t  
-  //
-  //
-  // XY part
-  //
-  Double_t  t  =  x*x+y*y;
-  if (t<2) return;
-  t            = 1./t;
-  Double_t  u  =  2.*x*t;
-  Double_t  v  =  2.*y*t;
-  Double_t  error = 2.*sy*t;
-  error *=error;
-  Double_t weight = 1./error;
-  fSumXY[0] +=weight;
-  fSumXY[1] +=u*weight;      fSumXY[2]+=v*weight;  fSumXY[3]+=t*weight;
-  fSumXY[4] +=u*u*weight;    fSumXY[5]+=t*t*weight;
-  fSumXY[6] +=u*v*weight;    fSumXY[7]+=u*t*weight; fSumXY[8]+=v*t*weight;
-  //
-  // XZ part
-  //
-  weight = 1./sz;
-  fSumXZ[0] +=weight;
-  fSumXZ[1] +=weight*x;   fSumXZ[2] +=weight*x*x; fSumXZ[3] +=weight*x*x*x; fSumXZ[4] += weight*x*x*x*x;
-  fSumXZ[5] +=weight*z;   fSumXZ[6] +=weight*x*z; fSumXZ[7] +=weight*x*x*z;
+  fRieman->AddPoint(x,y,z,sy,sz);
+  fNUsed = fRieman->GetN();
 }
 
+
+
 void AliTrackFitterRieman::Update(){
   //
-  //  Rieman update
-  //
+  // 
   //
-  for (Int_t i=0;i<6;i++)fParams[i]=0;
-  Int_t conv=0;
-  //
-  // XY part
-  //
-  TMatrixDSym     smatrix(3);
-  TMatrixD        sums(1,3);
-  //
-  //   smatrix(0,0) = s0; smatrix(1,1)=su2; smatrix(2,2)=st2;
-  //   smatrix(0,1) = su; smatrix(0,2)=st; smatrix(1,2)=sut;
-  //   sums(0,0)    = sv; sums(0,1)=suv; sums(0,2)=svt;
-
-  smatrix(0,0) = fSumXY[0]; smatrix(1,1)=fSumXY[4]; smatrix(2,2)=fSumXY[5];
-  smatrix(0,1) = fSumXY[1]; smatrix(0,2)=fSumXY[3]; smatrix(1,2)=fSumXY[7];
-  sums(0,0)    = fSumXY[2]; sums(0,1)   =fSumXY[6]; sums(0,2)   =fSumXY[8];
-  smatrix.Invert();
-  if (smatrix.IsValid()){
-    for (Int_t i=0;i<3;i++)
-      for (Int_t j=0;j<=i;j++){
-       (*fCov)(i,j)=smatrix(i,j);
-      }
-    TMatrixD  res = sums*smatrix;
-    fParams[0] = res(0,0);
-    fParams[1] = res(0,1);
-    fParams[2] = res(0,2);
-    conv++;
-  }
-  //
-  // XZ part
-  //
-  TMatrixDSym     smatrixz(3);
-  smatrixz(0,0) = fSumXZ[0]; smatrixz(0,1) = fSumXZ[1]; smatrixz(0,2) = fSumXZ[2];
-  smatrixz(1,1) = fSumXZ[2]; smatrixz(1,2) = fSumXZ[3];
-  smatrixz(2,2) = fSumXZ[4];
-  smatrixz.Invert();
-  if (smatrixz.IsValid()){
-    sums(0,0)    = fSumXZ[5];
-    sums(0,1)    = fSumXZ[6];
-    sums(0,2)    = fSumXZ[7];
-    TMatrixD res = sums*smatrixz;
-    fParams[3] = res(0,0);
-    fParams[4] = res(0,1);
-    fParams[5] = res(0,2);
-    for (Int_t i=0;i<3;i++)
-      for (Int_t j=0;j<=i;j++){
-       (*fCov)(i+2,j+2)=smatrixz(i,j);
+  fRieman->Update();
+  fConv = kFALSE;
+  if (fRieman->IsValid()){
+    for (Int_t ipar=0; ipar<6; ipar++){
+      fParams[ipar] = fRieman->GetParam()[ipar];
     }
-    conv++;
+    fChi2  =  fRieman->GetChi2();
+    fNdf   =  fRieman->GetN()- 2;
+    fNUsed =  fRieman->GetN();
+    fConv = kTRUE;
   }
-
-  //  (x-x0)^2+(y-y0)^2-R^2=0 ===>
-  //
-  //  (x^2+y^2 -2*x*x0 - 2*y*y0+ x0^2 -y0^2 -R^2 =0;  ==>
-  //   substitution t = 1/(x^2+y^2),   u = 2*x*t, y = 2*y*t,  D0 = R^2 - x0^2- y0^2
-  //
-  //  1 - u*x0 - v*y0 - t *D0 =0 ;  - linear equation
-  //     
-  //  next substition   a = 1/y0    b = -x0/y0   c = -D0/y0
-  //  final linear equation :   a + u*b +t*c - v =0;
-  //
-  //  fParam[0]  = 1/y0
-  //  fParam[1]  = -x0/y0
-  //  fParam[2]  = - (R^2 - x0^2 - y0^2)/y0
-  if (conv>1) fConv =kTRUE;
-  else
-    fConv=kFALSE;
-}
-
-Double_t AliTrackFitterRieman::GetYat(Double_t x){
-  if (!fConv) return 0.;
-  Double_t res2 = (x*fParams[0]+fParams[1]);
-  res2*=res2;
-  res2 = 1.-fParams[2]*fParams[0]+fParams[1]*fParams[1]-res2;
-  if (res2<0) return 0;
-  res2 = TMath::Sqrt(res2);
-  res2 = (1-res2)/fParams[0];
-  return res2;
-}
-
-Double_t AliTrackFitterRieman::GetDYat(Double_t x){
-  if (!fConv) return 0.;
-  Double_t x0 = -fParams[1]/fParams[0];
-  if (-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1<0) return 0;
-  Double_t Rm1  = fParams[0]/TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1); 
-  if ( 1./(Rm1*Rm1)-(x-x0)*(x-x0)<=0) return 0;
-  Double_t res = (x-x0)/TMath::Sqrt(1./(Rm1*Rm1)-(x-x0)*(x-x0));
-  if (fParams[0]<0) res*=-1.;
-  return res;
-}
-
-
-
-Double_t AliTrackFitterRieman::GetZat(Double_t x){
-  if (!fConv) return 0.;
-  Double_t x0 = -fParams[1]/fParams[0];
-  if (-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1<=0) return 0;
-  Double_t Rm1  = fParams[0]/TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1); 
-  Double_t phi  = TMath::ASin((x-x0)*Rm1);
-  Double_t phi0 = TMath::ASin((0.-x0)*Rm1);
-  Double_t dphi = (phi-phi0);
-  Double_t res = fParams[3]+fParams[4]*dphi/Rm1;
-  return res;
-}
-
-Double_t AliTrackFitterRieman::GetDZat(Double_t x){
-  if (!fConv) return 0.;
-  Double_t x0 = -fParams[1]/fParams[0]; 
-  if  (-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1<=0) return 0;
-  Double_t Rm1  = fParams[0]/TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1); 
-  Double_t res = fParams[4]/TMath::Cos(TMath::ASin((x-x0)*Rm1));
-  return res;
-}
-
-
-Double_t AliTrackFitterRieman::GetC(){
-  return fParams[0]/TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1);
-}
-
-Bool_t AliTrackFitterRieman::GetXYZat(Double_t r, Float_t *xyz){
-  if (!fConv) return kFALSE;
-  Double_t res2 = (r*fParams[0]+fParams[1]);
-  res2*=res2;
-  res2 = 1.-fParams[2]*fParams[0]+fParams[1]*fParams[1]-res2;
-  if (res2<0) return kFALSE;
-  res2 = TMath::Sqrt(res2);
-  res2 = (1-res2)/fParams[0];
-
-  if (!fConv) return kFALSE;
-  Double_t x0 = -fParams[1]/fParams[0];
-  if (-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1<=0) return 0;
-  Double_t Rm1  = fParams[0]/TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1); 
-  Double_t phi  = TMath::ASin((r-x0)*Rm1);
-  Double_t phi0 = TMath::ASin((0.-x0)*Rm1);
-  Double_t dphi = (phi-phi0);
-  Double_t res = fParams[3]+fParams[4]*dphi/Rm1;
-
-  Double_t sin = TMath::Sin(fAlpha);
-  Double_t cos = TMath::Cos(fAlpha);
-  xyz[0] = r*cos - res2*sin;
-  xyz[1] = res2*cos + r*sin;
-  xyz[2] = res;
-
-  return kTRUE;
 }
 
+//_____________________________________________________________________________
 Bool_t AliTrackFitterRieman::GetPCA(const AliTrackPoint &p, AliTrackPoint &p2) const
 {
+  //
   // Get the closest to a given spacepoint track trajectory point
   // Look for details in the description of the Fit() method
-
+  //
   if (!fConv) return kFALSE;
 
   // First X and Y coordinates
@@ -378,25 +344,71 @@ Bool_t AliTrackFitterRieman::GetPCA(const AliTrackPoint &p, AliTrackPoint &p2) c
   //  fParam[1]  = -x0/y0
   //  fParam[2]  = - (R^2 - x0^2 - y0^2)/y0
   if (fParams[0] == 0) return kFALSE;
+  // Track parameters in the global coordinate system
   Double_t x0 = -fParams[1]/fParams[0]*cos -         1./fParams[0]*sin;
   Double_t y0 =          1./fParams[0]*cos - fParams[1]/fParams[0]*sin;
   if ((-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1) <= 0) return kFALSE;
-  Double_t R  = TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1)/
+  Double_t r  = TMath::Sqrt(-fParams[2]*fParams[0]+fParams[1]*fParams[1]+1)/
                 fParams[0];
 
-  Double_t x  = p.GetX();
-  Double_t y  = p.GetY();
-  Double_t dR = TMath::Sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
-  Double_t xprime = TMath::Abs(R)*(x-x0)/dR + x0;
-  Double_t yprime = TMath::Abs(R)*(y-y0)/dR + y0;
-
-  // Now Z coordinate
-  Double_t phi  = TMath::ASin((x-x0)/R);
-  Double_t phi0 = TMath::ASin((0.-x0)/R);
-  Double_t dphi = (phi-phi0);
-  Double_t zprime = fParams[3]+fParams[4]*dphi*R;
-
-  p2.SetXYZ(xprime,yprime,zprime);
-
+  // Define space-point refence plane
+  Double_t alphap = p.GetAngle();
+  Double_t sinp = TMath::Sin(alphap);
+  Double_t cosp = TMath::Cos(alphap);
+  Double_t x  = p.GetX()*cosp + p.GetY()*sinp;
+  Double_t y  = p.GetY()*cosp - p.GetX()*sinp;
+  Double_t x0p= x0*cosp + y0*sinp;
+  Double_t y0p= y0*cosp - x0*sinp;
+  if ((r*r - (x-x0p)*(x-x0p))<0) {
+    AliWarning(Form("Track extrapolation failed ! (Track radius = %f, track circle x = %f, space-point x = %f, reference plane angle = %f\n",r,x0p,x,alphap));
+    return kFALSE;
+  }
+  Double_t temp = TMath::Sqrt(r*r - (x-x0p)*(x-x0p));
+  Double_t y1 = y0p + temp;
+  Double_t y2 = y0p - temp;
+  Double_t yprime = y1;
+  if(TMath::Abs(y2-y) < TMath::Abs(y1-y)) yprime = y2;
+
+  // Back to the global coordinate system
+  Double_t xsecond = x*cosp - yprime*sinp;
+  Double_t ysecond = yprime*cosp + x*sinp;
+
+  // Now Z coordinate and track angles
+  Double_t x2 = xsecond*cos + ysecond*sin;
+  Double_t zsecond = GetZat(x2);
+  Double_t dydx = GetDYat(x2);
+  Double_t dzdx = GetDZat(x2);
+
+  // Fill the cov matrix of the track extrapolation point
+  Double_t cov[6] = {0,0,0,0,0,0};
+  Double_t sigmax = 100*100.;
+  cov[0] = sigmax;           cov[1] = sigmax*dydx;      cov[2] = sigmax*dzdx;
+  cov[3] = sigmax*dydx*dydx; cov[4] = sigmax*dydx*dzdx;
+  cov[5] = sigmax*dzdx*dzdx;
+
+  Float_t  newcov[6];
+  newcov[0] = cov[0]*cos*cos-
+            2*cov[1]*sin*cos+
+              cov[3]*sin*sin;
+  newcov[1] = cov[1]*(cos*cos-sin*sin)-
+             (cov[3]-cov[0])*sin*cos;
+  newcov[2] = cov[2]*cos-
+              cov[4]*sin;
+  newcov[3] = cov[0]*sin*sin+
+            2*cov[1]*sin*cos+
+              cov[3]*cos*cos;
+  newcov[4] = cov[4]*cos+
+              cov[2]*sin;
+  newcov[5] = cov[5];
+
+  p2.SetXYZ(xsecond,ysecond,zsecond,newcov);
+  if (AliLog::GetDebugLevel("","AliTrackFitterRieman")>1){
+    AliTrackPoint lp0(p);
+    AliTrackPoint lp2(p2);
+    if (0)(*fDebugStream)<<"PCA"<<
+      "P0.="<<&lp0<<
+      "P2.="<<&lp2<<
+      "\n";
+  }
   return kTRUE;
 }