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