For Pythia with tune don't switch off MI in ConfigHeavyFlavor
[u/mrichter/AliRoot.git] / ITS / AliITStrackV2.cxx
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 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////
19 //                Implementation of the ITS track class
20 //
21 //          Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
22 //     dEdx analysis by: Boris Batyunya, JINR, Boris.Batiounia@cern.ch
23 ///////////////////////////////////////////////////////////////////////////
24 #include <TMath.h>
25
26 #include "AliCluster.h"
27 #include "AliESDVertex.h"
28 #include "AliITSReconstructor.h"
29 #include "AliITStrackV2.h"
30 #include "AliTracker.h"
31
32 const Int_t AliITStrackV2::fgkWARN = 5;
33
34 ClassImp(AliITStrackV2)
35
36
37 //____________________________________________________________________________
38 AliITStrackV2::AliITStrackV2() : AliKalmanTrack(),
39   fCheckInvariant(kTRUE),
40   fdEdx(0),
41   fESDtrack(0)
42 {
43   for(Int_t i=0; i<2*AliITSgeomTGeo::kNLayers; i++) {fIndex[i]=-1; fModule[i]=-1;}
44   for(Int_t i=0; i<4; i++) fdEdxSample[i]=0;
45 }
46
47
48 //____________________________________________________________________________
49 AliITStrackV2::AliITStrackV2(AliESDtrack& t,Bool_t c) throw (const Char_t *) :
50   AliKalmanTrack(),
51   fCheckInvariant(kTRUE),
52   fdEdx(t.GetITSsignal()),
53   fESDtrack(&t)
54 {
55   //------------------------------------------------------------------
56   // Conversion ESD track -> ITS track.
57   // If c==kTRUE, create the ITS track out of the constrained params.
58   //------------------------------------------------------------------
59   const AliExternalTrackParam *par=&t;
60   if (c) {
61     par=t.GetConstrainedParam();
62     if (!par) throw "AliITStrackV2: conversion failed !\n";
63   }
64   Set(par->GetX(),par->GetAlpha(),par->GetParameter(),par->GetCovariance());
65
66   //if (!Invariant()) throw "AliITStrackV2: conversion failed !\n";
67
68   SetLabel(t.GetLabel());
69   SetMass(t.GetMass());
70   SetNumberOfClusters(t.GetITSclusters(fIndex));
71
72   if (t.GetStatus()&AliESDtrack::kTIME) {
73     StartTimeIntegral();
74     Double_t times[10]; t.GetIntegratedTimes(times); SetIntegratedTimes(times);
75     SetIntegratedLength(t.GetIntegratedLength());
76   }
77
78   for(Int_t i=0; i<4; i++) fdEdxSample[i]=0;
79 }
80
81 //____________________________________________________________________________
82 void AliITStrackV2::ResetClusters() {
83   //------------------------------------------------------------------
84   // Reset the array of attached clusters.
85   //------------------------------------------------------------------
86   for (Int_t i=0; i<2*AliITSgeomTGeo::kNLayers; i++) fIndex[i]=-1;
87   SetChi2(0.); 
88   SetNumberOfClusters(0);
89
90
91 //____________________________________________________________________________
92 void AliITStrackV2::UpdateESDtrack(ULong_t flags) const {
93   // Update track params
94   fESDtrack->UpdateTrackParams(this,flags);
95   // copy the module indices
96   for(Int_t i=0;i<12;i++) {
97     //   printf("     %d\n",GetModuleIndex(i));
98     fESDtrack->SetITSModuleIndex(i,GetModuleIndex(i));
99   }
100   // copy the 4 dedx samples
101   Double_t sdedx[4]={0.,0.,0.,0.};
102   for(Int_t i=0; i<4; i++) sdedx[i]=fdEdxSample[i];
103   fESDtrack->SetITSdEdxSamples(sdedx);
104 }
105
106 //____________________________________________________________________________
107 AliITStrackV2::AliITStrackV2(const AliITStrackV2& t) : 
108   AliKalmanTrack(t),
109   fCheckInvariant(t.fCheckInvariant),
110   fdEdx(t.fdEdx),
111   fESDtrack(t.fESDtrack) 
112 {
113   //------------------------------------------------------------------
114   //Copy constructor
115   //------------------------------------------------------------------
116   Int_t i;
117   for (i=0; i<4; i++) fdEdxSample[i]=t.fdEdxSample[i];
118   for (i=0; i<2*AliITSgeomTGeo::GetNLayers(); i++) {
119     fIndex[i]=t.fIndex[i];
120     fModule[i]=t.fModule[i];
121   }
122 }
123
124 //_____________________________________________________________________________
125 Int_t AliITStrackV2::Compare(const TObject *o) const {
126   //-----------------------------------------------------------------
127   // This function compares tracks according to the their curvature
128   //-----------------------------------------------------------------
129   AliITStrackV2 *t=(AliITStrackV2*)o;
130   //Double_t co=OneOverPt();
131   //Double_t c =OneOverPt();
132   Double_t co=t->GetSigmaY2()*t->GetSigmaZ2();
133   Double_t c =GetSigmaY2()*GetSigmaZ2();
134   if (c>co) return 1;
135   else if (c<co) return -1;
136   return 0;
137 }
138
139 //____________________________________________________________________________
140 Bool_t 
141 AliITStrackV2::PropagateToVertex(const AliESDVertex *v,Double_t d,Double_t x0) 
142 {
143   //------------------------------------------------------------------
144   //This function propagates a track to the minimal distance from the origin
145   //------------------------------------------------------------------  
146   Double_t bz=GetBz();
147   if (PropagateToDCA(v,bz,kVeryBig)) {
148     Double_t xOverX0,xTimesRho; 
149     xOverX0 = d; xTimesRho = d*x0;
150     if (CorrectForMeanMaterial(xOverX0,xTimesRho,kTRUE)) return kTRUE;
151   }
152   return kFALSE;
153 }
154
155 //____________________________________________________________________________
156 Bool_t AliITStrackV2::
157 GetGlobalXYZat(Double_t xloc, Double_t &x, Double_t &y, Double_t &z) const {
158   //------------------------------------------------------------------
159   //This function returns a track position in the global system
160   //------------------------------------------------------------------
161   Double_t r[3];
162   Bool_t rc=GetXYZAt(xloc, GetBz(), r);
163   x=r[0]; y=r[1]; z=r[2]; 
164   return rc;
165 }
166
167 //_____________________________________________________________________________
168 Double_t AliITStrackV2::GetPredictedChi2(const AliCluster *c) const {
169   //-----------------------------------------------------------------
170   // This function calculates a predicted chi2 increment.
171   //-----------------------------------------------------------------
172   Double_t p[2]={c->GetY(), c->GetZ()};
173   Double_t cov[3]={c->GetSigmaY2(), 0., c->GetSigmaZ2()};
174   return AliExternalTrackParam::GetPredictedChi2(p,cov);
175 }
176
177 //____________________________________________________________________________
178 Bool_t AliITStrackV2::PropagateTo(Double_t xk, Double_t d, Double_t x0) {
179   //------------------------------------------------------------------
180   //This function propagates a track
181   //------------------------------------------------------------------
182
183   Double_t oldX=GetX(), oldY=GetY(), oldZ=GetZ();
184   
185   //Double_t bz=GetBz();
186   //if (!AliExternalTrackParam::PropagateTo(xk,bz)) return kFALSE;
187   Double_t b[3]; GetBxByBz(b);
188   if (!AliExternalTrackParam::PropagateToBxByBz(xk,b)) return kFALSE;
189   Double_t xOverX0,xTimesRho; 
190   xOverX0 = d; xTimesRho = d*x0;
191   if (!CorrectForMeanMaterial(xOverX0,xTimesRho,kTRUE)) return kFALSE;
192
193   Double_t x=GetX(), y=GetY(), z=GetZ();
194   if (IsStartedTimeIntegral() && x>oldX) {
195     Double_t l2 = (x-oldX)*(x-oldX) + (y-oldY)*(y-oldY) + (z-oldZ)*(z-oldZ);
196     AddTimeStep(TMath::Sqrt(l2));
197   }
198
199   return kTRUE;
200 }
201
202 //____________________________________________________________________________
203 Bool_t AliITStrackV2::PropagateToTGeo(Double_t xToGo, Int_t nstep, Double_t &xOverX0, Double_t &xTimesRho, Bool_t addTime) {
204   //-------------------------------------------------------------------
205   //  Propagates the track to a reference plane x=xToGo in n steps.
206   //  These n steps are only used to take into account the curvature.
207   //  The material is calculated with TGeo. (L.Gaudichet)
208   //-------------------------------------------------------------------
209   
210   Double_t startx = GetX(), starty = GetY(), startz = GetZ();
211   Double_t sign = (startx<xToGo) ? -1.:1.;
212   Double_t step = (xToGo-startx)/TMath::Abs(nstep);
213
214   Double_t start[3], end[3], mparam[7];
215   //Double_t bz = GetBz();
216   Double_t b[3]; GetBxByBz(b);
217   Double_t bz = b[2];
218
219   Double_t x = startx;
220   
221   for (Int_t i=0; i<nstep; i++) {
222     
223     GetXYZ(start);   //starting global position
224     x += step;
225     if (!GetXYZAt(x, bz, end)) return kFALSE;
226     //if (!AliExternalTrackParam::PropagateTo(x, bz)) return kFALSE;
227     if (!AliExternalTrackParam::PropagateToBxByBz(x, b)) return kFALSE;
228     AliTracker::MeanMaterialBudget(start, end, mparam);
229     xTimesRho = sign*mparam[4]*mparam[0];
230     xOverX0   = mparam[1];
231     if (mparam[1]<900000) {
232       if (!AliExternalTrackParam::CorrectForMeanMaterial(xOverX0,
233                            xTimesRho,GetMass())) return kFALSE;
234     } else { // this happens when MeanMaterialBudget cannot cross a boundary
235       return kFALSE;
236     }
237   }
238
239   if (addTime && IsStartedTimeIntegral() && GetX()>startx) {
240     Double_t l2 = ( (GetX()-startx)*(GetX()-startx) +
241                     (GetY()-starty)*(GetY()-starty) +
242                     (GetZ()-startz)*(GetZ()-startz) );
243     AddTimeStep(TMath::Sqrt(l2));
244   }
245
246   return kTRUE;
247 }
248
249 //____________________________________________________________________________
250 Bool_t AliITStrackV2::Update(const AliCluster* c, Double_t chi2, Int_t index) 
251 {
252   //------------------------------------------------------------------
253   //This function updates track parameters
254   //------------------------------------------------------------------
255   Double_t p[2]={c->GetY(), c->GetZ()};
256   Double_t cov[3]={c->GetSigmaY2(), c->GetSigmaYZ(), c->GetSigmaZ2()};
257
258   if (!AliExternalTrackParam::Update(p,cov)) return kFALSE;
259
260   Int_t n=GetNumberOfClusters();
261   if (!Invariant()) {
262      if (n>fgkWARN) AliWarning("Wrong invariant !");
263      return kFALSE;
264   }
265
266   if (chi2<0) return kTRUE;
267
268   // fill residuals for ITS+TPC tracks 
269   if (fESDtrack) {
270     if (fESDtrack->GetStatus()&AliESDtrack::kTPCin) {
271       AliTracker::FillResiduals(this,p,cov,c->GetVolumeId());
272     }
273   }
274
275   fIndex[n]=index;
276   SetNumberOfClusters(n+1);
277   SetChi2(GetChi2()+chi2);
278
279   return kTRUE;
280 }
281
282 Bool_t AliITStrackV2::Invariant() const {
283   //------------------------------------------------------------------
284   // This function is for debugging purpose only
285   //------------------------------------------------------------------
286   if(!fCheckInvariant) return kTRUE;
287
288   Int_t n=GetNumberOfClusters();
289
290   // take into account the misalignment error
291   Float_t maxMisalErrY2=0,maxMisalErrZ2=0;
292   for (Int_t lay=0; lay<AliITSgeomTGeo::kNLayers; lay++) {
293     maxMisalErrY2 = TMath::Max(maxMisalErrY2,AliITSReconstructor::GetRecoParam()->GetClusterMisalErrorY(lay,GetBz()));
294     maxMisalErrZ2 = TMath::Max(maxMisalErrZ2,AliITSReconstructor::GetRecoParam()->GetClusterMisalErrorZ(lay,GetBz()));
295   }
296   maxMisalErrY2 *= maxMisalErrY2;
297   maxMisalErrZ2 *= maxMisalErrZ2;
298   // this is because when we reset before refitting, we multiply the
299   // matrix by 10
300   maxMisalErrY2 *= 10.; 
301   maxMisalErrZ2 *= 10.;
302
303   Double_t sP2=GetParameter()[2];
304   if (TMath::Abs(sP2) >= kAlmost1){
305      if (n>fgkWARN) Warning("Invariant","fP2=%f\n",sP2);
306      return kFALSE;
307   }
308   Double_t sC00=GetCovariance()[0];
309   if (sC00<=0 || sC00>(9.+maxMisalErrY2)) {
310      if (n>fgkWARN) Warning("Invariant","fC00=%f\n",sC00); 
311      return kFALSE;
312   }
313   Double_t sC11=GetCovariance()[2];
314   if (sC11<=0 || sC11>(9.+maxMisalErrZ2)) {
315      if (n>fgkWARN) Warning("Invariant","fC11=%f\n",sC11); 
316      return kFALSE;
317   }
318   Double_t sC22=GetCovariance()[5];
319   if (sC22<=0 || sC22>1.) {
320      if (n>fgkWARN) Warning("Invariant","fC22=%f\n",sC22); 
321      return kFALSE;
322   }
323   Double_t sC33=GetCovariance()[9];
324   if (sC33<=0 || sC33>1.) {
325      if (n>fgkWARN) Warning("Invariant","fC33=%f\n",sC33); 
326      return kFALSE;
327   }
328   Double_t sC44=GetCovariance()[14];
329   if (sC44<=0 /*|| sC44>6e-5*/) {
330      if (n>fgkWARN) Warning("Invariant","fC44=%f\n",sC44);
331      return kFALSE;
332   }
333
334   return kTRUE;
335 }
336
337 //____________________________________________________________________________
338 Bool_t AliITStrackV2::Propagate(Double_t alp,Double_t xk) {
339   //------------------------------------------------------------------
340   //This function propagates a track
341   //------------------------------------------------------------------
342   //Double_t bz=GetBz();
343   //if (!AliExternalTrackParam::Propagate(alp,xk,bz)) return kFALSE;
344   Double_t b[3]; GetBxByBz(b);
345   if (!AliExternalTrackParam::PropagateBxByBz(alp,xk,b)) return kFALSE;
346
347   if (!Invariant()) {
348     Int_t n=GetNumberOfClusters();
349     if (n>fgkWARN) AliWarning("Wrong invariant !");
350     return kFALSE;
351   }
352
353   return kTRUE;
354 }
355
356 Bool_t AliITStrackV2::MeanBudgetToPrimVertex(Double_t xyz[3], Double_t step, Double_t &d) const {
357
358   //-------------------------------------------------------------------
359   //  Get the mean material budget between the actual point and the
360   //  primary vertex. (L.Gaudichet)
361   //-------------------------------------------------------------------
362
363   Double_t cs=TMath::Cos(GetAlpha()), sn=TMath::Sin(GetAlpha());
364   Double_t vertexX = xyz[0]*cs + xyz[1]*sn;
365
366   Int_t nstep = Int_t((GetX()-vertexX)/step);
367   if (nstep<1) nstep = 1;
368   step = (GetX()-vertexX)/nstep;
369
370   //  Double_t mparam[7], densMean=0, radLength=0, length=0;
371   Double_t mparam[7];
372   Double_t p1[3], p2[3], x = GetX(), bz = GetBz();
373   GetXYZ(p1);
374
375   d=0.;
376
377   for (Int_t i=0; i<nstep; i++) {
378     x  += step;
379     if (!GetXYZAt(x, bz, p2)) return kFALSE;
380     AliTracker::MeanMaterialBudget(p1, p2, mparam);
381     if (mparam[1]>900000) return kFALSE;
382     d  += mparam[1];
383
384     p1[0] = p2[0];
385     p1[1] = p2[1];
386     p1[2] = p2[2];
387   }
388
389   return kTRUE;
390 }
391
392 Bool_t AliITStrackV2::Improve(Double_t x0,Double_t xyz[3],Double_t ers[3]) {
393   //------------------------------------------------------------------
394   //This function improves angular track parameters
395   //------------------------------------------------------------------
396   //Store the initail track parameters
397
398   return kTRUE; //PH temporary switched off
399
400   Double_t x = GetX();
401   Double_t alpha = GetAlpha();
402   Double_t par[] = {GetY(),GetZ(),GetSnp(),GetTgl(),GetSigned1Pt()};
403   Double_t cov[] = {
404     GetSigmaY2(),
405     GetSigmaZY(),
406     GetSigmaZ2(),
407     GetSigmaSnpY(),
408     GetSigmaSnpZ(),
409     GetSigmaSnp2(),
410     GetSigmaTglY(),
411     GetSigmaTglZ(),
412     GetSigmaTglSnp(),
413     GetSigmaTgl2(),
414     GetSigma1PtY(),
415     GetSigma1PtZ(),
416     GetSigma1PtSnp(),
417     GetSigma1PtTgl(),
418     GetSigma1Pt2()
419   }; 
420
421
422   Double_t cs=TMath::Cos(GetAlpha()), sn=TMath::Sin(GetAlpha());
423 //Double_t xv = xyz[0]*cs + xyz[1]*sn; // vertex
424   Double_t yv =-xyz[0]*sn + xyz[1]*cs; // in the
425   Double_t zv = xyz[2];                // local frame
426
427   Double_t dy = par[0] - yv, dz = par[1] - zv;
428   Double_t r2=GetX()*GetX() + dy*dy;
429   Double_t p2=(1.+ GetTgl()*GetTgl())/(GetSigned1Pt()*GetSigned1Pt());
430   Double_t beta2=p2/(p2 + GetMass()*GetMass());
431   x0*=TMath::Sqrt((1.+ GetTgl()*GetTgl())/(1.- GetSnp()*GetSnp()));
432   Double_t theta2=14.1*14.1/(beta2*p2*1e6)*x0;
433   //Double_t theta2=1.0259e-6*14*14/28/(beta2*p2)*x0*9.36*2.33;
434
435   Double_t cnv=GetBz()*kB2C;
436   {
437     Double_t dummy = 4/r2 - GetC()*GetC();
438     if (dummy < 0) return kFALSE;
439     Double_t parp = 0.5*(GetC()*GetX() + dy*TMath::Sqrt(dummy));
440     Double_t sigma2p = theta2*(1.-GetSnp())*(1.+GetSnp())*(1. + GetTgl()*GetTgl());
441     Double_t ovSqr2 = 1./TMath::Sqrt(r2);
442     Double_t tfact = ovSqr2*(1.-dy*ovSqr2)*(1.+dy*ovSqr2);
443     sigma2p += cov[0]*tfact*tfact;
444     sigma2p += ers[1]*ers[1]/r2;
445     sigma2p += 0.25*cov[14]*cnv*cnv*GetX()*GetX();
446     Double_t eps2p=sigma2p/(cov[5] + sigma2p);
447     par[0] += cov[3]/(cov[5] + sigma2p)*(parp - GetSnp());
448     par[2]  = eps2p*GetSnp() + (1 - eps2p)*parp;
449     cov[5] *= eps2p;
450     cov[3] *= eps2p;
451   }
452   {
453     Double_t parl=0.5*GetC()*dz/TMath::ASin(0.5*GetC()*TMath::Sqrt(r2));
454     Double_t sigma2l=theta2;
455     sigma2l += cov[2]/r2 + cov[0]*dy*dy*dz*dz/(r2*r2*r2);
456     sigma2l += ers[2]*ers[2]/r2;
457     Double_t eps2l = sigma2l/(cov[9] + sigma2l);
458     par[1] += cov[7 ]/(cov[9] + sigma2l)*(parl - par[3]);
459     par[4] += cov[13]/(cov[9] + sigma2l)*(parl - par[3]);
460     par[3]  = eps2l*par[3] + (1-eps2l)*parl;
461     cov[9] *= eps2l; 
462     cov[13]*= eps2l; 
463     cov[7] *= eps2l; 
464   }
465
466   Set(x,alpha,par,cov);
467
468   if (!Invariant()) return kFALSE;
469
470   return kTRUE;
471 }
472
473 void AliITStrackV2::CookdEdx(Double_t low, Double_t up) {
474   //-----------------------------------------------------------------
475   // This function calculates dE/dX within the "low" and "up" cuts.
476   // Origin: Boris Batyunya, JINR, Boris.Batiounia@cern.ch 
477   // Updated: F. Prino 8-June-2009
478   //-----------------------------------------------------------------
479   // The cluster order is: SDD-1, SDD-2, SSD-1, SSD-2
480
481   Int_t nc=0;
482   Float_t dedx[4];
483   for (Int_t il=0; il<4; il++) { // count good (>0) dE/dx values
484     if(fdEdxSample[il]>0.){
485       dedx[nc]= fdEdxSample[il];
486       nc++;
487     }
488   }
489   if(nc<1){
490     SetdEdx(0.);
491     return;
492   }
493
494   Int_t swap; // sort in ascending order
495   do {
496     swap=0;
497     for (Int_t i=0; i<nc-1; i++) {
498       if (dedx[i]<=dedx[i+1]) continue;
499       Float_t tmp=dedx[i];
500       dedx[i]=dedx[i+1]; 
501       dedx[i+1]=tmp;
502       swap++;
503     }
504   } while (swap);
505
506
507   Double_t nl=low*nc, nu =up*nc;
508   Float_t sumamp = 0;
509   Float_t sumweight =0;
510   for (Int_t i=0; i<nc; i++) {
511     Float_t weight =1;
512     if (i<nl+0.1)     weight = TMath::Max(1.-(nl-i),0.);
513     if (i>nu-1)     weight = TMath::Max(nu-i,0.);
514     sumamp+= dedx[i]*weight;
515     sumweight+=weight;
516   }
517   SetdEdx(sumamp/sumweight);
518 }
519
520 //____________________________________________________________________________
521 Bool_t AliITStrackV2::
522 GetPhiZat(Double_t r, Double_t &phi, Double_t &z) const {
523   //------------------------------------------------------------------
524   // This function returns the global cylindrical (phi,z) of the track 
525   // position estimated at the radius r. 
526   // The track curvature is neglected.
527   //------------------------------------------------------------------
528   Double_t d=GetD(0.,0.);
529   if (TMath::Abs(d) > r) {
530     if (r>1e-1) return kFALSE;
531     r = TMath::Abs(d);
532   }
533
534   Double_t rcurr=TMath::Sqrt(GetX()*GetX() + GetY()*GetY());
535   if (TMath::Abs(d) > rcurr) return kFALSE;
536   Double_t globXYZcurr[3]; GetXYZ(globXYZcurr); 
537   Double_t phicurr=TMath::ATan2(globXYZcurr[1],globXYZcurr[0]);
538
539   if (GetX()>=0.) {
540     phi=phicurr+TMath::ASin(d/r)-TMath::ASin(d/rcurr);
541   } else {
542     phi=phicurr+TMath::ASin(d/r)+TMath::ASin(d/rcurr)-TMath::Pi();
543   }
544
545   // return a phi in [0,2pi[ 
546   if (phi<0.) phi+=2.*TMath::Pi();
547   else if (phi>=2.*TMath::Pi()) phi-=2.*TMath::Pi();
548   z=GetZ()+GetTgl()*(TMath::Sqrt((r-d)*(r+d))-TMath::Sqrt((rcurr-d)*(rcurr+d)));
549   return kTRUE;
550 }
551 //____________________________________________________________________________
552 Bool_t AliITStrackV2::
553 GetLocalXat(Double_t r,Double_t &xloc) const {
554   //------------------------------------------------------------------
555   // This function returns the local x of the track 
556   // position estimated at the radius r. 
557   // The track curvature is neglected.
558   //------------------------------------------------------------------
559   Double_t d=GetD(0.,0.);
560   if (TMath::Abs(d) > r) { 
561     if (r>1e-1) return kFALSE; 
562     r = TMath::Abs(d); 
563   } 
564
565   Double_t rcurr=TMath::Sqrt(GetX()*GetX() + GetY()*GetY());
566   Double_t globXYZcurr[3]; GetXYZ(globXYZcurr); 
567   Double_t phicurr=TMath::ATan2(globXYZcurr[1],globXYZcurr[0]);
568   Double_t phi;
569   if (GetX()>=0.) {
570     phi=phicurr+TMath::ASin(d/r)-TMath::ASin(d/rcurr);
571   } else {
572     phi=phicurr+TMath::ASin(d/r)+TMath::ASin(d/rcurr)-TMath::Pi();
573   }
574
575   xloc=r*(TMath::Cos(phi)*TMath::Cos(GetAlpha())
576          +TMath::Sin(phi)*TMath::Sin(GetAlpha())); 
577
578   return kTRUE;
579 }