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 : /* $Id$ */
17 :
18 : ///////////////////////////////////////////////////////////////////////////////
19 : // //
20 : // Implementation of the external track parameterisation class. //
21 : // //
22 : // This parameterisation is used to exchange tracks between the detectors. //
23 : // A set of functions returning the position and the momentum of tracks //
24 : // in the global coordinate system as well as the track impact parameters //
25 : // are implemented.
26 : // Origin: I.Belikov, CERN, Jouri.Belikov@cern.ch //
27 : ///////////////////////////////////////////////////////////////////////////////
28 : #include <cassert>
29 :
30 : #include <TVectorD.h>
31 : #include <TMatrixDSym.h>
32 : #include <TPolyMarker3D.h>
33 : #include <TVector3.h>
34 : #include <TMatrixD.h>
35 :
36 : #include "AliExternalTrackParam.h"
37 : #include "AliVVertex.h"
38 : #include "AliLog.h"
39 :
40 176 : ClassImp(AliExternalTrackParam)
41 :
42 : Double32_t AliExternalTrackParam::fgMostProbablePt=kMostProbablePt;
43 : Bool_t AliExternalTrackParam::fgUseLogTermMS = kFALSE;;
44 : //_____________________________________________________________________________
45 : AliExternalTrackParam::AliExternalTrackParam() :
46 40576 : AliVTrack(),
47 40576 : fX(0),
48 40576 : fAlpha(0)
49 160388 : {
50 : //
51 : // default constructor
52 : //
53 486912 : for (Int_t i = 0; i < 5; i++) fP[i] = 0;
54 1298432 : for (Int_t i = 0; i < 15; i++) fC[i] = 0;
55 59906 : }
56 :
57 : //_____________________________________________________________________________
58 : AliExternalTrackParam::AliExternalTrackParam(const AliExternalTrackParam &track):
59 24232 : AliVTrack(track),
60 24232 : fX(track.fX),
61 24232 : fAlpha(track.fAlpha)
62 87370 : {
63 : //
64 : // copy constructor
65 : //
66 290784 : for (Int_t i = 0; i < 5; i++) fP[i] = track.fP[i];
67 775424 : for (Int_t i = 0; i < 15; i++) fC[i] = track.fC[i];
68 24232 : CheckCovariance();
69 31569 : }
70 :
71 : //_____________________________________________________________________________
72 : AliExternalTrackParam& AliExternalTrackParam::operator=(const AliExternalTrackParam &trkPar)
73 : {
74 : //
75 : // assignment operator
76 : //
77 :
78 31792 : if (this!=&trkPar) {
79 15896 : AliVTrack::operator=(trkPar);
80 15896 : fX = trkPar.fX;
81 15896 : fAlpha = trkPar.fAlpha;
82 :
83 190752 : for (Int_t i = 0; i < 5; i++) fP[i] = trkPar.fP[i];
84 508672 : for (Int_t i = 0; i < 15; i++) fC[i] = trkPar.fC[i];
85 15896 : CheckCovariance();
86 15896 : }
87 :
88 15896 : return *this;
89 : }
90 :
91 : //_____________________________________________________________________________
92 : AliExternalTrackParam::AliExternalTrackParam(Double_t x, Double_t alpha,
93 : const Double_t param[5],
94 : const Double_t covar[15]) :
95 96 : AliVTrack(),
96 96 : fX(x),
97 96 : fAlpha(alpha)
98 480 : {
99 : //
100 : // create external track parameters from given arguments
101 : //
102 1152 : for (Int_t i = 0; i < 5; i++) fP[i] = param[i];
103 3072 : for (Int_t i = 0; i < 15; i++) fC[i] = covar[i];
104 96 : CheckCovariance();
105 192 : }
106 :
107 : //_____________________________________________________________________________
108 : void AliExternalTrackParam::CopyFromVTrack(const AliVTrack *vTrack)
109 : {
110 : //
111 : // Recreate TrackParams from VTrack
112 : // This is not a copy contructor !
113 : //
114 0 : if (!vTrack) {
115 0 : AliError("Source VTrack is NULL");
116 0 : return;
117 : }
118 0 : if (this==vTrack) {
119 0 : AliError("Copy of itself is requested");
120 0 : return;
121 : }
122 : //
123 0 : if (vTrack->InheritsFrom(AliExternalTrackParam::Class())) {
124 0 : AliDebug(1,"Source itself is AliExternalTrackParam, using assignment operator");
125 0 : *this = *(AliExternalTrackParam*)vTrack;
126 0 : return;
127 : }
128 : //
129 0 : AliVTrack::operator=( *vTrack );
130 : //
131 0 : Double_t xyz[3],pxpypz[3],cv[21];
132 0 : vTrack->GetXYZ(xyz);
133 0 : pxpypz[0]=vTrack->Px();
134 0 : pxpypz[1]=vTrack->Py();
135 0 : pxpypz[2]=vTrack->Pz();
136 0 : vTrack->GetCovarianceXYZPxPyPz(cv);
137 0 : Short_t sign = (Short_t)vTrack->Charge();
138 0 : Set(xyz,pxpypz,cv,sign);
139 0 : }
140 :
141 : //_____________________________________________________________________________
142 : AliExternalTrackParam::AliExternalTrackParam(const AliVTrack *vTrack) :
143 0 : AliVTrack(),
144 0 : fX(0.),
145 0 : fAlpha(0.)
146 0 : {
147 : //
148 : // Constructor from virtual track,
149 : // This is not a copy contructor !
150 : //
151 :
152 0 : if (vTrack->InheritsFrom("AliExternalTrackParam")) {
153 0 : AliError("This is not a copy constructor. Use AliExternalTrackParam(const AliExternalTrackParam &) !");
154 0 : AliWarning("Calling the default constructor...");
155 0 : AliExternalTrackParam();
156 0 : return;
157 : }
158 :
159 0 : Double_t xyz[3],pxpypz[3],cv[21];
160 0 : vTrack->GetXYZ(xyz);
161 0 : pxpypz[0]=vTrack->Px();
162 0 : pxpypz[1]=vTrack->Py();
163 0 : pxpypz[2]=vTrack->Pz();
164 0 : vTrack->GetCovarianceXYZPxPyPz(cv);
165 0 : Short_t sign = (Short_t)vTrack->Charge();
166 :
167 0 : Set(xyz,pxpypz,cv,sign);
168 0 : }
169 :
170 : //_____________________________________________________________________________
171 : AliExternalTrackParam::AliExternalTrackParam(Double_t xyz[3],Double_t pxpypz[3],
172 : Double_t cv[21],Short_t sign) :
173 0 : AliVTrack(),
174 0 : fX(0.),
175 0 : fAlpha(0.)
176 0 : {
177 : //
178 : // constructor from the global parameters
179 : //
180 :
181 0 : Set(xyz,pxpypz,cv,sign);
182 0 : }
183 :
184 : /*
185 : //_____________________________________________________________________________
186 : void AliExternalTrackParam::Set(Double_t xyz[3],Double_t pxpypz[3],
187 : Double_t cv[21],Short_t sign)
188 : {
189 : //
190 : // create external track parameters from the global parameters
191 : // x,y,z,px,py,pz and their 6x6 covariance matrix
192 : // A.Dainese 10.10.08
193 :
194 : // Calculate alpha: the rotation angle of the corresponding local system.
195 : //
196 : // For global radial position inside the beam pipe, alpha is the
197 : // azimuthal angle of the momentum projected on (x,y).
198 : //
199 : // For global radial position outside the ITS, alpha is the
200 : // azimuthal angle of the centre of the TPC sector in which the point
201 : // xyz lies
202 : //
203 : const double kSafe = 1e-5;
204 : Double_t radPos2 = xyz[0]*xyz[0]+xyz[1]*xyz[1];
205 : Double_t radMax = 45.; // approximately ITS outer radius
206 : if (radPos2 < radMax*radMax) { // inside the ITS
207 : fAlpha = TMath::ATan2(pxpypz[1],pxpypz[0]);
208 : } else { // outside the ITS
209 : Float_t phiPos = TMath::Pi()+TMath::ATan2(-xyz[1], -xyz[0]);
210 : fAlpha =
211 : TMath::DegToRad()*(20*((((Int_t)(phiPos*TMath::RadToDeg()))/20))+10);
212 : }
213 : //
214 : Double_t cs=TMath::Cos(fAlpha), sn=TMath::Sin(fAlpha);
215 : // protection: avoid alpha being too close to 0 or +-pi/2
216 : if (TMath::Abs(sn)<2*kSafe) {
217 : if (fAlpha>0) fAlpha += fAlpha< TMath::Pi()/2. ? 2*kSafe : -2*kSafe;
218 : else fAlpha += fAlpha>-TMath::Pi()/2. ? -2*kSafe : 2*kSafe;
219 : cs=TMath::Cos(fAlpha);
220 : sn=TMath::Sin(fAlpha);
221 : }
222 : else if (TMath::Abs(cs)<2*kSafe) {
223 : if (fAlpha>0) fAlpha += fAlpha> TMath::Pi()/2. ? 2*kSafe : -2*kSafe;
224 : else fAlpha += fAlpha>-TMath::Pi()/2. ? 2*kSafe : -2*kSafe;
225 : cs=TMath::Cos(fAlpha);
226 : sn=TMath::Sin(fAlpha);
227 : }
228 : // Get the vertex of origin and the momentum
229 : TVector3 ver(xyz[0],xyz[1],xyz[2]);
230 : TVector3 mom(pxpypz[0],pxpypz[1],pxpypz[2]);
231 : //
232 : // avoid momenta along axis
233 : if (TMath::Abs(mom[0])<kSafe) mom[0] = TMath::Sign(kSafe*TMath::Abs(mom[1]), mom[0]);
234 : if (TMath::Abs(mom[1])<kSafe) mom[1] = TMath::Sign(kSafe*TMath::Abs(mom[0]), mom[1]);
235 :
236 : // Rotate to the local coordinate system
237 : ver.RotateZ(-fAlpha);
238 : mom.RotateZ(-fAlpha);
239 :
240 : //
241 : // x of the reference plane
242 : fX = ver.X();
243 :
244 : Double_t charge = (Double_t)sign;
245 :
246 : fP[0] = ver.Y();
247 : fP[1] = ver.Z();
248 : fP[2] = TMath::Sin(mom.Phi());
249 : fP[3] = mom.Pz()/mom.Pt();
250 : fP[4] = TMath::Sign(1/mom.Pt(),charge);
251 : //
252 : if (TMath::Abs( 1-fP[2]) < 3*kSafe) fP[2] = 1.- 3*kSafe; //Protection
253 : else if (TMath::Abs(-1-fP[2]) < 3*kSafe) fP[2] =-1.+ 3*kSafe; //Protection
254 : //
255 : // Covariance matrix (formulas to be simplified)
256 : Double_t pt=1./TMath::Abs(fP[4]);
257 : // avoid alpha+phi being to close to +-pi/2 in the cov.matrix evaluation
258 : double fp2 = fP[2];
259 : Double_t r=TMath::Sqrt((1.-fp2)*(1.+fp2));
260 : //
261 : Double_t m00=-sn;// m10=cs;
262 : Double_t m23=-pt*(sn + fp2*cs/r), m43=-pt*pt*(r*cs - fp2*sn);
263 : Double_t m24= pt*(cs - fp2*sn/r), m44=-pt*pt*(r*sn + fp2*cs);
264 : Double_t m35=pt, m45=-pt*pt*fP[3];
265 :
266 : m43*=GetSign();
267 : m44*=GetSign();
268 : m45*=GetSign();
269 :
270 : Double_t cv34 = TMath::Sqrt(cv[3 ]*cv[3 ]+cv[4 ]*cv[4 ]);
271 : Double_t a1=cv[13]-cv[9]*(m23*m44+m43*m24)/m23/m43;
272 : Double_t a2=m23*m24-m23*(m23*m44+m43*m24)/m43;
273 : Double_t a3=m43*m44-m43*(m23*m44+m43*m24)/m23;
274 : Double_t a4=cv[14]+2.*cv[9]; //cv[14]-2.*cv[9]*m24*m44/m23/m43;
275 : Double_t a5=m24*m24-2.*m24*m44*m23/m43;
276 : Double_t a6=m44*m44-2.*m24*m44*m43/m23;
277 :
278 : fC[0 ] = cv[0 ]+cv[2 ];
279 : fC[1 ] = TMath::Sign(cv34,cv[3 ]/m00);
280 : fC[2 ] = cv[5 ];
281 : fC[3 ] = (cv[10]*m43-cv[6]*m44)/(m24*m43-m23*m44)/m00;
282 : fC[10] = (cv[6]/m00-fC[3 ]*m23)/m43;
283 : fC[6 ] = (cv[15]/m00-fC[10]*m45)/m35;
284 : fC[4 ] = (cv[12]*m43-cv[8]*m44)/(m24*m43-m23*m44);
285 : fC[11] = (cv[8]-fC[4]*m23)/m43;
286 : fC[7 ] = cv[17]/m35-fC[11]*m45/m35;
287 : fC[5 ] = TMath::Abs((a4*a3-a6*a1)/(a5*a3-a6*a2));
288 : fC[14] = TMath::Abs((a1-a2*fC[5])/a3);
289 : fC[12] = (cv[9]-fC[5]*m23*m23-fC[14]*m43*m43)/m23/m43;
290 : Double_t b1=cv[18]-fC[12]*m23*m45-fC[14]*m43*m45;
291 : Double_t b2=m23*m35;
292 : Double_t b3=m43*m35;
293 : Double_t b4=cv[19]-fC[12]*m24*m45-fC[14]*m44*m45;
294 : Double_t b5=m24*m35;
295 : Double_t b6=m44*m35;
296 : fC[8 ] = (b4-b6*b1/b3)/(b5-b6*b2/b3);
297 : fC[13] = b1/b3-b2*fC[8]/b3;
298 : fC[9 ] = TMath::Abs((cv[20]-fC[14]*(m45*m45)-fC[13]*2.*m35*m45)/(m35*m35));
299 :
300 : CheckCovariance();
301 :
302 : return;
303 : }
304 : */
305 :
306 : //_____________________________________________________________________________
307 : void AliExternalTrackParam::Set(Double_t xyz[3],Double_t pxpypz[3],
308 : Double_t cv[21],Short_t sign)
309 : {
310 : //
311 : // create external track parameters from the global parameters
312 : // x,y,z,px,py,pz and their 6x6 covariance matrix
313 : // A.Dainese 10.10.08
314 :
315 : // Calculate alpha: the rotation angle of the corresponding local system.
316 : //
317 : // For global radial position inside the beam pipe, alpha is the
318 : // azimuthal angle of the momentum projected on (x,y).
319 : //
320 : // For global radial position outside the ITS, alpha is the
321 : // azimuthal angle of the centre of the TPC sector in which the point
322 : // xyz lies
323 : //
324 : const double kSafe = 1e-5;
325 8 : Double_t radPos2 = xyz[0]*xyz[0]+xyz[1]*xyz[1];
326 : Double_t radMax = 45.; // approximately ITS outer radius
327 4 : if (radPos2 < radMax*radMax) { // inside the ITS
328 0 : fAlpha = TMath::ATan2(pxpypz[1],pxpypz[0]);
329 0 : } else { // outside the ITS
330 4 : Float_t phiPos = TMath::Pi()+TMath::ATan2(-xyz[1], -xyz[0]);
331 4 : fAlpha =
332 4 : TMath::DegToRad()*(20*((((Int_t)(phiPos*TMath::RadToDeg()))/20))+10);
333 : }
334 : //
335 4 : Double_t cs=TMath::Cos(fAlpha), sn=TMath::Sin(fAlpha);
336 : // protection: avoid alpha being too close to 0 or +-pi/2
337 4 : if (TMath::Abs(sn)<2*kSafe) {
338 0 : if (fAlpha>0) fAlpha += fAlpha< TMath::Pi()/2. ? 2*kSafe : -2*kSafe;
339 0 : else fAlpha += fAlpha>-TMath::Pi()/2. ? -2*kSafe : 2*kSafe;
340 0 : cs=TMath::Cos(fAlpha);
341 0 : sn=TMath::Sin(fAlpha);
342 0 : }
343 4 : else if (TMath::Abs(cs)<2*kSafe) {
344 8 : if (fAlpha>0) fAlpha += fAlpha> TMath::Pi()/2. ? 2*kSafe : -2*kSafe;
345 0 : else fAlpha += fAlpha>-TMath::Pi()/2. ? 2*kSafe : -2*kSafe;
346 4 : cs=TMath::Cos(fAlpha);
347 4 : sn=TMath::Sin(fAlpha);
348 4 : }
349 : // Get the vertex of origin and the momentum
350 4 : TVector3 ver(xyz[0],xyz[1],xyz[2]);
351 4 : TVector3 mom(pxpypz[0],pxpypz[1],pxpypz[2]);
352 : //
353 : // Rotate to the local coordinate system
354 4 : ver.RotateZ(-fAlpha);
355 4 : mom.RotateZ(-fAlpha);
356 :
357 : //
358 : // x of the reference plane
359 4 : fX = ver.X();
360 :
361 4 : Double_t charge = (Double_t)sign;
362 :
363 4 : fP[0] = ver.Y();
364 4 : fP[1] = ver.Z();
365 8 : fP[2] = TMath::Sin(mom.Phi());
366 8 : fP[3] = mom.Pz()/mom.Pt();
367 8 : fP[4] = TMath::Sign(1/mom.Pt(),charge);
368 : //
369 4 : if (TMath::Abs( 1-fP[2]) < kSafe) fP[2] = 1.- kSafe; //Protection
370 4 : else if (TMath::Abs(-1-fP[2]) < kSafe) fP[2] =-1.+ kSafe; //Protection
371 : //
372 : // Covariance matrix (formulas to be simplified)
373 4 : Double_t pt=1./TMath::Abs(fP[4]);
374 4 : Double_t r=TMath::Sqrt((1.-fP[2])*(1.+fP[2]));
375 : //
376 4 : Double_t cv34 = TMath::Sqrt(cv[3 ]*cv[3 ]+cv[4 ]*cv[4 ]);
377 : //
378 : Int_t special = 0;
379 4 : double sgcheck = r*sn + fP[2]*cs;
380 4 : if (TMath::Abs(sgcheck)>=1-kSafe) { // special case: lab phi is +-pi/2
381 : special = 1;
382 0 : sgcheck = TMath::Sign(1.0,sgcheck);
383 0 : }
384 4 : else if (TMath::Abs(sgcheck)<kSafe) {
385 0 : sgcheck = TMath::Sign(1.0,cs);
386 : special = 2; // special case: lab phi is 0
387 0 : }
388 : //
389 4 : fC[0 ] = cv[0 ]+cv[2 ];
390 4 : fC[1 ] = TMath::Sign(cv34,-cv[3 ]*sn);
391 4 : fC[2 ] = cv[5 ];
392 : //
393 4 : if (special==1) {
394 0 : double pti = 1./pt;
395 0 : double pti2 = pti*pti;
396 0 : int q = GetSign();
397 0 : fC[3 ] = cv[6]*pti;
398 0 : fC[4 ] = -sgcheck*cv[8]*r*pti;
399 0 : fC[5 ] = TMath::Abs(cv[9]*r*r*pti2);
400 0 : fC[6 ] = (cv[10]*fP[3]-sgcheck*cv[15])*pti/r;
401 0 : fC[7 ] = (cv[17]-sgcheck*cv[12]*fP[3])*pti;
402 0 : fC[8 ] = (-sgcheck*cv[18]+cv[13]*fP[3])*r*pti2;
403 0 : fC[9 ] = TMath::Abs( cv[20]-2*sgcheck*cv[19]*fP[3]+cv[14]*fP[3]*fP[3])*pti2;
404 0 : fC[10] = cv[10]*pti2/r*q;
405 0 : fC[11] = -sgcheck*cv[12]*pti2*q;
406 0 : fC[12] = cv[13]*r*pti*pti2*q;
407 0 : fC[13] = (-sgcheck*cv[19]+cv[14]*fP[3])*r*pti2*pti;
408 0 : fC[14] = TMath::Abs(cv[14]*pti2*pti2);
409 4 : } else if (special==2) {
410 0 : double pti = 1./pt;
411 0 : double pti2 = pti*pti;
412 0 : int q = GetSign();
413 0 : fC[3 ] = -cv[10]*pti*cs/sn;
414 0 : fC[4 ] = cv[12]*cs*pti;
415 0 : fC[5 ] = TMath::Abs(cv[14]*cs*cs*pti2);
416 0 : fC[6 ] = (sgcheck*cv[6]*fP[3]-cv[15])*pti/sn;
417 0 : fC[7 ] = (cv[17]-sgcheck*cv[8]*fP[3])*pti;
418 0 : fC[8 ] = (cv[19]-sgcheck*cv[13]*fP[3])*cs*pti2;
419 0 : fC[9 ] = TMath::Abs( cv[20]-2*sgcheck*cv[18]*fP[3]+cv[9]*fP[3]*fP[3])*pti2;
420 0 : fC[10] = sgcheck*cv[6]*pti2/sn*q;
421 0 : fC[11] = -sgcheck*cv[8]*pti2*q;
422 0 : fC[12] = -sgcheck*cv[13]*cs*pti*pti2*q;
423 0 : fC[13] = (-sgcheck*cv[18]+cv[9]*fP[3])*pti2*pti*q;
424 0 : fC[14] = TMath::Abs(cv[9]*pti2*pti2);
425 0 : }
426 : else {
427 4 : Double_t m00=-sn;// m10=cs;
428 4 : Double_t m23=-pt*(sn + fP[2]*cs/r), m43=-pt*pt*(r*cs - fP[2]*sn);
429 4 : Double_t m24= pt*(cs - fP[2]*sn/r), m44=-pt*pt*(r*sn + fP[2]*cs);
430 4 : Double_t m35=pt, m45=-pt*pt*fP[3];
431 : //
432 8 : m43*=GetSign();
433 8 : m44*=GetSign();
434 8 : m45*=GetSign();
435 : //
436 4 : Double_t a1=cv[13]-cv[9]*(m23*m44+m43*m24)/m23/m43;
437 4 : Double_t a2=m23*m24-m23*(m23*m44+m43*m24)/m43;
438 4 : Double_t a3=m43*m44-m43*(m23*m44+m43*m24)/m23;
439 4 : Double_t a4=cv[14]+2.*cv[9]; //cv[14]-2.*cv[9]*m24*m44/m23/m43;
440 4 : Double_t a5=m24*m24-2.*m24*m44*m23/m43;
441 4 : Double_t a6=m44*m44-2.*m24*m44*m43/m23;
442 : //
443 4 : fC[3 ] = (cv[10]*m43-cv[6]*m44)/(m24*m43-m23*m44)/m00;
444 4 : fC[10] = (cv[6]/m00-fC[3 ]*m23)/m43;
445 4 : fC[6 ] = (cv[15]/m00-fC[10]*m45)/m35;
446 4 : fC[4 ] = (cv[12]*m43-cv[8]*m44)/(m24*m43-m23*m44);
447 4 : fC[11] = (cv[8]-fC[4]*m23)/m43;
448 4 : fC[7 ] = cv[17]/m35-fC[11]*m45/m35;
449 4 : fC[5 ] = TMath::Abs((a4*a3-a6*a1)/(a5*a3-a6*a2));
450 4 : fC[14] = TMath::Abs((a1-a2*fC[5])/a3);
451 4 : fC[12] = (cv[9]-fC[5]*m23*m23-fC[14]*m43*m43)/m23/m43;
452 4 : Double_t b1=cv[18]-fC[12]*m23*m45-fC[14]*m43*m45;
453 4 : Double_t b2=m23*m35;
454 4 : Double_t b3=m43*m35;
455 4 : Double_t b4=cv[19]-fC[12]*m24*m45-fC[14]*m44*m45;
456 4 : Double_t b5=m24*m35;
457 4 : Double_t b6=m44*m35;
458 4 : fC[8 ] = (b4-b6*b1/b3)/(b5-b6*b2/b3);
459 4 : fC[13] = b1/b3-b2*fC[8]/b3;
460 4 : fC[9 ] = TMath::Abs((cv[20]-fC[14]*(m45*m45)-fC[13]*2.*m35*m45)/(m35*m35));
461 : }
462 4 : CheckCovariance();
463 :
464 : return;
465 4 : }
466 :
467 : //_____________________________________________________________________________
468 : void AliExternalTrackParam::Reset() {
469 : //
470 : // Resets all the parameters to 0
471 : //
472 0 : fX=fAlpha=0.;
473 0 : for (Int_t i = 0; i < 5; i++) fP[i] = 0;
474 0 : for (Int_t i = 0; i < 15; i++) fC[i] = 0;
475 0 : }
476 :
477 : //_____________________________________________________________________________
478 : void AliExternalTrackParam::AddCovariance(const Double_t c[15]) {
479 : //
480 : // Add "something" to the track covarince matrix.
481 : // May be needed to account for unknown mis-calibration/mis-alignment
482 : //
483 24 : fC[0] +=c[0];
484 12 : fC[1] +=c[1]; fC[2] +=c[2];
485 12 : fC[3] +=c[3]; fC[4] +=c[4]; fC[5] +=c[5];
486 12 : fC[6] +=c[6]; fC[7] +=c[7]; fC[8] +=c[8]; fC[9] +=c[9];
487 12 : fC[10]+=c[10]; fC[11]+=c[11]; fC[12]+=c[12]; fC[13]+=c[13]; fC[14]+=c[14];
488 12 : CheckCovariance();
489 12 : }
490 :
491 :
492 : Double_t AliExternalTrackParam::GetP() const {
493 : //---------------------------------------------------------------------
494 : // This function returns the track momentum
495 : // Results for (nearly) straight tracks are meaningless !
496 : //---------------------------------------------------------------------
497 1437636 : if (TMath::Abs(fP[4])<=kAlmost0) return kVeryBig;
498 718818 : return TMath::Sqrt(1.+ fP[3]*fP[3])/TMath::Abs(fP[4]);
499 718818 : }
500 :
501 : Double_t AliExternalTrackParam::Get1P() const {
502 : //---------------------------------------------------------------------
503 : // This function returns the 1/(track momentum)
504 : //---------------------------------------------------------------------
505 0 : return TMath::Abs(fP[4])/TMath::Sqrt(1.+ fP[3]*fP[3]);
506 : }
507 :
508 : //_______________________________________________________________________
509 : Double_t AliExternalTrackParam::GetD(Double_t x,Double_t y,Double_t b) const {
510 : //------------------------------------------------------------------
511 : // This function calculates the transverse impact parameter
512 : // with respect to a point with global coordinates (x,y)
513 : // in the magnetic field "b" (kG)
514 : //------------------------------------------------------------------
515 101878 : if (TMath::Abs(b) < kAlmost0Field) return GetLinearD(x,y);
516 50939 : Double_t rp4=GetC(b);
517 :
518 50939 : Double_t xt=fX, yt=fP[0];
519 :
520 50939 : Double_t sn=TMath::Sin(fAlpha), cs=TMath::Cos(fAlpha);
521 50939 : Double_t a = x*cs + y*sn;
522 50939 : y = -x*sn + y*cs; x=a;
523 50939 : xt-=x; yt-=y;
524 :
525 50939 : sn=rp4*xt - fP[2]; cs=rp4*yt + TMath::Sqrt((1.- fP[2])*(1.+fP[2]));
526 50939 : a=2*(xt*fP[2] - yt*TMath::Sqrt((1.-fP[2])*(1.+fP[2])))-rp4*(xt*xt + yt*yt);
527 50939 : return -a/(1 + TMath::Sqrt(sn*sn + cs*cs));
528 50939 : }
529 :
530 : //_______________________________________________________________________
531 : void AliExternalTrackParam::
532 : GetDZ(Double_t x, Double_t y, Double_t z, Double_t b, Float_t dz[2]) const {
533 : //------------------------------------------------------------------
534 : // This function calculates the transverse and longitudinal impact parameters
535 : // with respect to a point with global coordinates (x,y)
536 : // in the magnetic field "b" (kG)
537 : //------------------------------------------------------------------
538 6356 : Double_t f1 = fP[2], r1 = TMath::Sqrt((1.-f1)*(1.+f1));
539 3178 : Double_t xt=fX, yt=fP[0];
540 3178 : Double_t sn=TMath::Sin(fAlpha), cs=TMath::Cos(fAlpha);
541 3178 : Double_t a = x*cs + y*sn;
542 3178 : y = -x*sn + y*cs; x=a;
543 3178 : xt-=x; yt-=y;
544 :
545 3178 : Double_t rp4=GetC(b);
546 6356 : if ((TMath::Abs(b) < kAlmost0Field) || (TMath::Abs(rp4) < kAlmost0)) {
547 0 : dz[0] = -(xt*f1 - yt*r1);
548 0 : dz[1] = fP[1] + (dz[0]*f1 - xt)/r1*fP[3] - z;
549 0 : return;
550 : }
551 :
552 3178 : sn=rp4*xt - f1; cs=rp4*yt + r1;
553 3178 : a=2*(xt*f1 - yt*r1)-rp4*(xt*xt + yt*yt);
554 3178 : Double_t rr=TMath::Sqrt(sn*sn + cs*cs);
555 3178 : dz[0] = -a/(1 + rr);
556 3178 : Double_t f2 = -sn/rr, r2 = TMath::Sqrt((1.-f2)*(1.+f2));
557 3178 : dz[1] = fP[1] + fP[3]/rp4*TMath::ASin(f2*r1 - f1*r2) - z;
558 6356 : }
559 :
560 : //_______________________________________________________________________
561 : Double_t AliExternalTrackParam::GetLinearD(Double_t xv,Double_t yv) const {
562 : //------------------------------------------------------------------
563 : // This function calculates the transverse impact parameter
564 : // with respect to a point with global coordinates (xv,yv)
565 : // neglecting the track curvature.
566 : //------------------------------------------------------------------
567 0 : Double_t sn=TMath::Sin(fAlpha), cs=TMath::Cos(fAlpha);
568 0 : Double_t x= xv*cs + yv*sn;
569 0 : Double_t y=-xv*sn + yv*cs;
570 :
571 0 : Double_t d = (fX-x)*fP[2] - (fP[0]-y)*TMath::Sqrt((1.-fP[2])*(1.+fP[2]));
572 :
573 0 : return -d;
574 : }
575 :
576 : Bool_t AliExternalTrackParam::CorrectForMeanMaterialdEdx
577 : (Double_t xOverX0, Double_t xTimesRho, Double_t mass,
578 : Double_t dEdx,
579 : Bool_t anglecorr) {
580 : //------------------------------------------------------------------
581 : // This function corrects the track parameters for the crossed material.
582 : // "xOverX0" - X/X0, the thickness in units of the radiation length.
583 : // "xTimesRho" - is the product length*density (g/cm^2).
584 : // It should be passed as negative when propagating tracks
585 : // from the intreaction point to the outside of the central barrel.
586 : // "mass" - the mass of this particle (GeV/c^2). Negative mass means charge=2 particle
587 : // "dEdx" - mean enery loss (GeV/(g/cm^2)
588 : // "anglecorr" - switch for the angular correction
589 : //------------------------------------------------------------------
590 202868 : Double_t &fP2=fP[2];
591 202868 : Double_t &fP3=fP[3];
592 202868 : Double_t &fP4=fP[4];
593 :
594 202868 : Double_t &fC22=fC[5];
595 202868 : Double_t &fC33=fC[9];
596 202868 : Double_t &fC43=fC[13];
597 202868 : Double_t &fC44=fC[14];
598 :
599 : //Apply angle correction, if requested
600 202868 : if(anglecorr) {
601 19360 : Double_t angle=TMath::Sqrt((1.+ fP3*fP3)/((1-fP2)*(1.+fP2)));
602 19360 : xOverX0 *=angle;
603 19360 : xTimesRho *=angle;
604 19360 : }
605 :
606 202868 : Double_t p=GetP();
607 202868 : if (mass<0) p += p; // q=2 particle
608 202868 : Double_t p2=p*p;
609 202868 : Double_t beta2=p2/(p2 + mass*mass);
610 :
611 : //Calculating the multiple scattering corrections******************
612 : Double_t cC22 = 0.;
613 : Double_t cC33 = 0.;
614 : Double_t cC43 = 0.;
615 : Double_t cC44 = 0.;
616 202868 : if (xOverX0 != 0) {
617 : //Double_t theta2=1.0259e-6*14*14/28/(beta2*p2)*TMath::Abs(d)*9.36*2.33;
618 200892 : Double_t theta2=0.0136*0.0136/(beta2*p2)*TMath::Abs(xOverX0);
619 200892 : if (GetUseLogTermMS()) {
620 0 : double lt = 1+0.038*TMath::Log(TMath::Abs(xOverX0));
621 0 : if (lt>0) theta2 *= lt*lt;
622 0 : }
623 200892 : if (mass<0) theta2 *= 4; // q=2 particle
624 200893 : if(theta2>TMath::Pi()*TMath::Pi()) return kFALSE;
625 200891 : cC22 = theta2*((1.-fP2)*(1.+fP2))*(1. + fP3*fP3);
626 200891 : cC33 = theta2*(1. + fP3*fP3)*(1. + fP3*fP3);
627 200891 : cC43 = theta2*fP3*fP4*(1. + fP3*fP3);
628 200891 : cC44 = theta2*fP3*fP4*fP3*fP4;
629 200891 : }
630 :
631 : //Calculating the energy loss corrections************************
632 : Double_t cP4=1.;
633 202867 : if ((xTimesRho != 0.) && (beta2 < 1.)) {
634 200891 : Double_t dE=dEdx*xTimesRho;
635 200891 : Double_t e=TMath::Sqrt(p2 + mass*mass);
636 200893 : if ( TMath::Abs(dE) > 0.3*e ) return kFALSE; //30% energy loss is too much!
637 200895 : if ( (1.+ dE/p2*(dE + 2*e)) < 0. ) return kFALSE;
638 200883 : cP4 = 1./TMath::Sqrt(1.+ dE/p2*(dE + 2*e)); //A precise formula by Ruben !
639 200883 : if (TMath::Abs(fP4*cP4)>100.) return kFALSE; //Do not track below 10 MeV/c
640 :
641 :
642 : // Approximate energy loss fluctuation (M.Ivanov)
643 : const Double_t knst=0.07; // To be tuned.
644 200883 : Double_t sigmadE=knst*TMath::Sqrt(TMath::Abs(dE));
645 200883 : cC44 += ((sigmadE*e/p2*fP4)*(sigmadE*e/p2*fP4));
646 :
647 200883 : }
648 :
649 : //Applying the corrections*****************************
650 202859 : fC22 += cC22;
651 202859 : fC33 += cC33;
652 202859 : fC43 += cC43;
653 202859 : fC44 += cC44;
654 202859 : fP4 *= cP4;
655 :
656 202859 : CheckCovariance();
657 :
658 202859 : return kTRUE;
659 202868 : }
660 :
661 : Bool_t AliExternalTrackParam::CorrectForMeanMaterial
662 : (Double_t xOverX0, Double_t xTimesRho, Double_t mass,
663 : Bool_t anglecorr,
664 : Double_t (*Bethe)(Double_t)) {
665 : //------------------------------------------------------------------
666 : // This function corrects the track parameters for the crossed material.
667 : // "xOverX0" - X/X0, the thickness in units of the radiation length.
668 : // "xTimesRho" - is the product length*density (g/cm^2).
669 : // It should be passed as negative when propagating tracks
670 : // from the intreaction point to the outside of the central barrel.
671 : // "mass" - the mass of this particle (GeV/c^2). mass<0 means charge=2
672 : // "anglecorr" - switch for the angular correction
673 : // "Bethe" - function calculating the energy loss (GeV/(g/cm^2))
674 : //------------------------------------------------------------------
675 :
676 202868 : Double_t bg=GetP()/mass;
677 202868 : if (mass<0) {
678 0 : if (mass<-990) {
679 0 : AliDebug(2,Form("Mass %f corresponds to unknown PID particle",mass));
680 0 : return kFALSE;
681 : }
682 0 : bg = -2*bg;
683 0 : }
684 202868 : Double_t dEdx=Bethe(bg);
685 202868 : if (mass<0) dEdx *= 4;
686 :
687 202868 : return CorrectForMeanMaterialdEdx(xOverX0,xTimesRho,mass,dEdx,anglecorr);
688 202868 : }
689 :
690 : Bool_t AliExternalTrackParam::CorrectForMeanMaterialZA
691 : (Double_t xOverX0, Double_t xTimesRho, Double_t mass,
692 : Double_t zOverA,
693 : Double_t density,
694 : Double_t exEnergy,
695 : Double_t jp1,
696 : Double_t jp2,
697 : Bool_t anglecorr) {
698 : //------------------------------------------------------------------
699 : // This function corrects the track parameters for the crossed material
700 : // using the full Geant-like Bethe-Bloch formula parameterization
701 : // "xOverX0" - X/X0, the thickness in units of the radiation length.
702 : // "xTimesRho" - is the product length*density (g/cm^2).
703 : // It should be passed as negative when propagating tracks
704 : // from the intreaction point to the outside of the central barrel.
705 : // "mass" - the mass of this particle (GeV/c^2). mass<0 means charge=2 particle
706 : // "density" - mean density (g/cm^3)
707 : // "zOverA" - mean Z/A
708 : // "exEnergy" - mean exitation energy (GeV)
709 : // "jp1" - density effect first junction point
710 : // "jp2" - density effect second junction point
711 : // "anglecorr" - switch for the angular correction
712 : //
713 : // The default values of the parameters are for silicon
714 : //
715 : //------------------------------------------------------------------
716 :
717 0 : Double_t bg=GetP()/mass;
718 0 : if (mass<0) {
719 0 : if (mass<-990) {
720 0 : AliDebug(2,Form("Mass %f corresponds to unknown PID particle",mass));
721 0 : return kFALSE;
722 : }
723 0 : bg = -2*bg;
724 0 : }
725 0 : Double_t dEdx=BetheBlochGeant(bg,density,jp1,jp2,exEnergy,zOverA);
726 :
727 0 : if (mass<0) dEdx *= 4;
728 0 : return CorrectForMeanMaterialdEdx(xOverX0,xTimesRho,mass,dEdx,anglecorr);
729 0 : }
730 :
731 :
732 :
733 : Bool_t AliExternalTrackParam::CorrectForMaterial
734 : (Double_t d, Double_t x0, Double_t mass, Double_t (*Bethe)(Double_t)) {
735 : //------------------------------------------------------------------
736 : // Deprecated function !
737 : // Better use CorrectForMeanMaterial instead of it.
738 : //
739 : // This function corrects the track parameters for the crossed material
740 : // "d" - the thickness (fraction of the radiation length)
741 : // It should be passed as negative when propagating tracks
742 : // from the intreaction point to the outside of the central barrel.
743 : // "x0" - the radiation length (g/cm^2)
744 : // "mass" - the mass of this particle (GeV/c^2)
745 : //------------------------------------------------------------------
746 :
747 0 : return CorrectForMeanMaterial(d,x0*d,mass,kTRUE,Bethe);
748 :
749 : }
750 :
751 : Double_t AliExternalTrackParam::BetheBlochAleph(Double_t bg,
752 : Double_t kp1,
753 : Double_t kp2,
754 : Double_t kp3,
755 : Double_t kp4,
756 : Double_t kp5) {
757 : //
758 : // This is the empirical ALEPH parameterization of the Bethe-Bloch formula.
759 : // It is normalized to 1 at the minimum.
760 : //
761 : // bg - beta*gamma
762 : //
763 : // The default values for the kp* parameters are for ALICE TPC.
764 : // The returned value is in MIP units
765 : //
766 :
767 1654632 : Double_t beta = bg/TMath::Sqrt(1.+ bg*bg);
768 :
769 827316 : Double_t aa = TMath::Power(beta,kp4);
770 827316 : Double_t bb = TMath::Power(1./bg,kp5);
771 :
772 827316 : bb=TMath::Log(kp3+bb);
773 :
774 827316 : return (kp2-aa-bb)*kp1/aa;
775 : }
776 :
777 : Double_t AliExternalTrackParam::BetheBlochGeant(Double_t bg,
778 : Double_t kp0,
779 : Double_t kp1,
780 : Double_t kp2,
781 : Double_t kp3,
782 : Double_t kp4) {
783 : //
784 : // This is the parameterization of the Bethe-Bloch formula inspired by Geant.
785 : //
786 : // bg - beta*gamma
787 : // kp0 - density [g/cm^3]
788 : // kp1 - density effect first junction point
789 : // kp2 - density effect second junction point
790 : // kp3 - mean excitation energy [GeV]
791 : // kp4 - mean Z/A
792 : //
793 : // The default values for the kp* parameters are for silicon.
794 : // The returned value is in [GeV/(g/cm^2)].
795 : //
796 :
797 : const Double_t mK = 0.307075e-3; // [GeV*cm^2/g]
798 : const Double_t me = 0.511e-3; // [GeV/c^2]
799 : const Double_t rho = kp0;
800 406304 : const Double_t x0 = kp1*2.303;
801 203152 : const Double_t x1 = kp2*2.303;
802 : const Double_t mI = kp3;
803 : const Double_t mZA = kp4;
804 203152 : const Double_t bg2 = bg*bg;
805 203152 : const Double_t maxT= 2*me*bg2; // neglecting the electron mass
806 :
807 : //*** Density effect
808 : Double_t d2=0.;
809 203152 : const Double_t x=TMath::Log(bg);
810 203152 : const Double_t lhwI=TMath::Log(28.816*1e-9*TMath::Sqrt(rho*mZA)/mI);
811 203152 : if (x > x1) {
812 829 : d2 = lhwI + x - 0.5;
813 203152 : } else if (x > x0) {
814 91217 : const Double_t r=(x1-x)/(x1-x0);
815 91217 : d2 = lhwI + x - 0.5 + (0.5 - lhwI - x0)*r*r*r;
816 91217 : }
817 :
818 406304 : return mK*mZA*(1+bg2)/bg2*
819 203152 : (0.5*TMath::Log(2*me*bg2*maxT/(mI*mI)) - bg2/(1+bg2) - d2);
820 : }
821 :
822 : Double_t AliExternalTrackParam::BetheBlochSolid(Double_t bg) {
823 : //------------------------------------------------------------------
824 : // This is an approximation of the Bethe-Bloch formula,
825 : // reasonable for solid materials.
826 : // All the parameters are, in fact, for Si.
827 : // The returned value is in [GeV/(g/cm^2)]
828 : //------------------------------------------------------------------
829 :
830 171368 : return BetheBlochGeant(bg);
831 : }
832 :
833 : Double_t AliExternalTrackParam::BetheBlochGas(Double_t bg) {
834 : //------------------------------------------------------------------
835 : // This is an approximation of the Bethe-Bloch formula,
836 : // reasonable for gas materials.
837 : // All the parameters are, in fact, for Ne.
838 : // The returned value is in [GeV/(g/cm^2)]
839 : //------------------------------------------------------------------
840 :
841 : const Double_t rho = 0.9e-3;
842 : const Double_t x0 = 2.;
843 : const Double_t x1 = 4.;
844 : const Double_t mI = 140.e-9;
845 : const Double_t mZA = 0.49555;
846 :
847 234368 : return BetheBlochGeant(bg,rho,x0,x1,mI,mZA);
848 : }
849 :
850 : Bool_t AliExternalTrackParam::Rotate(Double_t alpha) {
851 : //------------------------------------------------------------------
852 : // Transform this track to the local coord. system rotated
853 : // by angle "alpha" (rad) with respect to the global coord. system.
854 : //------------------------------------------------------------------
855 212690 : if (TMath::Abs(fP[2]) >= kAlmost1) {
856 0 : AliError(Form("Precondition is not satisfied: |sin(phi)|>1 ! %f",fP[2]));
857 0 : return kFALSE;
858 : }
859 :
860 106425 : if (alpha < -TMath::Pi()) alpha += 2*TMath::Pi();
861 114165 : else if (alpha >= TMath::Pi()) alpha -= 2*TMath::Pi();
862 :
863 106345 : Double_t &fP0=fP[0];
864 : Double_t &fP2=fP[2];
865 106345 : Double_t &fC00=fC[0];
866 106345 : Double_t &fC10=fC[1];
867 106345 : Double_t &fC20=fC[3];
868 106345 : Double_t &fC21=fC[4];
869 106345 : Double_t &fC22=fC[5];
870 106345 : Double_t &fC30=fC[6];
871 106345 : Double_t &fC32=fC[8];
872 106345 : Double_t &fC40=fC[10];
873 106345 : Double_t &fC42=fC[12];
874 :
875 106345 : Double_t x=fX;
876 106345 : Double_t ca=TMath::Cos(alpha-fAlpha), sa=TMath::Sin(alpha-fAlpha);
877 106345 : Double_t sf=fP2, cf=TMath::Sqrt((1.- fP2)*(1.+fP2)); // Improve precision
878 : // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle
879 : // direction in local frame is along the X axis
880 106345 : if ((cf*ca+sf*sa)<0) {
881 480 : AliDebug(1,Form("Rotation failed: local cos(phi) would become %.2f",cf*ca+sf*sa));
882 160 : return kFALSE;
883 : }
884 : //
885 106185 : Double_t tmp=sf*ca - cf*sa;
886 :
887 106185 : if (TMath::Abs(tmp) >= kAlmost1) {
888 0 : if (TMath::Abs(tmp) > 1.+ Double_t(FLT_EPSILON))
889 0 : AliWarning(Form("Rotation failed ! %.10e",tmp));
890 0 : return kFALSE;
891 : }
892 106185 : fAlpha = alpha;
893 106185 : fX = x*ca + fP0*sa;
894 106185 : fP0= -x*sa + fP0*ca;
895 106185 : fP2= tmp;
896 :
897 106185 : if (TMath::Abs(cf)<kAlmost0) {
898 0 : AliError(Form("Too small cosine value %f",cf));
899 : cf = kAlmost0;
900 0 : }
901 :
902 106185 : Double_t rr=(ca+sf/cf*sa);
903 :
904 106185 : fC00 *= (ca*ca);
905 106185 : fC10 *= ca;
906 106185 : fC20 *= ca*rr;
907 106185 : fC21 *= rr;
908 106185 : fC22 *= rr*rr;
909 106185 : fC30 *= ca;
910 106185 : fC32 *= rr;
911 106185 : fC40 *= ca;
912 106185 : fC42 *= rr;
913 :
914 106185 : CheckCovariance();
915 :
916 : return kTRUE;
917 106345 : }
918 :
919 : //______________________________________________________
920 : Bool_t AliExternalTrackParam::RotateParamOnly(Double_t alpha)
921 : {
922 : // rotate to new frame, ignore covariance
923 168 : if (TMath::Abs(fP[2]) >= kAlmost1) {
924 0 : AliError(Form("Precondition is not satisfied: |sin(phi)|>1 ! %f",fP[2]));
925 0 : return kFALSE;
926 : }
927 : //
928 84 : if (alpha < -TMath::Pi()) alpha += 2*TMath::Pi();
929 168 : else if (alpha >= TMath::Pi()) alpha -= 2*TMath::Pi();
930 : //
931 84 : Double_t &fP0=fP[0];
932 : Double_t &fP2=fP[2];
933 : //
934 84 : Double_t x=fX;
935 84 : Double_t ca=TMath::Cos(alpha-fAlpha), sa=TMath::Sin(alpha-fAlpha);
936 84 : Double_t sf=fP2, cf=TMath::Sqrt((1.- fP2)*(1.+fP2)); // Improve precision
937 : // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle
938 : // direction in local frame is along the X axis
939 84 : if ((cf*ca+sf*sa)<0) {
940 180 : AliDebug(1,Form("Rotation failed: local cos(phi) would become %.2f",cf*ca+sf*sa));
941 60 : return kFALSE;
942 : }
943 : //
944 24 : Double_t tmp=sf*ca - cf*sa;
945 :
946 24 : if (TMath::Abs(tmp) >= kAlmost1) {
947 0 : if (TMath::Abs(tmp) > 1.+ Double_t(FLT_EPSILON))
948 0 : AliWarning(Form("Rotation failed ! %.10e",tmp));
949 0 : return kFALSE;
950 : }
951 24 : fAlpha = alpha;
952 24 : fX = x*ca + fP0*sa;
953 24 : fP0= -x*sa + fP0*ca;
954 24 : fP2= tmp;
955 24 : return kTRUE;
956 84 : }
957 :
958 : Bool_t AliExternalTrackParam::Invert() {
959 : //------------------------------------------------------------------
960 : // Transform this track to the local coord. system rotated by 180 deg.
961 : //------------------------------------------------------------------
962 0 : fX = -fX;
963 0 : fAlpha += TMath::Pi();
964 0 : while (fAlpha < -TMath::Pi()) fAlpha += 2*TMath::Pi();
965 0 : while (fAlpha >= TMath::Pi()) fAlpha -= 2*TMath::Pi();
966 : //
967 0 : fP[0] = -fP[0];
968 : //fP[2] = -fP[2];
969 0 : fP[3] = -fP[3];
970 0 : fP[4] = -fP[4];
971 : //
972 0 : fC[1] = -fC[1]; // since the fP1 and fP2 are not inverted, their covariances with others change sign
973 0 : fC[3] = -fC[3];
974 0 : fC[7] = -fC[7];
975 0 : fC[8] = -fC[8];
976 0 : fC[11] = -fC[11];
977 0 : fC[12] = -fC[12];
978 : //
979 0 : return kTRUE;
980 : }
981 :
982 : Bool_t AliExternalTrackParam::PropagateTo(Double_t xk, Double_t b) {
983 : //----------------------------------------------------------------
984 : // Propagate this track to the plane X=xk (cm) in the field "b" (kG)
985 : //----------------------------------------------------------------
986 41482 : Double_t dx=xk-fX;
987 20867 : if (TMath::Abs(dx)<=kAlmost0) return kTRUE;
988 :
989 20615 : Double_t crv=GetC(b);
990 20615 : if (TMath::Abs(b) < kAlmost0Field) crv=0.;
991 :
992 20615 : Double_t x2r = crv*dx;
993 20615 : Double_t f1=fP[2], f2=f1 + x2r;
994 20615 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
995 20616 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
996 20614 : if (TMath::Abs(fP[4])< kAlmost0) return kFALSE;
997 :
998 20614 : Double_t &fP0=fP[0], &fP1=fP[1], &fP2=fP[2], &fP3=fP[3], &fP4=fP[4];
999 : Double_t
1000 20614 : &fC00=fC[0],
1001 20614 : &fC10=fC[1], &fC11=fC[2],
1002 20614 : &fC20=fC[3], &fC21=fC[4], &fC22=fC[5],
1003 20614 : &fC30=fC[6], &fC31=fC[7], &fC32=fC[8], &fC33=fC[9],
1004 20614 : &fC40=fC[10], &fC41=fC[11], &fC42=fC[12], &fC43=fC[13], &fC44=fC[14];
1005 :
1006 20614 : Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
1007 20614 : if (TMath::Abs(r1)<kAlmost0) return kFALSE;
1008 20614 : if (TMath::Abs(r2)<kAlmost0) return kFALSE;
1009 :
1010 20614 : fX=xk;
1011 20614 : double dy2dx = (f1+f2)/(r1+r2);
1012 20614 : fP0 += dx*dy2dx;
1013 20614 : fP2 += x2r;
1014 41134 : if (TMath::Abs(x2r)<0.05) fP1 += dx*(r2 + f2*dy2dx)*fP3; // Many thanks to P.Hristov !
1015 : else {
1016 : // for small dx/R the linear apporximation of the arc by the segment is OK,
1017 : // but at large dx/R the error is very large and leads to incorrect Z propagation
1018 : // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
1019 : // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
1020 : // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
1021 : // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
1022 : // fP1 += rot/crv*fP3;
1023 : //
1024 94 : double rot = TMath::ASin(r1*f2 - r2*f1); // more economic version from Yura.
1025 98 : if (f1*f1+f2*f2>1 && f1*f2<0) { // special cases of large rotations or large abs angles
1026 0 : if (f2>0) rot = TMath::Pi() - rot; //
1027 0 : else rot = -TMath::Pi() - rot;
1028 : }
1029 94 : fP1 += fP3/crv*rot;
1030 : }
1031 :
1032 : //f = F - 1
1033 : /*
1034 : Double_t f02= dx/(r1*r1*r1); Double_t cc=crv/fP4;
1035 : Double_t f04=0.5*dx*dx/(r1*r1*r1); f04*=cc;
1036 : Double_t f12= dx*fP3*f1/(r1*r1*r1);
1037 : Double_t f14=0.5*dx*dx*fP3*f1/(r1*r1*r1); f14*=cc;
1038 : Double_t f13= dx/r1;
1039 : Double_t f24= dx; f24*=cc;
1040 : */
1041 20614 : Double_t rinv = 1./r1;
1042 20614 : Double_t r3inv = rinv*rinv*rinv;
1043 20614 : Double_t f24= x2r/fP4;
1044 20614 : Double_t f02= dx*r3inv;
1045 20614 : Double_t f04=0.5*f24*f02;
1046 20614 : Double_t f12= f02*fP3*f1;
1047 20614 : Double_t f14=0.5*f24*f02*fP3*f1;
1048 20614 : Double_t f13= dx*rinv;
1049 :
1050 : //b = C*ft
1051 20614 : Double_t b00=f02*fC20 + f04*fC40, b01=f12*fC20 + f14*fC40 + f13*fC30;
1052 20614 : Double_t b02=f24*fC40;
1053 20614 : Double_t b10=f02*fC21 + f04*fC41, b11=f12*fC21 + f14*fC41 + f13*fC31;
1054 20614 : Double_t b12=f24*fC41;
1055 20614 : Double_t b20=f02*fC22 + f04*fC42, b21=f12*fC22 + f14*fC42 + f13*fC32;
1056 20614 : Double_t b22=f24*fC42;
1057 20614 : Double_t b40=f02*fC42 + f04*fC44, b41=f12*fC42 + f14*fC44 + f13*fC43;
1058 20614 : Double_t b42=f24*fC44;
1059 20614 : Double_t b30=f02*fC32 + f04*fC43, b31=f12*fC32 + f14*fC43 + f13*fC33;
1060 20614 : Double_t b32=f24*fC43;
1061 :
1062 : //a = f*b = f*C*ft
1063 20614 : Double_t a00=f02*b20+f04*b40,a01=f02*b21+f04*b41,a02=f02*b22+f04*b42;
1064 20614 : Double_t a11=f12*b21+f14*b41+f13*b31,a12=f12*b22+f14*b42+f13*b32;
1065 20614 : Double_t a22=f24*b42;
1066 :
1067 : //F*C*Ft = C + (b + bt + a)
1068 20614 : fC00 += b00 + b00 + a00;
1069 20614 : fC10 += b10 + b01 + a01;
1070 20614 : fC20 += b20 + b02 + a02;
1071 20614 : fC30 += b30;
1072 20614 : fC40 += b40;
1073 20614 : fC11 += b11 + b11 + a11;
1074 20614 : fC21 += b21 + b12 + a12;
1075 20614 : fC31 += b31;
1076 20614 : fC41 += b41;
1077 20614 : fC22 += b22 + b22 + a22;
1078 20614 : fC32 += b32;
1079 20614 : fC42 += b42;
1080 :
1081 20614 : CheckCovariance();
1082 :
1083 : return kTRUE;
1084 20741 : }
1085 :
1086 : Bool_t AliExternalTrackParam::PropagateParamOnlyTo(Double_t xk, Double_t b) {
1087 : //----------------------------------------------------------------
1088 : // Propagate this track to the plane X=xk (cm) in the field "b" (kG)
1089 : // Only parameters are propagated, not the matrix. To be used for small
1090 : // distances only (<mm, i.e. misalignment)
1091 : //----------------------------------------------------------------
1092 0 : Double_t dx=xk-fX;
1093 0 : if (TMath::Abs(dx)<=kAlmost0) return kTRUE;
1094 :
1095 0 : Double_t crv=GetC(b);
1096 0 : if (TMath::Abs(b) < kAlmost0Field) crv=0.;
1097 :
1098 0 : Double_t x2r = crv*dx;
1099 0 : Double_t f1=fP[2], f2=f1 + x2r;
1100 0 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
1101 0 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
1102 0 : if (TMath::Abs(fP[4])< kAlmost0) return kFALSE;
1103 :
1104 0 : Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
1105 0 : if (TMath::Abs(r1)<kAlmost0) return kFALSE;
1106 0 : if (TMath::Abs(r2)<kAlmost0) return kFALSE;
1107 :
1108 0 : fX=xk;
1109 0 : double dy2dx = (f1+f2)/(r1+r2);
1110 0 : fP[0] += dx*dy2dx;
1111 0 : fP[2] += x2r;
1112 0 : if (TMath::Abs(x2r)<0.05) fP[1] += dx*(r2 + f2*dy2dx)*fP[3]; // Many thanks to P.Hristov !
1113 : else {
1114 : // for small dx/R the linear apporximation of the arc by the segment is OK,
1115 : // but at large dx/R the error is very large and leads to incorrect Z propagation
1116 : // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
1117 : // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
1118 : // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
1119 : // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
1120 : // fP1 += rot/crv*fP3;
1121 : //
1122 0 : double rot = TMath::ASin(r1*f2 - r2*f1); // more economic version from Yura.
1123 0 : if (f1*f1+f2*f2>1 && f1*f2<0) { // special cases of large rotations or large abs angles
1124 0 : if (f2>0) rot = TMath::Pi() - rot; //
1125 0 : else rot = -TMath::Pi() - rot;
1126 : }
1127 0 : fP[1] += fP[3]/crv*rot;
1128 : }
1129 : return kTRUE;
1130 0 : }
1131 :
1132 : Bool_t
1133 : AliExternalTrackParam::Propagate(Double_t alpha, Double_t x, Double_t b) {
1134 : //------------------------------------------------------------------
1135 : // Transform this track to the local coord. system rotated
1136 : // by angle "alpha" (rad) with respect to the global coord. system,
1137 : // and propagate this track to the plane X=xk (cm) in the field "b" (kG)
1138 : //------------------------------------------------------------------
1139 :
1140 : //Save the parameters
1141 880 : Double_t as=fAlpha;
1142 440 : Double_t xs=fX;
1143 440 : Double_t ps[5], cs[15];
1144 5280 : for (Int_t i=0; i<5; i++) ps[i]=fP[i];
1145 14080 : for (Int_t i=0; i<15; i++) cs[i]=fC[i];
1146 :
1147 440 : if (Rotate(alpha))
1148 880 : if (PropagateTo(x,b)) return kTRUE;
1149 :
1150 : //Restore the parameters, if the operation failed
1151 0 : fAlpha=as;
1152 0 : fX=xs;
1153 0 : for (Int_t i=0; i<5; i++) fP[i]=ps[i];
1154 0 : for (Int_t i=0; i<15; i++) fC[i]=cs[i];
1155 0 : return kFALSE;
1156 440 : }
1157 :
1158 : Bool_t AliExternalTrackParam::PropagateBxByBz
1159 : (Double_t alpha, Double_t x, Double_t b[3]) {
1160 : //------------------------------------------------------------------
1161 : // Transform this track to the local coord. system rotated
1162 : // by angle "alpha" (rad) with respect to the global coord. system,
1163 : // and propagate this track to the plane X=xk (cm),
1164 : // taking into account all three components of the B field, "b[3]" (kG)
1165 : //------------------------------------------------------------------
1166 :
1167 : //Save the parameters
1168 193322 : Double_t as=fAlpha;
1169 96661 : Double_t xs=fX;
1170 96661 : Double_t ps[5], cs[15];
1171 1159932 : for (Int_t i=0; i<5; i++) ps[i]=fP[i];
1172 3093152 : for (Int_t i=0; i<15; i++) cs[i]=fC[i];
1173 :
1174 96661 : if (Rotate(alpha))
1175 193312 : if (PropagateToBxByBz(x,b)) return kTRUE;
1176 :
1177 : //Restore the parameters, if the operation failed
1178 6 : fAlpha=as;
1179 6 : fX=xs;
1180 72 : for (Int_t i=0; i<5; i++) fP[i]=ps[i];
1181 192 : for (Int_t i=0; i<15; i++) fC[i]=cs[i];
1182 6 : return kFALSE;
1183 96661 : }
1184 :
1185 :
1186 : void AliExternalTrackParam::Propagate(Double_t len, Double_t x[3],
1187 : Double_t p[3], Double_t bz) const {
1188 : //+++++++++++++++++++++++++++++++++++++++++
1189 : // Origin: K. Shileev (Kirill.Shileev@cern.ch)
1190 : // Extrapolate track along simple helix in magnetic field
1191 : // Arguments: len -distance alogn helix, [cm]
1192 : // bz - mag field, [kGaus]
1193 : // Returns: x and p contain extrapolated positon and momentum
1194 : // The momentum returned for straight-line tracks is meaningless !
1195 : //+++++++++++++++++++++++++++++++++++++++++
1196 0 : GetXYZ(x);
1197 :
1198 0 : if (OneOverPt() < kAlmost0 || TMath::Abs(bz) < kAlmost0Field || GetC(bz) < kAlmost0){ //straight-line tracks
1199 0 : Double_t unit[3]; GetDirection(unit);
1200 0 : x[0]+=unit[0]*len;
1201 0 : x[1]+=unit[1]*len;
1202 0 : x[2]+=unit[2]*len;
1203 :
1204 0 : p[0]=unit[0]/kAlmost0;
1205 0 : p[1]=unit[1]/kAlmost0;
1206 0 : p[2]=unit[2]/kAlmost0;
1207 0 : } else {
1208 0 : GetPxPyPz(p);
1209 0 : Double_t pp=GetP();
1210 0 : Double_t a = -kB2C*bz*GetSign();
1211 0 : Double_t rho = a/pp;
1212 0 : x[0] += p[0]*TMath::Sin(rho*len)/a - p[1]*(1-TMath::Cos(rho*len))/a;
1213 0 : x[1] += p[1]*TMath::Sin(rho*len)/a + p[0]*(1-TMath::Cos(rho*len))/a;
1214 0 : x[2] += p[2]*len/pp;
1215 :
1216 0 : Double_t p0=p[0];
1217 0 : p[0] = p0 *TMath::Cos(rho*len) - p[1]*TMath::Sin(rho*len);
1218 0 : p[1] = p[1]*TMath::Cos(rho*len) + p0 *TMath::Sin(rho*len);
1219 : }
1220 0 : }
1221 :
1222 : Bool_t AliExternalTrackParam::Intersect(Double_t pnt[3], Double_t norm[3],
1223 : Double_t bz) const {
1224 : //+++++++++++++++++++++++++++++++++++++++++
1225 : // Origin: K. Shileev (Kirill.Shileev@cern.ch)
1226 : // Finds point of intersection (if exists) of the helix with the plane.
1227 : // Stores result in fX and fP.
1228 : // Arguments: planePoint,planeNorm - the plane defined by any plane's point
1229 : // and vector, normal to the plane
1230 : // Returns: kTrue if helix intersects the plane, kFALSE otherwise.
1231 : //+++++++++++++++++++++++++++++++++++++++++
1232 0 : Double_t x0[3]; GetXYZ(x0); //get track position in MARS
1233 :
1234 : //estimates initial helix length up to plane
1235 : Double_t s=
1236 0 : (pnt[0]-x0[0])*norm[0] + (pnt[1]-x0[1])*norm[1] + (pnt[2]-x0[2])*norm[2];
1237 : Double_t dist=99999,distPrev=dist;
1238 0 : Double_t x[3],p[3];
1239 0 : while(TMath::Abs(dist)>0.00001){
1240 : //calculates helix at the distance s from x0 ALONG the helix
1241 0 : Propagate(s,x,p,bz);
1242 :
1243 : //distance between current helix position and plane
1244 0 : dist=(x[0]-pnt[0])*norm[0]+(x[1]-pnt[1])*norm[1]+(x[2]-pnt[2])*norm[2];
1245 :
1246 0 : if(TMath::Abs(dist) >= TMath::Abs(distPrev)) {return kFALSE;}
1247 : distPrev=dist;
1248 0 : s-=dist;
1249 : }
1250 : //on exit pnt is intersection point,norm is track vector at that point,
1251 : //all in MARS
1252 0 : for (Int_t i=0; i<3; i++) {pnt[i]=x[i]; norm[i]=p[i];}
1253 0 : return kTRUE;
1254 0 : }
1255 :
1256 : Double_t
1257 : AliExternalTrackParam::GetPredictedChi2(const Double_t p[2],const Double_t cov[3]) const {
1258 : //----------------------------------------------------------------
1259 : // Estimate the chi2 of the space point "p" with the cov. matrix "cov"
1260 : //----------------------------------------------------------------
1261 229880 : Double_t sdd = fC[0] + cov[0];
1262 114940 : Double_t sdz = fC[1] + cov[1];
1263 114940 : Double_t szz = fC[2] + cov[2];
1264 114940 : Double_t det = sdd*szz - sdz*sdz;
1265 :
1266 114940 : if (TMath::Abs(det) < kAlmost0) return kVeryBig;
1267 :
1268 114940 : Double_t d = fP[0] - p[0];
1269 114940 : Double_t z = fP[1] - p[1];
1270 :
1271 114940 : return (d*szz*d - 2*d*sdz*z + z*sdd*z)/det;
1272 114940 : }
1273 :
1274 : Double_t AliExternalTrackParam::
1275 : GetPredictedChi2(const Double_t p[3],const Double_t covyz[3],const Double_t covxyz[3]) const {
1276 : //----------------------------------------------------------------
1277 : // Estimate the chi2 of the 3D space point "p" and
1278 : // the full covariance matrix "covyz" and "covxyz"
1279 : //
1280 : // Cov(x,x) ... : covxyz[0]
1281 : // Cov(y,x) ... : covxyz[1] covyz[0]
1282 : // Cov(z,x) ... : covxyz[2] covyz[1] covyz[2]
1283 : //----------------------------------------------------------------
1284 :
1285 0 : Double_t res[3] = {
1286 0 : GetX() - p[0],
1287 0 : GetY() - p[1],
1288 0 : GetZ() - p[2]
1289 : };
1290 :
1291 0 : Double_t f=GetSnp();
1292 0 : if (TMath::Abs(f) >= kAlmost1) return kVeryBig;
1293 0 : Double_t r=TMath::Sqrt((1.-f)*(1.+f));
1294 0 : Double_t a=f/r, b=GetTgl()/r;
1295 :
1296 : Double_t s2=333.*333.; //something reasonably big (cm^2)
1297 :
1298 0 : TMatrixDSym v(3);
1299 0 : v(0,0)= s2; v(0,1)= a*s2; v(0,2)= b*s2;;
1300 0 : v(1,0)=a*s2; v(1,1)=a*a*s2 + GetSigmaY2(); v(1,2)=a*b*s2 + GetSigmaZY();
1301 0 : v(2,0)=b*s2; v(2,1)=a*b*s2 + GetSigmaZY(); v(2,2)=b*b*s2 + GetSigmaZ2();
1302 :
1303 0 : v(0,0)+=covxyz[0]; v(0,1)+=covxyz[1]; v(0,2)+=covxyz[2];
1304 0 : v(1,0)+=covxyz[1]; v(1,1)+=covyz[0]; v(1,2)+=covyz[1];
1305 0 : v(2,0)+=covxyz[2]; v(2,1)+=covyz[1]; v(2,2)+=covyz[2];
1306 :
1307 0 : v.Invert();
1308 0 : if (!v.IsValid()) return kVeryBig;
1309 :
1310 : Double_t chi2=0.;
1311 0 : for (Int_t i = 0; i < 3; i++)
1312 0 : for (Int_t j = 0; j < 3; j++) chi2 += res[i]*res[j]*v(i,j);
1313 :
1314 : return chi2;
1315 0 : }
1316 :
1317 : Double_t AliExternalTrackParam::
1318 : GetPredictedChi2(const AliExternalTrackParam *t) const {
1319 : //----------------------------------------------------------------
1320 : // Estimate the chi2 (5 dof) of this track with respect to the track
1321 : // given by the argument.
1322 : // The two tracks must be in the same reference system
1323 : // and estimated at the same reference plane.
1324 : //----------------------------------------------------------------
1325 :
1326 544 : if (TMath::Abs(t->GetAlpha()-GetAlpha()) > FLT_EPSILON) {
1327 0 : AliError("The reference systems of the tracks differ !");
1328 0 : return kVeryBig;
1329 : }
1330 272 : if (TMath::Abs(t->GetX()-GetX()) > FLT_EPSILON) {
1331 0 : AliError("The reference of the tracks planes differ !");
1332 0 : return kVeryBig;
1333 : }
1334 :
1335 272 : TMatrixDSym c(5);
1336 544 : c(0,0)=GetSigmaY2();
1337 816 : c(1,0)=GetSigmaZY(); c(1,1)=GetSigmaZ2();
1338 1360 : c(2,0)=GetSigmaSnpY(); c(2,1)=GetSigmaSnpZ(); c(2,2)=GetSigmaSnp2();
1339 1360 : c(3,0)=GetSigmaTglY(); c(3,1)=GetSigmaTglZ(); c(3,2)=GetSigmaTglSnp(); c(3,3)=GetSigmaTgl2();
1340 1632 : c(4,0)=GetSigma1PtY(); c(4,1)=GetSigma1PtZ(); c(4,2)=GetSigma1PtSnp(); c(4,3)=GetSigma1PtTgl(); c(4,4)=GetSigma1Pt2();
1341 :
1342 544 : c(0,0)+=t->GetSigmaY2();
1343 816 : c(1,0)+=t->GetSigmaZY(); c(1,1)+=t->GetSigmaZ2();
1344 1360 : c(2,0)+=t->GetSigmaSnpY();c(2,1)+=t->GetSigmaSnpZ();c(2,2)+=t->GetSigmaSnp2();
1345 1360 : c(3,0)+=t->GetSigmaTglY();c(3,1)+=t->GetSigmaTglZ();c(3,2)+=t->GetSigmaTglSnp();c(3,3)+=t->GetSigmaTgl2();
1346 1632 : c(4,0)+=t->GetSigma1PtY();c(4,1)+=t->GetSigma1PtZ();c(4,2)+=t->GetSigma1PtSnp();c(4,3)+=t->GetSigma1PtTgl();c(4,4)+=t->GetSigma1Pt2();
1347 816 : c(0,1)=c(1,0);
1348 1360 : c(0,2)=c(2,0); c(1,2)=c(2,1);
1349 1904 : c(0,3)=c(3,0); c(1,3)=c(3,1); c(2,3)=c(3,2);
1350 2448 : c(0,4)=c(4,0); c(1,4)=c(4,1); c(2,4)=c(4,2); c(3,4)=c(4,3);
1351 :
1352 272 : c.Invert();
1353 544 : if (!c.IsValid()) return kVeryBig;
1354 :
1355 :
1356 1632 : Double_t res[5] = {
1357 816 : GetY() - t->GetY(),
1358 816 : GetZ() - t->GetZ(),
1359 816 : GetSnp() - t->GetSnp(),
1360 816 : GetTgl() - t->GetTgl(),
1361 816 : GetSigned1Pt() - t->GetSigned1Pt()
1362 : };
1363 :
1364 : Double_t chi2=0.;
1365 3264 : for (Int_t i = 0; i < 5; i++)
1366 23120 : for (Int_t j = 0; j < 5; j++) chi2 += res[i]*res[j]*c(i,j);
1367 :
1368 : return chi2;
1369 816 : }
1370 :
1371 : Bool_t AliExternalTrackParam::
1372 : PropagateTo(Double_t p[3],Double_t covyz[3],Double_t covxyz[3],Double_t bz) {
1373 : //----------------------------------------------------------------
1374 : // Propagate this track to the plane
1375 : // the 3D space point "p" (with the covariance matrix "covyz" and "covxyz")
1376 : // belongs to.
1377 : // The magnetic field is "bz" (kG)
1378 : //
1379 : // The track curvature and the change of the covariance matrix
1380 : // of the track parameters are negleted !
1381 : // (So the "step" should be small compared with 1/curvature)
1382 : //----------------------------------------------------------------
1383 :
1384 0 : Double_t f=GetSnp();
1385 0 : if (TMath::Abs(f) >= kAlmost1) return kFALSE;
1386 0 : Double_t r=TMath::Sqrt((1.-f)*(1.+f));
1387 0 : Double_t a=f/r, b=GetTgl()/r;
1388 :
1389 : Double_t s2=333.*333.; //something reasonably big (cm^2)
1390 :
1391 0 : TMatrixDSym tV(3);
1392 0 : tV(0,0)= s2; tV(0,1)= a*s2; tV(0,2)= b*s2;
1393 0 : tV(1,0)=a*s2; tV(1,1)=a*a*s2; tV(1,2)=a*b*s2;
1394 0 : tV(2,0)=b*s2; tV(2,1)=a*b*s2; tV(2,2)=b*b*s2;
1395 :
1396 0 : TMatrixDSym pV(3);
1397 0 : pV(0,0)=covxyz[0]; pV(0,1)=covxyz[1]; pV(0,2)=covxyz[2];
1398 0 : pV(1,0)=covxyz[1]; pV(1,1)=covyz[0]; pV(1,2)=covyz[1];
1399 0 : pV(2,0)=covxyz[2]; pV(2,1)=covyz[1]; pV(2,2)=covyz[2];
1400 :
1401 0 : TMatrixDSym tpV(tV);
1402 0 : tpV+=pV;
1403 0 : tpV.Invert();
1404 0 : if (!tpV.IsValid()) return kFALSE;
1405 :
1406 0 : TMatrixDSym pW(3),tW(3);
1407 0 : for (Int_t i=0; i<3; i++)
1408 0 : for (Int_t j=0; j<3; j++) {
1409 0 : pW(i,j)=tW(i,j)=0.;
1410 0 : for (Int_t k=0; k<3; k++) {
1411 0 : pW(i,j) += tV(i,k)*tpV(k,j);
1412 0 : tW(i,j) += pV(i,k)*tpV(k,j);
1413 : }
1414 : }
1415 :
1416 0 : Double_t t[3] = {GetX(), GetY(), GetZ()};
1417 :
1418 : Double_t x=0.;
1419 0 : for (Int_t i=0; i<3; i++) x += (tW(0,i)*t[i] + pW(0,i)*p[i]);
1420 0 : Double_t crv=GetC(bz);
1421 0 : if (TMath::Abs(b) < kAlmost0Field) crv=0.;
1422 0 : f += crv*(x-fX);
1423 0 : if (TMath::Abs(f) >= kAlmost1) return kFALSE;
1424 0 : fX=x;
1425 :
1426 0 : fP[0]=0.;
1427 0 : for (Int_t i=0; i<3; i++) fP[0] += (tW(1,i)*t[i] + pW(1,i)*p[i]);
1428 0 : fP[1]=0.;
1429 0 : for (Int_t i=0; i<3; i++) fP[1] += (tW(2,i)*t[i] + pW(2,i)*p[i]);
1430 :
1431 0 : return kTRUE;
1432 0 : }
1433 :
1434 : Double_t *AliExternalTrackParam::GetResiduals(
1435 : Double_t *p,Double_t *cov,Bool_t updated) const {
1436 : //------------------------------------------------------------------
1437 : // Returns the track residuals with the space point "p" having
1438 : // the covariance matrix "cov".
1439 : // If "updated" is kTRUE, the track parameters expected to be updated,
1440 : // otherwise they must be predicted.
1441 : //------------------------------------------------------------------
1442 : static Double_t res[2];
1443 :
1444 0 : Double_t r00=cov[0], r01=cov[1], r11=cov[2];
1445 0 : if (updated) {
1446 0 : r00-=fC[0]; r01-=fC[1]; r11-=fC[2];
1447 0 : } else {
1448 0 : r00+=fC[0]; r01+=fC[1]; r11+=fC[2];
1449 : }
1450 0 : Double_t det=r00*r11 - r01*r01;
1451 :
1452 0 : if (TMath::Abs(det) < kAlmost0) return 0;
1453 :
1454 0 : Double_t tmp=r00; r00=r11/det; r11=tmp/det;
1455 :
1456 0 : if (r00 < 0.) return 0;
1457 0 : if (r11 < 0.) return 0;
1458 :
1459 0 : Double_t dy = fP[0] - p[0];
1460 0 : Double_t dz = fP[1] - p[1];
1461 :
1462 0 : res[0]=dy*TMath::Sqrt(r00);
1463 0 : res[1]=dz*TMath::Sqrt(r11);
1464 :
1465 : return res;
1466 0 : }
1467 :
1468 : Bool_t AliExternalTrackParam::Update(const Double_t p[2], const Double_t cov[3]) {
1469 : //------------------------------------------------------------------
1470 : // Update the track parameters with the space point "p" having
1471 : // the covariance matrix "cov"
1472 : //------------------------------------------------------------------
1473 229998 : Double_t &fP0=fP[0], &fP1=fP[1], &fP2=fP[2], &fP3=fP[3], &fP4=fP[4];
1474 : Double_t
1475 114999 : &fC00=fC[0],
1476 114999 : &fC10=fC[1], &fC11=fC[2],
1477 114999 : &fC20=fC[3], &fC21=fC[4], &fC22=fC[5],
1478 114999 : &fC30=fC[6], &fC31=fC[7], &fC32=fC[8], &fC33=fC[9],
1479 114999 : &fC40=fC[10], &fC41=fC[11], &fC42=fC[12], &fC43=fC[13], &fC44=fC[14];
1480 :
1481 114999 : Double_t r00=cov[0], r01=cov[1], r11=cov[2];
1482 114999 : r00+=fC00; r01+=fC10; r11+=fC11;
1483 114999 : Double_t det=r00*r11 - r01*r01;
1484 :
1485 114999 : if (TMath::Abs(det) < kAlmost0) return kFALSE;
1486 :
1487 :
1488 114999 : Double_t tmp=r00; r00=r11/det; r11=tmp/det; r01=-r01/det;
1489 :
1490 114999 : Double_t k00=fC00*r00+fC10*r01, k01=fC00*r01+fC10*r11;
1491 114999 : Double_t k10=fC10*r00+fC11*r01, k11=fC10*r01+fC11*r11;
1492 114999 : Double_t k20=fC20*r00+fC21*r01, k21=fC20*r01+fC21*r11;
1493 114999 : Double_t k30=fC30*r00+fC31*r01, k31=fC30*r01+fC31*r11;
1494 114999 : Double_t k40=fC40*r00+fC41*r01, k41=fC40*r01+fC41*r11;
1495 :
1496 114999 : Double_t dy=p[0] - fP0, dz=p[1] - fP1;
1497 114999 : Double_t sf=fP2 + k20*dy + k21*dz;
1498 115011 : if (TMath::Abs(sf) > kAlmost1) return kFALSE;
1499 :
1500 114987 : fP0 += k00*dy + k01*dz;
1501 114987 : fP1 += k10*dy + k11*dz;
1502 114987 : fP2 = sf;
1503 114987 : fP3 += k30*dy + k31*dz;
1504 114987 : fP4 += k40*dy + k41*dz;
1505 :
1506 114987 : Double_t c01=fC10, c02=fC20, c03=fC30, c04=fC40;
1507 114987 : Double_t c12=fC21, c13=fC31, c14=fC41;
1508 :
1509 114987 : fC00-=k00*fC00+k01*fC10; fC10-=k00*c01+k01*fC11;
1510 114987 : fC20-=k00*c02+k01*c12; fC30-=k00*c03+k01*c13;
1511 114987 : fC40-=k00*c04+k01*c14;
1512 :
1513 114987 : fC11-=k10*c01+k11*fC11;
1514 114987 : fC21-=k10*c02+k11*c12; fC31-=k10*c03+k11*c13;
1515 114987 : fC41-=k10*c04+k11*c14;
1516 :
1517 114987 : fC22-=k20*c02+k21*c12; fC32-=k20*c03+k21*c13;
1518 114987 : fC42-=k20*c04+k21*c14;
1519 :
1520 114987 : fC33-=k30*c03+k31*c13;
1521 114987 : fC43-=k30*c04+k31*c14;
1522 :
1523 114987 : fC44-=k40*c04+k41*c14;
1524 :
1525 114987 : CheckCovariance();
1526 :
1527 : return kTRUE;
1528 114999 : }
1529 :
1530 : void
1531 : AliExternalTrackParam::GetHelixParameters(Double_t hlx[6], Double_t b) const {
1532 : //--------------------------------------------------------------------
1533 : // External track parameters -> helix parameters
1534 : // "b" - magnetic field (kG)
1535 : //--------------------------------------------------------------------
1536 656 : Double_t cs=TMath::Cos(fAlpha), sn=TMath::Sin(fAlpha);
1537 :
1538 328 : hlx[0]=fP[0]; hlx[1]=fP[1]; hlx[2]=fP[2]; hlx[3]=fP[3];
1539 :
1540 328 : hlx[5]=fX*cs - hlx[0]*sn; // x0
1541 328 : hlx[0]=fX*sn + hlx[0]*cs; // y0
1542 : //hlx[1]= // z0
1543 328 : hlx[2]=TMath::ASin(hlx[2]) + fAlpha; // phi0
1544 : //hlx[3]= // tgl
1545 328 : hlx[4]=GetC(b); // C
1546 328 : }
1547 :
1548 :
1549 : static void Evaluate(const Double_t *h, Double_t t,
1550 : Double_t r[3], //radius vector
1551 : Double_t g[3], //first defivatives
1552 : Double_t gg[3]) //second derivatives
1553 : {
1554 : //--------------------------------------------------------------------
1555 : // Calculate position of a point on a track and some derivatives
1556 : //--------------------------------------------------------------------
1557 3312 : Double_t phase=h[4]*t+h[2];
1558 1656 : Double_t sn=TMath::Sin(phase), cs=TMath::Cos(phase);
1559 :
1560 1656 : r[0] = h[5];
1561 1656 : r[1] = h[0];
1562 1656 : if (TMath::Abs(h[4])>kAlmost0) {
1563 1656 : r[0] += (sn - h[6])/h[4];
1564 1656 : r[1] -= (cs - h[7])/h[4];
1565 1656 : } else {
1566 0 : r[0] += t*cs;
1567 0 : r[1] -= -t*sn;
1568 : }
1569 1656 : r[2] = h[1] + h[3]*t;
1570 :
1571 1656 : g[0] = cs; g[1]=sn; g[2]=h[3];
1572 :
1573 1656 : gg[0]=-h[4]*sn; gg[1]=h[4]*cs; gg[2]=0.;
1574 1656 : }
1575 :
1576 : Double_t AliExternalTrackParam::GetDCA(const AliExternalTrackParam *p,
1577 : Double_t b, Double_t &xthis, Double_t &xp) const {
1578 : //------------------------------------------------------------
1579 : // Returns the (weighed !) distance of closest approach between
1580 : // this track and the track "p".
1581 : // Other returned values:
1582 : // xthis, xt - coordinates of tracks' reference planes at the DCA
1583 : //-----------------------------------------------------------
1584 328 : Double_t dy2=GetSigmaY2() + p->GetSigmaY2();
1585 164 : Double_t dz2=GetSigmaZ2() + p->GetSigmaZ2();
1586 : Double_t dx2=dy2;
1587 :
1588 164 : Double_t p1[8]; GetHelixParameters(p1,b);
1589 164 : p1[6]=TMath::Sin(p1[2]); p1[7]=TMath::Cos(p1[2]);
1590 164 : Double_t p2[8]; p->GetHelixParameters(p2,b);
1591 164 : p2[6]=TMath::Sin(p2[2]); p2[7]=TMath::Cos(p2[2]);
1592 :
1593 :
1594 164 : Double_t r1[3],g1[3],gg1[3]; Double_t t1=0.;
1595 164 : Evaluate(p1,t1,r1,g1,gg1);
1596 164 : Double_t r2[3],g2[3],gg2[3]; Double_t t2=0.;
1597 164 : Evaluate(p2,t2,r2,g2,gg2);
1598 :
1599 164 : Double_t dx=r2[0]-r1[0], dy=r2[1]-r1[1], dz=r2[2]-r1[2];
1600 164 : Double_t dm=dx*dx/dx2 + dy*dy/dy2 + dz*dz/dz2;
1601 :
1602 : Int_t max=27;
1603 954 : while (max--) {
1604 790 : Double_t gt1=-(dx*g1[0]/dx2 + dy*g1[1]/dy2 + dz*g1[2]/dz2);
1605 790 : Double_t gt2=+(dx*g2[0]/dx2 + dy*g2[1]/dy2 + dz*g2[2]/dz2);
1606 1580 : Double_t h11=(g1[0]*g1[0] - dx*gg1[0])/dx2 +
1607 1580 : (g1[1]*g1[1] - dy*gg1[1])/dy2 +
1608 790 : (g1[2]*g1[2] - dz*gg1[2])/dz2;
1609 1580 : Double_t h22=(g2[0]*g2[0] + dx*gg2[0])/dx2 +
1610 1580 : (g2[1]*g2[1] + dy*gg2[1])/dy2 +
1611 790 : (g2[2]*g2[2] + dz*gg2[2])/dz2;
1612 790 : Double_t h12=-(g1[0]*g2[0]/dx2 + g1[1]*g2[1]/dy2 + g1[2]*g2[2]/dz2);
1613 :
1614 790 : Double_t det=h11*h22-h12*h12;
1615 :
1616 : Double_t dt1,dt2;
1617 790 : if (TMath::Abs(det)<1.e-33) {
1618 : //(quasi)singular Hessian
1619 0 : dt1=-gt1; dt2=-gt2;
1620 0 : } else {
1621 790 : dt1=-(gt1*h22 - gt2*h12)/det;
1622 790 : dt2=-(h11*gt2 - h12*gt1)/det;
1623 : }
1624 :
1625 819 : if ((dt1*gt1+dt2*gt2)>0) {dt1=-dt1; dt2=-dt2;}
1626 :
1627 : //check delta(phase1) ?
1628 : //check delta(phase2) ?
1629 :
1630 790 : if (TMath::Abs(dt1)/(TMath::Abs(t1)+1.e-3) < 1.e-4)
1631 166 : if (TMath::Abs(dt2)/(TMath::Abs(t2)+1.e-3) < 1.e-4) {
1632 164 : if ((gt1*gt1+gt2*gt2) > 1.e-4/dy2/dy2)
1633 0 : AliDebug(1," stopped at not a stationary point !");
1634 164 : Double_t lmb=h11+h22; lmb=lmb-TMath::Sqrt(lmb*lmb-4*det);
1635 164 : if (lmb < 0.)
1636 0 : AliDebug(1," stopped at not a minimum !");
1637 : break;
1638 : }
1639 :
1640 : Double_t dd=dm;
1641 664 : for (Int_t div=1 ; ; div*=2) {
1642 664 : Evaluate(p1,t1+dt1,r1,g1,gg1);
1643 664 : Evaluate(p2,t2+dt2,r2,g2,gg2);
1644 664 : dx=r2[0]-r1[0]; dy=r2[1]-r1[1]; dz=r2[2]-r1[2];
1645 664 : dd=dx*dx/dx2 + dy*dy/dy2 + dz*dz/dz2;
1646 1290 : if (dd<dm) break;
1647 38 : dt1*=0.5; dt2*=0.5;
1648 38 : if (div>512) {
1649 0 : AliDebug(1," overshoot !"); break;
1650 : }
1651 : }
1652 : dm=dd;
1653 :
1654 626 : t1+=dt1;
1655 626 : t2+=dt2;
1656 :
1657 626 : }
1658 :
1659 164 : if (max<=0) AliDebug(1," too many iterations !");
1660 :
1661 164 : Double_t cs=TMath::Cos(GetAlpha());
1662 164 : Double_t sn=TMath::Sin(GetAlpha());
1663 164 : xthis=r1[0]*cs + r1[1]*sn;
1664 :
1665 164 : cs=TMath::Cos(p->GetAlpha());
1666 164 : sn=TMath::Sin(p->GetAlpha());
1667 164 : xp=r2[0]*cs + r2[1]*sn;
1668 :
1669 328 : return TMath::Sqrt(dm*TMath::Sqrt(dy2*dz2));
1670 164 : }
1671 :
1672 : Double_t AliExternalTrackParam::
1673 : PropagateToDCA(AliExternalTrackParam *p, Double_t b) {
1674 : //--------------------------------------------------------------
1675 : // Propagates this track and the argument track to the position of the
1676 : // distance of closest approach.
1677 : // Returns the (weighed !) distance of closest approach.
1678 : //--------------------------------------------------------------
1679 0 : Double_t xthis,xp;
1680 0 : Double_t dca=GetDCA(p,b,xthis,xp);
1681 :
1682 0 : if (!PropagateTo(xthis,b)) {
1683 : //AliWarning(" propagation failed !");
1684 0 : return 1e+33;
1685 : }
1686 :
1687 0 : if (!p->PropagateTo(xp,b)) {
1688 : //AliWarning(" propagation failed !";
1689 0 : return 1e+33;
1690 : }
1691 :
1692 0 : return dca;
1693 0 : }
1694 :
1695 :
1696 : Bool_t AliExternalTrackParam::PropagateToDCA(const AliVVertex *vtx,
1697 : Double_t b, Double_t maxd, Double_t dz[2], Double_t covar[3]) {
1698 : //
1699 : // Propagate this track to the DCA to vertex "vtx",
1700 : // if the (rough) transverse impact parameter is not bigger then "maxd".
1701 : // Magnetic field is "b" (kG).
1702 : //
1703 : // a) The track gets extapolated to the DCA to the vertex.
1704 : // b) The impact parameters and their covariance matrix are calculated.
1705 : //
1706 : // In the case of success, the returned value is kTRUE
1707 : // (otherwise, it's kFALSE)
1708 : //
1709 880 : Double_t alpha=GetAlpha();
1710 440 : Double_t sn=TMath::Sin(alpha), cs=TMath::Cos(alpha);
1711 440 : Double_t x=GetX(), y=GetParameter()[0], snp=GetParameter()[2];
1712 440 : Double_t xv= vtx->GetX()*cs + vtx->GetY()*sn;
1713 440 : Double_t yv=-vtx->GetX()*sn + vtx->GetY()*cs, zv=vtx->GetZ();
1714 440 : x-=xv; y-=yv;
1715 :
1716 : //Estimate the impact parameter neglecting the track curvature
1717 440 : Double_t d=TMath::Abs(x*snp - y*TMath::Sqrt((1.-snp)*(1.+snp)));
1718 440 : if (d > maxd) return kFALSE;
1719 :
1720 : //Propagate to the DCA
1721 440 : Double_t crv=GetC(b);
1722 440 : if (TMath::Abs(b) < kAlmost0Field) crv=0.;
1723 :
1724 440 : Double_t tgfv=-(crv*x - snp)/(crv*y + TMath::Sqrt((1.-snp)*(1.+snp)));
1725 440 : sn=tgfv/TMath::Sqrt(1.+ tgfv*tgfv); cs=TMath::Sqrt((1.-sn)*(1.+sn));
1726 880 : if (TMath::Abs(tgfv)>0.) cs = sn/tgfv;
1727 : else cs=1.;
1728 :
1729 440 : x = xv*cs + yv*sn;
1730 440 : yv=-xv*sn + yv*cs; xv=x;
1731 :
1732 440 : if (!Propagate(alpha+TMath::ASin(sn),xv,b)) return kFALSE;
1733 :
1734 440 : if (dz==0) return kTRUE;
1735 440 : dz[0] = GetParameter()[0] - yv;
1736 440 : dz[1] = GetParameter()[1] - zv;
1737 :
1738 440 : if (covar==0) return kTRUE;
1739 440 : Double_t cov[6]; vtx->GetCovarianceMatrix(cov);
1740 :
1741 : //***** Improvements by A.Dainese
1742 440 : alpha=GetAlpha(); sn=TMath::Sin(alpha); cs=TMath::Cos(alpha);
1743 440 : Double_t s2ylocvtx = cov[0]*sn*sn + cov[2]*cs*cs - 2.*cov[1]*cs*sn;
1744 440 : covar[0] = GetCovariance()[0] + s2ylocvtx; // neglecting correlations
1745 440 : covar[1] = GetCovariance()[1]; // between (x,y) and z
1746 440 : covar[2] = GetCovariance()[2] + cov[5]; // in vertex's covariance matrix
1747 : //*****
1748 :
1749 : return kTRUE;
1750 880 : }
1751 :
1752 : Bool_t AliExternalTrackParam::PropagateToDCABxByBz(const AliVVertex *vtx,
1753 : Double_t b[3], Double_t maxd, Double_t dz[2], Double_t covar[3]) {
1754 : //
1755 : // Propagate this track to the DCA to vertex "vtx",
1756 : // if the (rough) transverse impact parameter is not bigger then "maxd".
1757 : //
1758 : // This function takes into account all three components of the magnetic
1759 : // field given by the b[3] arument (kG)
1760 : //
1761 : // a) The track gets extapolated to the DCA to the vertex.
1762 : // b) The impact parameters and their covariance matrix are calculated.
1763 : //
1764 : // In the case of success, the returned value is kTRUE
1765 : // (otherwise, it's kFALSE)
1766 : //
1767 696 : Double_t alpha=GetAlpha();
1768 348 : Double_t sn=TMath::Sin(alpha), cs=TMath::Cos(alpha);
1769 348 : Double_t x=GetX(), y=GetParameter()[0], snp=GetParameter()[2];
1770 348 : Double_t xv= vtx->GetX()*cs + vtx->GetY()*sn;
1771 348 : Double_t yv=-vtx->GetX()*sn + vtx->GetY()*cs, zv=vtx->GetZ();
1772 348 : x-=xv; y-=yv;
1773 :
1774 : //Estimate the impact parameter neglecting the track curvature
1775 348 : Double_t d=TMath::Abs(x*snp - y*TMath::Sqrt((1.-snp)*(1.+snp)));
1776 348 : if (d > maxd) return kFALSE;
1777 :
1778 : //Propagate to the DCA
1779 348 : Double_t crv=GetC(b[2]);
1780 348 : if (TMath::Abs(b[2]) < kAlmost0Field) crv=0.;
1781 :
1782 348 : Double_t tgfv=-(crv*x - snp)/(crv*y + TMath::Sqrt((1.-snp)*(1.+snp)));
1783 348 : sn=tgfv/TMath::Sqrt(1.+ tgfv*tgfv); cs=TMath::Sqrt((1.-sn)*(1.+sn));
1784 696 : if (TMath::Abs(tgfv)>0.) cs = sn/tgfv;
1785 : else cs=1.;
1786 :
1787 348 : x = xv*cs + yv*sn;
1788 348 : yv=-xv*sn + yv*cs; xv=x;
1789 :
1790 348 : if (!PropagateBxByBz(alpha+TMath::ASin(sn),xv,b)) return kFALSE;
1791 :
1792 348 : if (dz==0) return kTRUE;
1793 348 : dz[0] = GetParameter()[0] - yv;
1794 348 : dz[1] = GetParameter()[1] - zv;
1795 :
1796 348 : if (covar==0) return kTRUE;
1797 348 : Double_t cov[6]; vtx->GetCovarianceMatrix(cov);
1798 :
1799 : //***** Improvements by A.Dainese
1800 348 : alpha=GetAlpha(); sn=TMath::Sin(alpha); cs=TMath::Cos(alpha);
1801 348 : Double_t s2ylocvtx = cov[0]*sn*sn + cov[2]*cs*cs - 2.*cov[1]*cs*sn;
1802 348 : covar[0] = GetCovariance()[0] + s2ylocvtx; // neglecting correlations
1803 348 : covar[1] = GetCovariance()[1]; // between (x,y) and z
1804 348 : covar[2] = GetCovariance()[2] + cov[5]; // in vertex's covariance matrix
1805 : //*****
1806 :
1807 : return kTRUE;
1808 696 : }
1809 :
1810 : void AliExternalTrackParam::GetDirection(Double_t d[3]) const {
1811 : //----------------------------------------------------------------
1812 : // This function returns a unit vector along the track direction
1813 : // in the global coordinate system.
1814 : //----------------------------------------------------------------
1815 16 : Double_t cs=TMath::Cos(fAlpha), sn=TMath::Sin(fAlpha);
1816 8 : Double_t snp=fP[2];
1817 8 : Double_t csp =TMath::Sqrt((1.-snp)*(1.+snp));
1818 8 : Double_t norm=TMath::Sqrt(1.+ fP[3]*fP[3]);
1819 8 : d[0]=(csp*cs - snp*sn)/norm;
1820 8 : d[1]=(snp*cs + csp*sn)/norm;
1821 8 : d[2]=fP[3]/norm;
1822 8 : }
1823 :
1824 : Bool_t AliExternalTrackParam::GetPxPyPz(Double_t p[3]) const {
1825 : //---------------------------------------------------------------------
1826 : // This function returns the global track momentum components
1827 : // Results for (nearly) straight tracks are meaningless !
1828 : //---------------------------------------------------------------------
1829 614636 : p[0]=fP[4]; p[1]=fP[2]; p[2]=fP[3];
1830 307318 : return Local2GlobalMomentum(p,fAlpha);
1831 : }
1832 :
1833 : Double_t AliExternalTrackParam::Px() const {
1834 : //---------------------------------------------------------------------
1835 : // Returns x-component of momentum
1836 : // Result for (nearly) straight tracks is meaningless !
1837 : //---------------------------------------------------------------------
1838 :
1839 0 : Double_t p[3]={kVeryBig,kVeryBig,kVeryBig};
1840 0 : GetPxPyPz(p);
1841 :
1842 0 : return p[0];
1843 0 : }
1844 :
1845 : Double_t AliExternalTrackParam::Py() const {
1846 : //---------------------------------------------------------------------
1847 : // Returns y-component of momentum
1848 : // Result for (nearly) straight tracks is meaningless !
1849 : //---------------------------------------------------------------------
1850 :
1851 0 : Double_t p[3]={kVeryBig,kVeryBig,kVeryBig};
1852 0 : GetPxPyPz(p);
1853 :
1854 0 : return p[1];
1855 0 : }
1856 :
1857 : Double_t AliExternalTrackParam::Xv() const {
1858 : //---------------------------------------------------------------------
1859 : // Returns x-component of first track point
1860 : //---------------------------------------------------------------------
1861 :
1862 0 : Double_t r[3]={0.,0.,0.};
1863 0 : GetXYZ(r);
1864 :
1865 0 : return r[0];
1866 0 : }
1867 :
1868 : Double_t AliExternalTrackParam::Yv() const {
1869 : //---------------------------------------------------------------------
1870 : // Returns y-component of first track point
1871 : //---------------------------------------------------------------------
1872 :
1873 0 : Double_t r[3]={0.,0.,0.};
1874 0 : GetXYZ(r);
1875 :
1876 0 : return r[1];
1877 0 : }
1878 :
1879 : Double_t AliExternalTrackParam::Theta() const {
1880 : // return theta angle of momentum
1881 :
1882 564 : return 0.5*TMath::Pi() - TMath::ATan(fP[3]);
1883 : }
1884 :
1885 : Double_t AliExternalTrackParam::Phi() const {
1886 : //---------------------------------------------------------------------
1887 : // Returns the azimuthal angle of momentum
1888 : // 0 <= phi < 2*pi
1889 : //---------------------------------------------------------------------
1890 :
1891 2630 : Double_t phi=TMath::ASin(fP[2]) + fAlpha;
1892 1801 : if (phi<0.) phi+=2.*TMath::Pi();
1893 829 : else if (phi>=2.*TMath::Pi()) phi-=2.*TMath::Pi();
1894 :
1895 1315 : return phi;
1896 : }
1897 :
1898 : Double_t AliExternalTrackParam::PhiPos() const {
1899 : //---------------------------------------------------------------------
1900 : // Returns the azimuthal angle of position
1901 : // 0 <= phi < 2*pi
1902 : //---------------------------------------------------------------------
1903 272 : Double_t r[3]={0.,0.,0.};
1904 136 : GetXYZ(r);
1905 136 : Double_t phi=TMath::ATan2(r[1],r[0]);
1906 184 : if (phi<0.) phi+=2.*TMath::Pi();
1907 :
1908 136 : return phi;
1909 136 : }
1910 :
1911 : Double_t AliExternalTrackParam::M() const {
1912 : // return particle mass
1913 :
1914 : // No mass information available so far.
1915 : // Redifine in derived class!
1916 :
1917 0 : return -999.;
1918 : }
1919 :
1920 : Double_t AliExternalTrackParam::E() const {
1921 : // return particle energy
1922 :
1923 : // No PID information available so far.
1924 : // Redifine in derived class!
1925 :
1926 0 : return -999.;
1927 : }
1928 :
1929 : Double_t AliExternalTrackParam::Eta() const {
1930 : // return pseudorapidity
1931 :
1932 504 : return -TMath::Log(TMath::Tan(0.5 * Theta()));
1933 : }
1934 :
1935 : Double_t AliExternalTrackParam::Y() const {
1936 : // return rapidity
1937 :
1938 : // No PID information available so far.
1939 : // Redifine in derived class!
1940 :
1941 0 : return -999.;
1942 : }
1943 :
1944 : Bool_t AliExternalTrackParam::GetXYZ(Double_t *r) const {
1945 : //---------------------------------------------------------------------
1946 : // This function returns the global track position
1947 : //---------------------------------------------------------------------
1948 2185030 : r[0]=fX; r[1]=fP[0]; r[2]=fP[1];
1949 1092515 : return Local2GlobalPosition(r,fAlpha);
1950 : }
1951 :
1952 : Bool_t AliExternalTrackParam::GetCovarianceXYZPxPyPz(Double_t cv[21]) const {
1953 : //---------------------------------------------------------------------
1954 : // This function returns the global covariance matrix of the track params
1955 : //
1956 : // Cov(x,x) ... : cv[0]
1957 : // Cov(y,x) ... : cv[1] cv[2]
1958 : // Cov(z,x) ... : cv[3] cv[4] cv[5]
1959 : // Cov(px,x)... : cv[6] cv[7] cv[8] cv[9]
1960 : // Cov(py,x)... : cv[10] cv[11] cv[12] cv[13] cv[14]
1961 : // Cov(pz,x)... : cv[15] cv[16] cv[17] cv[18] cv[19] cv[20]
1962 : //
1963 : // Results for (nearly) straight tracks are meaningless !
1964 : //---------------------------------------------------------------------
1965 494 : if (TMath::Abs(fP[4])<=kAlmost0) {
1966 0 : for (Int_t i=0; i<21; i++) cv[i]=0.;
1967 0 : return kFALSE;
1968 : }
1969 247 : if (TMath::Abs(fP[2]) > kAlmost1) {
1970 0 : for (Int_t i=0; i<21; i++) cv[i]=0.;
1971 0 : return kFALSE;
1972 : }
1973 247 : Double_t pt=1./TMath::Abs(fP[4]);
1974 247 : Double_t cs=TMath::Cos(fAlpha), sn=TMath::Sin(fAlpha);
1975 247 : Double_t r=TMath::Sqrt((1.-fP[2])*(1.+fP[2]));
1976 :
1977 247 : Double_t m00=-sn, m10=cs;
1978 247 : Double_t m23=-pt*(sn + fP[2]*cs/r), m43=-pt*pt*(r*cs - fP[2]*sn);
1979 247 : Double_t m24= pt*(cs - fP[2]*sn/r), m44=-pt*pt*(r*sn + fP[2]*cs);
1980 247 : Double_t m35=pt, m45=-pt*pt*fP[3];
1981 :
1982 247 : m43*=GetSign();
1983 247 : m44*=GetSign();
1984 247 : m45*=GetSign();
1985 :
1986 247 : cv[0 ] = fC[0]*m00*m00;
1987 247 : cv[1 ] = fC[0]*m00*m10;
1988 247 : cv[2 ] = fC[0]*m10*m10;
1989 247 : cv[3 ] = fC[1]*m00;
1990 247 : cv[4 ] = fC[1]*m10;
1991 247 : cv[5 ] = fC[2];
1992 247 : cv[6 ] = m00*(fC[3]*m23 + fC[10]*m43);
1993 247 : cv[7 ] = m10*(fC[3]*m23 + fC[10]*m43);
1994 247 : cv[8 ] = fC[4]*m23 + fC[11]*m43;
1995 247 : cv[9 ] = m23*(fC[5]*m23 + fC[12]*m43) + m43*(fC[12]*m23 + fC[14]*m43);
1996 247 : cv[10] = m00*(fC[3]*m24 + fC[10]*m44);
1997 247 : cv[11] = m10*(fC[3]*m24 + fC[10]*m44);
1998 247 : cv[12] = fC[4]*m24 + fC[11]*m44;
1999 247 : cv[13] = m23*(fC[5]*m24 + fC[12]*m44) + m43*(fC[12]*m24 + fC[14]*m44);
2000 247 : cv[14] = m24*(fC[5]*m24 + fC[12]*m44) + m44*(fC[12]*m24 + fC[14]*m44);
2001 247 : cv[15] = m00*(fC[6]*m35 + fC[10]*m45);
2002 247 : cv[16] = m10*(fC[6]*m35 + fC[10]*m45);
2003 247 : cv[17] = fC[7]*m35 + fC[11]*m45;
2004 247 : cv[18] = m23*(fC[8]*m35 + fC[12]*m45) + m43*(fC[13]*m35 + fC[14]*m45);
2005 247 : cv[19] = m24*(fC[8]*m35 + fC[12]*m45) + m44*(fC[13]*m35 + fC[14]*m45);
2006 247 : cv[20] = m35*(fC[9]*m35 + fC[13]*m45) + m45*(fC[13]*m35 + fC[14]*m45);
2007 :
2008 : return kTRUE;
2009 247 : }
2010 :
2011 :
2012 : Bool_t
2013 : AliExternalTrackParam::GetPxPyPzAt(Double_t x, Double_t b, Double_t *p) const {
2014 : //---------------------------------------------------------------------
2015 : // This function returns the global track momentum extrapolated to
2016 : // the radial position "x" (cm) in the magnetic field "b" (kG)
2017 : //---------------------------------------------------------------------
2018 360 : p[0]=fP[4];
2019 180 : p[1]=fP[2]+(x-fX)*GetC(b);
2020 180 : p[2]=fP[3];
2021 180 : return Local2GlobalMomentum(p,fAlpha);
2022 : }
2023 :
2024 : Bool_t AliExternalTrackParam::GetYZAt(Double_t x, Double_t b, Double_t *yz) const
2025 : {
2026 : //---------------------------------------------------------------------
2027 : // This function returns the local Y,Z-coordinates of the intersection
2028 : // point between this track and the reference plane "x" (cm).
2029 : // Magnetic field "b" (kG)
2030 : //---------------------------------------------------------------------
2031 0 : double dx=x-fX;
2032 0 : if(TMath::Abs(dx)<=kAlmost0) {
2033 0 : yz[0] = fP[0];
2034 0 : yz[1] = fP[1];
2035 0 : return kTRUE;
2036 : }
2037 0 : double crv=GetC(b);
2038 0 : double f1=fP[2], x2r = crv*dx, f2=f1 + x2r;
2039 0 : if (TMath::Abs(f1) >= kAlmost1 ||
2040 0 : TMath::Abs(f2) >= kAlmost1 ||
2041 0 : TMath::Abs(fP[4])< kAlmost0) return kFALSE;
2042 0 : double r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
2043 0 : double dy2dx = (f1+f2)/(r1+r2);
2044 0 : yz[0] = fP[0] + dx*dy2dx;
2045 0 : if (TMath::Abs(x2r)<0.05) yz[1] = fP[1] + dx*(r2 + f2*dy2dx)*fP[3];
2046 : else {
2047 0 : double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
2048 0 : double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
2049 0 : yz[1] = fP[1] + rot/crv*fP[3];
2050 : }
2051 : return kTRUE;
2052 0 : }
2053 :
2054 :
2055 : Bool_t
2056 : AliExternalTrackParam::GetYAt(Double_t x, Double_t b, Double_t &y) const {
2057 : //---------------------------------------------------------------------
2058 : // This function returns the local Y-coordinate of the intersection
2059 : // point between this track and the reference plane "x" (cm).
2060 : // Magnetic field "b" (kG)
2061 : //---------------------------------------------------------------------
2062 23154 : Double_t dx=x-fX;
2063 11577 : if(TMath::Abs(dx)<=kAlmost0) {y=fP[0]; return kTRUE;}
2064 :
2065 11577 : Double_t f1=fP[2], f2=f1 + dx*GetC(b);
2066 :
2067 11577 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
2068 11637 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
2069 :
2070 11517 : Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
2071 11517 : y = fP[0] + dx*(f1+f2)/(r1+r2);
2072 : return kTRUE;
2073 11577 : }
2074 :
2075 : Bool_t
2076 : AliExternalTrackParam::GetZAt(Double_t x, Double_t b, Double_t &z) const {
2077 : //---------------------------------------------------------------------
2078 : // This function returns the local Z-coordinate of the intersection
2079 : // point between this track and the reference plane "x" (cm).
2080 : // Magnetic field "b" (kG)
2081 : //---------------------------------------------------------------------
2082 259370 : Double_t dx=x-fX;
2083 129685 : if(TMath::Abs(dx)<=kAlmost0) {z=fP[1]; return kTRUE;}
2084 :
2085 129685 : Double_t crv=GetC(b);
2086 129685 : Double_t x2r = crv*dx;
2087 129685 : Double_t f1=fP[2], f2=f1 + x2r;
2088 :
2089 129685 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
2090 129821 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
2091 :
2092 129549 : Double_t r1=sqrt((1.-f1)*(1.+f1)), r2=sqrt((1.-f2)*(1.+f2));
2093 129549 : double dy2dx = (f1+f2)/(r1+r2);
2094 129549 : if (TMath::Abs(x2r)<0.05) {
2095 128703 : z = fP[1] + dx*(r2 + f2*dy2dx)*fP[3]; // Many thanks to P.Hristov !
2096 128703 : }
2097 : else {
2098 : // for small dx/R the linear apporximation of the arc by the segment is OK,
2099 : // but at large dx/R the error is very large and leads to incorrect Z propagation
2100 : // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
2101 : // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
2102 : // Similarly, the rotation angle in linear in dx only for dx<<R
2103 846 : double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
2104 846 : double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
2105 846 : z = fP[1] + rot/crv*fP[3];
2106 : }
2107 : return kTRUE;
2108 129685 : }
2109 :
2110 : Bool_t
2111 : AliExternalTrackParam::GetXYZAt(Double_t x, Double_t b, Double_t *r) const {
2112 : //---------------------------------------------------------------------
2113 : // This function returns the global track position extrapolated to
2114 : // the radial position "x" (cm) in the magnetic field "b" (kG)
2115 : //---------------------------------------------------------------------
2116 86740 : Double_t dx=x-fX;
2117 43468 : if(TMath::Abs(dx)<=kAlmost0) return GetXYZ(r);
2118 :
2119 43272 : Double_t crv=GetC(b);
2120 43272 : Double_t x2r = crv*dx;
2121 43272 : Double_t f1=fP[2], f2=f1 + dx*crv;
2122 :
2123 43272 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
2124 45236 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
2125 :
2126 41308 : Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
2127 41308 : double dy2dx = (f1+f2)/(r1+r2);
2128 41308 : r[0] = x;
2129 41308 : r[1] = fP[0] + dx*dy2dx;
2130 41308 : if (TMath::Abs(x2r)<0.05) {
2131 38379 : r[2] = fP[1] + dx*(r2 + f2*dy2dx)*fP[3];//Thanks to Andrea & Peter
2132 38379 : }
2133 : else {
2134 : // for small dx/R the linear apporximation of the arc by the segment is OK,
2135 : // but at large dx/R the error is very large and leads to incorrect Z propagation
2136 : // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
2137 : // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
2138 : // Similarly, the rotation angle in linear in dx only for dx<<R
2139 2929 : double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
2140 2929 : double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
2141 2929 : r[2] = fP[1] + rot/crv*fP[3];
2142 : }
2143 :
2144 41308 : return Local2GlobalPosition(r,fAlpha);
2145 43370 : }
2146 :
2147 : //_____________________________________________________________________________
2148 : void AliExternalTrackParam::Print(Option_t* /*option*/) const
2149 : {
2150 : // print the parameters and the covariance matrix
2151 :
2152 0 : printf("AliExternalTrackParam: x = %-12g alpha = %-12g\n", fX, fAlpha);
2153 0 : printf(" parameters: %12g %12g %12g %12g %12g\n",
2154 0 : fP[0], fP[1], fP[2], fP[3], fP[4]);
2155 0 : printf(" covariance: %12g\n", fC[0]);
2156 0 : printf(" %12g %12g\n", fC[1], fC[2]);
2157 0 : printf(" %12g %12g %12g\n", fC[3], fC[4], fC[5]);
2158 0 : printf(" %12g %12g %12g %12g\n",
2159 0 : fC[6], fC[7], fC[8], fC[9]);
2160 0 : printf(" %12g %12g %12g %12g %12g\n",
2161 0 : fC[10], fC[11], fC[12], fC[13], fC[14]);
2162 0 : }
2163 :
2164 : Double_t AliExternalTrackParam::GetSnpAt(Double_t x,Double_t b) const {
2165 : //
2166 : // Get sinus at given x
2167 : //
2168 0 : Double_t crv=GetC(b);
2169 0 : if (TMath::Abs(b) < kAlmost0Field) crv=0.;
2170 0 : Double_t dx = x-fX;
2171 0 : Double_t res = fP[2]+dx*crv;
2172 0 : return res;
2173 : }
2174 :
2175 : Bool_t AliExternalTrackParam::GetDistance(AliExternalTrackParam *param2, Double_t x, Double_t dist[3], Double_t bz){
2176 : //------------------------------------------------------------------------
2177 : // Get the distance between two tracks at the local position x
2178 : // working in the local frame of this track.
2179 : // Origin : Marian.Ivanov@cern.ch
2180 : //-----------------------------------------------------------------------
2181 0 : Double_t xyz[3];
2182 0 : Double_t xyz2[3];
2183 0 : xyz[0]=x;
2184 0 : if (!GetYAt(x,bz,xyz[1])) return kFALSE;
2185 0 : if (!GetZAt(x,bz,xyz[2])) return kFALSE;
2186 : //
2187 : //
2188 0 : if (TMath::Abs(GetAlpha()-param2->GetAlpha())<kAlmost0){
2189 0 : xyz2[0]=x;
2190 0 : if (!param2->GetYAt(x,bz,xyz2[1])) return kFALSE;
2191 0 : if (!param2->GetZAt(x,bz,xyz2[2])) return kFALSE;
2192 : }else{
2193 : //
2194 0 : Double_t xyz1[3];
2195 0 : Double_t dfi = param2->GetAlpha()-GetAlpha();
2196 0 : Double_t ca = TMath::Cos(dfi), sa = TMath::Sin(dfi);
2197 0 : xyz2[0] = xyz[0]*ca+xyz[1]*sa;
2198 0 : xyz2[1] = -xyz[0]*sa+xyz[1]*ca;
2199 : //
2200 0 : xyz1[0]=xyz2[0];
2201 0 : if (!param2->GetYAt(xyz2[0],bz,xyz1[1])) return kFALSE;
2202 0 : if (!param2->GetZAt(xyz2[0],bz,xyz1[2])) return kFALSE;
2203 : //
2204 0 : xyz2[0] = xyz1[0]*ca-xyz1[1]*sa;
2205 0 : xyz2[1] = +xyz1[0]*sa+xyz1[1]*ca;
2206 0 : xyz2[2] = xyz1[2];
2207 0 : }
2208 0 : dist[0] = xyz[0]-xyz2[0];
2209 0 : dist[1] = xyz[1]-xyz2[1];
2210 0 : dist[2] = xyz[2]-xyz2[2];
2211 :
2212 0 : return kTRUE;
2213 0 : }
2214 :
2215 :
2216 : //
2217 : // Draw functionality.
2218 : // Origin: Marian Ivanov, Marian.Ivanov@cern.ch
2219 : //
2220 :
2221 : void AliExternalTrackParam::DrawTrack(Float_t magf, Float_t minR, Float_t maxR, Float_t stepR){
2222 : //
2223 : // Draw track line
2224 : //
2225 0 : if (minR>maxR) return ;
2226 0 : if (stepR<=0) return ;
2227 0 : Int_t npoints = TMath::Nint((maxR-minR)/stepR)+1;
2228 0 : if (npoints<1) return;
2229 0 : TPolyMarker3D *polymarker = new TPolyMarker3D(npoints);
2230 0 : FillPolymarker(polymarker, magf,minR,maxR,stepR);
2231 0 : polymarker->Draw();
2232 0 : }
2233 :
2234 : //
2235 : void AliExternalTrackParam::FillPolymarker(TPolyMarker3D *pol, Float_t magF, Float_t minR, Float_t maxR, Float_t stepR){
2236 : //
2237 : // Fill points in the polymarker
2238 : //
2239 : Int_t counter=0;
2240 0 : for (Double_t r=minR; r<maxR; r+=stepR){
2241 0 : Double_t point[3];
2242 0 : GetXYZAt(r,magF,point);
2243 0 : pol->SetPoint(counter,point[0],point[1], point[2]);
2244 : // printf("xyz\t%f\t%f\t%f\n",point[0], point[1],point[2]);
2245 0 : counter++;
2246 0 : }
2247 0 : }
2248 :
2249 : Int_t AliExternalTrackParam::GetIndex(Int_t i, Int_t j){
2250 : //
2251 20340 : Int_t min = TMath::Min(i,j);
2252 10170 : Int_t max = TMath::Max(i,j);
2253 :
2254 10170 : return min+(max+1)*max/2;
2255 : }
2256 :
2257 :
2258 : void AliExternalTrackParam::g3helx3(Double_t qfield,
2259 : Double_t step,
2260 : Double_t vect[7]) {
2261 : /******************************************************************
2262 : * *
2263 : * GEANT3 tracking routine in a constant field oriented *
2264 : * along axis 3 *
2265 : * Tracking is performed with a conventional *
2266 : * helix step method *
2267 : * *
2268 : * Authors R.Brun, M.Hansroul ********* *
2269 : * Rewritten V.Perevoztchikov *
2270 : * *
2271 : * Rewritten in C++ by I.Belikov *
2272 : * *
2273 : * qfield (kG) - particle charge times magnetic field *
2274 : * step (cm) - step length along the helix *
2275 : * vect[7](cm,GeV/c) - input/output x, y, z, px/p, py/p ,pz/p, p *
2276 : * *
2277 : ******************************************************************/
2278 : const Int_t ix=0, iy=1, iz=2, ipx=3, ipy=4, ipz=5, ipp=6;
2279 570186 : const Double_t kOvSqSix=TMath::Sqrt(1./6.);
2280 :
2281 285093 : Double_t cosx=vect[ipx], cosy=vect[ipy], cosz=vect[ipz];
2282 :
2283 285093 : Double_t rho = qfield*kB2C/vect[ipp];
2284 285093 : Double_t tet = rho*step;
2285 :
2286 : Double_t tsint, sintt, sint, cos1t;
2287 285093 : if (TMath::Abs(tet) > 0.03) {
2288 3827 : sint = TMath::Sin(tet);
2289 3827 : sintt = sint/tet;
2290 3827 : tsint = (tet - sint)/tet;
2291 3827 : Double_t t=TMath::Sin(0.5*tet);
2292 3827 : cos1t = 2*t*t/tet;
2293 3827 : } else {
2294 281266 : tsint = tet*tet/6.;
2295 281266 : sintt = (1.-tet*kOvSqSix)*(1.+tet*kOvSqSix); // 1.- tsint;
2296 281266 : sint = tet*sintt;
2297 281266 : cos1t = 0.5*tet;
2298 : }
2299 :
2300 285093 : Double_t f1 = step*sintt;
2301 285093 : Double_t f2 = step*cos1t;
2302 285093 : Double_t f3 = step*tsint*cosz;
2303 285093 : Double_t f4 = -tet*cos1t;
2304 : Double_t f5 = sint;
2305 :
2306 285093 : vect[ix] += f1*cosx - f2*cosy;
2307 285093 : vect[iy] += f1*cosy + f2*cosx;
2308 285093 : vect[iz] += f1*cosz + f3;
2309 :
2310 285093 : vect[ipx] += f4*cosx - f5*cosy;
2311 285093 : vect[ipy] += f4*cosy + f5*cosx;
2312 :
2313 285093 : }
2314 :
2315 : Bool_t AliExternalTrackParam::PropagateToBxByBz(Double_t xk, const Double_t b[3]) {
2316 : //----------------------------------------------------------------
2317 : // Extrapolate this track to the plane X=xk in the field b[].
2318 : //
2319 : // X [cm] is in the "tracking coordinate system" of this track.
2320 : // b[]={Bx,By,Bz} [kG] is in the Global coordidate system.
2321 : //----------------------------------------------------------------
2322 :
2323 560416 : Double_t dx=xk-fX;
2324 280492 : if (TMath::Abs(dx)<=kAlmost0) return kTRUE;
2325 279924 : if (TMath::Abs(fP[4])<=kAlmost0) return kFALSE;
2326 : // Do not propagate tracks outside the ALICE detector
2327 559848 : if (TMath::Abs(dx)>1e5 ||
2328 279924 : TMath::Abs(GetY())>1e5 ||
2329 279924 : TMath::Abs(GetZ())>1e5) {
2330 0 : AliWarning(Form("Anomalous track, target X:%f",xk));
2331 0 : Print();
2332 0 : return kFALSE;
2333 : }
2334 :
2335 279924 : Double_t crv=GetC(b[2]);
2336 279926 : if (TMath::Abs(b[2]) < kAlmost0Field) crv=0.;
2337 :
2338 279924 : Double_t x2r = crv*dx;
2339 279924 : Double_t f1=fP[2], f2=f1 + x2r;
2340 279924 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
2341 279959 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
2342 :
2343 :
2344 : // Estimate the covariance matrix
2345 279889 : Double_t &fP3=fP[3], &fP4=fP[4];
2346 : Double_t
2347 279889 : &fC00=fC[0],
2348 279889 : &fC10=fC[1], &fC11=fC[2],
2349 279889 : &fC20=fC[3], &fC21=fC[4], &fC22=fC[5],
2350 279889 : &fC30=fC[6], &fC31=fC[7], &fC32=fC[8], &fC33=fC[9],
2351 279889 : &fC40=fC[10], &fC41=fC[11], &fC42=fC[12], &fC43=fC[13], &fC44=fC[14];
2352 :
2353 279889 : Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
2354 :
2355 : //f = F - 1
2356 : /*
2357 : Double_t f02= dx/(r1*r1*r1); Double_t cc=crv/fP4;
2358 : Double_t f04=0.5*dx*dx/(r1*r1*r1); f04*=cc;
2359 : Double_t f12= dx*fP3*f1/(r1*r1*r1);
2360 : Double_t f14=0.5*dx*dx*fP3*f1/(r1*r1*r1); f14*=cc;
2361 : Double_t f13= dx/r1;
2362 : Double_t f24= dx; f24*=cc;
2363 : */
2364 279889 : Double_t rinv = 1./r1;
2365 279889 : Double_t r3inv = rinv*rinv*rinv;
2366 279889 : Double_t f24= x2r/fP4;
2367 279889 : Double_t f02= dx*r3inv;
2368 279889 : Double_t f04=0.5*f24*f02;
2369 279889 : Double_t f12= f02*fP3*f1;
2370 279889 : Double_t f14=0.5*f24*f02*fP3*f1;
2371 279889 : Double_t f13= dx*rinv;
2372 :
2373 : //b = C*ft
2374 279889 : Double_t b00=f02*fC20 + f04*fC40, b01=f12*fC20 + f14*fC40 + f13*fC30;
2375 279889 : Double_t b02=f24*fC40;
2376 279889 : Double_t b10=f02*fC21 + f04*fC41, b11=f12*fC21 + f14*fC41 + f13*fC31;
2377 279889 : Double_t b12=f24*fC41;
2378 279889 : Double_t b20=f02*fC22 + f04*fC42, b21=f12*fC22 + f14*fC42 + f13*fC32;
2379 279889 : Double_t b22=f24*fC42;
2380 279889 : Double_t b40=f02*fC42 + f04*fC44, b41=f12*fC42 + f14*fC44 + f13*fC43;
2381 279889 : Double_t b42=f24*fC44;
2382 279889 : Double_t b30=f02*fC32 + f04*fC43, b31=f12*fC32 + f14*fC43 + f13*fC33;
2383 279889 : Double_t b32=f24*fC43;
2384 :
2385 : //a = f*b = f*C*ft
2386 279889 : Double_t a00=f02*b20+f04*b40,a01=f02*b21+f04*b41,a02=f02*b22+f04*b42;
2387 279889 : Double_t a11=f12*b21+f14*b41+f13*b31,a12=f12*b22+f14*b42+f13*b32;
2388 279889 : Double_t a22=f24*b42;
2389 :
2390 : //F*C*Ft = C + (b + bt + a)
2391 279889 : fC00 += b00 + b00 + a00;
2392 279889 : fC10 += b10 + b01 + a01;
2393 279889 : fC20 += b20 + b02 + a02;
2394 279889 : fC30 += b30;
2395 279889 : fC40 += b40;
2396 279889 : fC11 += b11 + b11 + a11;
2397 279889 : fC21 += b21 + b12 + a12;
2398 279889 : fC31 += b31;
2399 279889 : fC41 += b41;
2400 279889 : fC22 += b22 + b22 + a22;
2401 279889 : fC32 += b32;
2402 279889 : fC42 += b42;
2403 :
2404 279889 : CheckCovariance();
2405 :
2406 : // Appoximate step length
2407 279889 : double dy2dx = (f1+f2)/(r1+r2);
2408 839667 : Double_t step = (TMath::Abs(x2r)<0.05) ? dx*TMath::Abs(r2 + f2*dy2dx) // chord
2409 1024 : : 2.*TMath::ASin(0.5*dx*TMath::Sqrt(1.+dy2dx*dy2dx)*crv)/crv; // arc
2410 279889 : step *= TMath::Sqrt(1.+ GetTgl()*GetTgl());
2411 :
2412 : // Get the track's (x,y,z) and (px,py,pz) in the Global System
2413 279889 : Double_t r[3]; GetXYZ(r);
2414 279889 : Double_t p[3]; GetPxPyPz(p);
2415 279889 : Double_t pp=GetP();
2416 279889 : p[0] /= pp;
2417 279889 : p[1] /= pp;
2418 279889 : p[2] /= pp;
2419 :
2420 :
2421 : // Rotate to the system where Bx=By=0.
2422 279889 : Double_t bt=TMath::Sqrt(b[0]*b[0] + b[1]*b[1]);
2423 : Double_t cosphi=1., sinphi=0.;
2424 559776 : if (bt > kAlmost0) {cosphi=b[0]/bt; sinphi=b[1]/bt;}
2425 279889 : Double_t bb=TMath::Sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]);
2426 : Double_t costet=1., sintet=0.;
2427 559778 : if (bb > kAlmost0) {costet=b[2]/bb; sintet=bt/bb;}
2428 279889 : Double_t vect[7];
2429 :
2430 279889 : vect[0] = costet*cosphi*r[0] + costet*sinphi*r[1] - sintet*r[2];
2431 279889 : vect[1] = -sinphi*r[0] + cosphi*r[1];
2432 279889 : vect[2] = sintet*cosphi*r[0] + sintet*sinphi*r[1] + costet*r[2];
2433 :
2434 279889 : vect[3] = costet*cosphi*p[0] + costet*sinphi*p[1] - sintet*p[2];
2435 279889 : vect[4] = -sinphi*p[0] + cosphi*p[1];
2436 279889 : vect[5] = sintet*cosphi*p[0] + sintet*sinphi*p[1] + costet*p[2];
2437 :
2438 279889 : vect[6] = pp;
2439 :
2440 :
2441 : // Do the helix step
2442 279889 : g3helx3(GetSign()*bb,step,vect);
2443 :
2444 :
2445 : // Rotate back to the Global System
2446 279889 : r[0] = cosphi*costet*vect[0] - sinphi*vect[1] + cosphi*sintet*vect[2];
2447 279889 : r[1] = sinphi*costet*vect[0] + cosphi*vect[1] + sinphi*sintet*vect[2];
2448 279889 : r[2] = -sintet*vect[0] + costet*vect[2];
2449 :
2450 279889 : p[0] = cosphi*costet*vect[3] - sinphi*vect[4] + cosphi*sintet*vect[5];
2451 279889 : p[1] = sinphi*costet*vect[3] + cosphi*vect[4] + sinphi*sintet*vect[5];
2452 279889 : p[2] = -sintet*vect[3] + costet*vect[5];
2453 :
2454 :
2455 : // Rotate back to the Tracking System
2456 279889 : Double_t cosalp = TMath::Cos(fAlpha);
2457 279889 : Double_t sinalp =-TMath::Sin(fAlpha);
2458 :
2459 : Double_t
2460 279889 : t = cosalp*r[0] - sinalp*r[1];
2461 279889 : r[1] = sinalp*r[0] + cosalp*r[1];
2462 279889 : r[0] = t;
2463 :
2464 279889 : t = cosalp*p[0] - sinalp*p[1];
2465 279889 : p[1] = sinalp*p[0] + cosalp*p[1];
2466 279889 : p[0] = t;
2467 :
2468 :
2469 : // Do the final correcting step to the target plane (linear approximation)
2470 279889 : Double_t x=r[0], y=r[1], z=r[2];
2471 279889 : if (TMath::Abs(dx) > kAlmost0) {
2472 279889 : if (TMath::Abs(p[0]) < kAlmost0) return kFALSE;
2473 279889 : dx = xk - r[0];
2474 279889 : x += dx;
2475 279889 : y += p[1]/p[0]*dx;
2476 279889 : z += p[2]/p[0]*dx;
2477 279889 : }
2478 :
2479 :
2480 : // Calculate the track parameters
2481 279889 : t=TMath::Sqrt(p[0]*p[0] + p[1]*p[1]);
2482 279889 : fX = x;
2483 279889 : fP[0] = y;
2484 279889 : fP[1] = z;
2485 279889 : fP[2] = p[1]/t;
2486 279889 : fP[3] = p[2]/t;
2487 279889 : fP[4] = GetSign()/(t*pp);
2488 :
2489 279889 : return kTRUE;
2490 560097 : }
2491 :
2492 : Bool_t AliExternalTrackParam::PropagateParamOnlyBxByBzTo(Double_t xk, const Double_t b[3]) {
2493 : //----------------------------------------------------------------
2494 : // Extrapolate this track params (w/o cov matrix) to the plane X=xk in the field b[].
2495 : //
2496 : // X [cm] is in the "tracking coordinate system" of this track.
2497 : // b[]={Bx,By,Bz} [kG] is in the Global coordidate system.
2498 : //----------------------------------------------------------------
2499 :
2500 10408 : Double_t dx=xk-fX;
2501 5204 : if (TMath::Abs(dx)<=kAlmost0) return kTRUE;
2502 5204 : if (TMath::Abs(fP[4])<=kAlmost0) return kFALSE;
2503 : // Do not propagate tracks outside the ALICE detector
2504 10408 : if (TMath::Abs(dx)>1e5 ||
2505 5204 : TMath::Abs(GetY())>1e5 ||
2506 5204 : TMath::Abs(GetZ())>1e5) {
2507 0 : AliWarning(Form("Anomalous track, target X:%f",xk));
2508 0 : Print();
2509 0 : return kFALSE;
2510 : }
2511 :
2512 5204 : Double_t crv=GetC(b[2]);
2513 5204 : if (TMath::Abs(b[2]) < kAlmost0Field) crv=0.;
2514 :
2515 5204 : Double_t x2r = crv*dx;
2516 5204 : Double_t f1=fP[2], f2=f1 + x2r;
2517 5204 : if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
2518 5204 : if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
2519 : //
2520 5204 : Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
2521 : //
2522 : // Appoximate step length
2523 5204 : double dy2dx = (f1+f2)/(r1+r2);
2524 15612 : Double_t step = (TMath::Abs(x2r)<0.05) ? dx*TMath::Abs(r2 + f2*dy2dx) // chord
2525 280 : : 2.*TMath::ASin(0.5*dx*TMath::Sqrt(1.+dy2dx*dy2dx)*crv)/crv; // arc
2526 5204 : step *= TMath::Sqrt(1.+ GetTgl()*GetTgl());
2527 :
2528 : // Get the track's (x,y,z) and (px,py,pz) in the Global System
2529 5204 : Double_t r[3]; GetXYZ(r);
2530 5204 : Double_t p[3]; GetPxPyPz(p);
2531 5204 : Double_t pp=GetP();
2532 5204 : p[0] /= pp;
2533 5204 : p[1] /= pp;
2534 5204 : p[2] /= pp;
2535 :
2536 : // Rotate to the system where Bx=By=0.
2537 5204 : Double_t bt=TMath::Sqrt(b[0]*b[0] + b[1]*b[1]);
2538 : Double_t cosphi=1., sinphi=0.;
2539 10408 : if (bt > kAlmost0) {cosphi=b[0]/bt; sinphi=b[1]/bt;}
2540 5204 : Double_t bb=TMath::Sqrt(b[0]*b[0] + b[1]*b[1] + b[2]*b[2]);
2541 : Double_t costet=1., sintet=0.;
2542 10408 : if (bb > kAlmost0) {costet=b[2]/bb; sintet=bt/bb;}
2543 5204 : Double_t vect[7];
2544 :
2545 5204 : vect[0] = costet*cosphi*r[0] + costet*sinphi*r[1] - sintet*r[2];
2546 5204 : vect[1] = -sinphi*r[0] + cosphi*r[1];
2547 5204 : vect[2] = sintet*cosphi*r[0] + sintet*sinphi*r[1] + costet*r[2];
2548 :
2549 5204 : vect[3] = costet*cosphi*p[0] + costet*sinphi*p[1] - sintet*p[2];
2550 5204 : vect[4] = -sinphi*p[0] + cosphi*p[1];
2551 5204 : vect[5] = sintet*cosphi*p[0] + sintet*sinphi*p[1] + costet*p[2];
2552 :
2553 5204 : vect[6] = pp;
2554 :
2555 : // Do the helix step
2556 5204 : g3helx3(GetSign()*bb,step,vect);
2557 :
2558 : // Rotate back to the Global System
2559 5204 : r[0] = cosphi*costet*vect[0] - sinphi*vect[1] + cosphi*sintet*vect[2];
2560 5204 : r[1] = sinphi*costet*vect[0] + cosphi*vect[1] + sinphi*sintet*vect[2];
2561 5204 : r[2] = -sintet*vect[0] + costet*vect[2];
2562 :
2563 5204 : p[0] = cosphi*costet*vect[3] - sinphi*vect[4] + cosphi*sintet*vect[5];
2564 5204 : p[1] = sinphi*costet*vect[3] + cosphi*vect[4] + sinphi*sintet*vect[5];
2565 5204 : p[2] = -sintet*vect[3] + costet*vect[5];
2566 :
2567 : // Rotate back to the Tracking System
2568 5204 : Double_t cosalp = TMath::Cos(fAlpha);
2569 5204 : Double_t sinalp =-TMath::Sin(fAlpha);
2570 :
2571 : Double_t
2572 5204 : t = cosalp*r[0] - sinalp*r[1];
2573 5204 : r[1] = sinalp*r[0] + cosalp*r[1];
2574 5204 : r[0] = t;
2575 :
2576 5204 : t = cosalp*p[0] - sinalp*p[1];
2577 5204 : p[1] = sinalp*p[0] + cosalp*p[1];
2578 5204 : p[0] = t;
2579 :
2580 : // Do the final correcting step to the target plane (linear approximation)
2581 5204 : Double_t x=r[0], y=r[1], z=r[2];
2582 5204 : if (TMath::Abs(dx) > kAlmost0) {
2583 5204 : if (TMath::Abs(p[0]) < kAlmost0) return kFALSE;
2584 5204 : dx = xk - r[0];
2585 5204 : x += dx;
2586 5204 : y += p[1]/p[0]*dx;
2587 5204 : z += p[2]/p[0]*dx;
2588 5204 : }
2589 :
2590 :
2591 : // Calculate the track parameters
2592 5204 : t=TMath::Sqrt(p[0]*p[0] + p[1]*p[1]);
2593 5204 : fX = x;
2594 5204 : fP[0] = y;
2595 5204 : fP[1] = z;
2596 5204 : fP[2] = p[1]/t;
2597 5204 : fP[3] = p[2]/t;
2598 5204 : fP[4] = GetSign()/(t*pp);
2599 :
2600 5204 : return kTRUE;
2601 10408 : }
2602 :
2603 :
2604 : Bool_t AliExternalTrackParam::Translate(Double_t *vTrasl,Double_t *covV){
2605 : //
2606 : //Translation: in the event mixing, the tracks can be shifted
2607 : //of the difference among primary vertices (vTrasl) and
2608 : //the covariance matrix is changed accordingly
2609 : //(covV = covariance of the primary vertex).
2610 : //Origin: "Romita, Rossella" <R.Romita@gsi.de>
2611 : //
2612 0 : TVector3 translation;
2613 : // vTrasl coordinates in the local system
2614 0 : translation.SetXYZ(vTrasl[0],vTrasl[1],vTrasl[2]);
2615 0 : translation.RotateZ(-fAlpha);
2616 0 : translation.GetXYZ(vTrasl);
2617 :
2618 : //compute the new x,y,z of the track
2619 0 : Double_t newX=fX-vTrasl[0];
2620 0 : Double_t newY=fP[0]-vTrasl[1];
2621 0 : Double_t newZ=fP[1]-vTrasl[2];
2622 :
2623 : //define the new parameters
2624 0 : Double_t newParam[5];
2625 0 : newParam[0]=newY;
2626 0 : newParam[1]=newZ;
2627 0 : newParam[2]=fP[2];
2628 0 : newParam[3]=fP[3];
2629 0 : newParam[4]=fP[4];
2630 :
2631 : // recompute the covariance matrix:
2632 : // 1. covV in the local system
2633 0 : Double_t cosRot=TMath::Cos(fAlpha), sinRot=TMath::Sin(fAlpha);
2634 0 : TMatrixD qQi(3,3);
2635 0 : qQi(0,0) = cosRot;
2636 0 : qQi(0,1) = sinRot;
2637 0 : qQi(0,2) = 0.;
2638 0 : qQi(1,0) = -sinRot;
2639 0 : qQi(1,1) = cosRot;
2640 0 : qQi(1,2) = 0.;
2641 0 : qQi(2,0) = 0.;
2642 0 : qQi(2,1) = 0.;
2643 0 : qQi(2,2) = 1.;
2644 0 : TMatrixD uUi(3,3);
2645 0 : uUi(0,0) = covV[0];
2646 0 : uUi(0,0) = covV[0];
2647 0 : uUi(1,0) = covV[1];
2648 0 : uUi(0,1) = covV[1];
2649 0 : uUi(2,0) = covV[3];
2650 0 : uUi(0,2) = covV[3];
2651 0 : uUi(1,1) = covV[2];
2652 0 : uUi(2,2) = covV[5];
2653 0 : uUi(1,2) = covV[4];
2654 0 : if(uUi.Determinant() <= 0.) {return kFALSE;}
2655 0 : TMatrixD uUiQi(uUi,TMatrixD::kMult,qQi);
2656 0 : TMatrixD m(qQi,TMatrixD::kTransposeMult,uUiQi);
2657 :
2658 : //2. compute the new covariance matrix of the track
2659 0 : Double_t sigmaXX=m(0,0);
2660 0 : Double_t sigmaXZ=m(2,0);
2661 0 : Double_t sigmaXY=m(1,0);
2662 0 : Double_t sigmaYY=GetSigmaY2()+m(1,1);
2663 0 : Double_t sigmaYZ=fC[1]+m(1,2);
2664 0 : Double_t sigmaZZ=fC[2]+m(2,2);
2665 0 : Double_t covarianceYY=sigmaYY + (-1.)*((sigmaXY*sigmaXY)/sigmaXX);
2666 0 : Double_t covarianceYZ=sigmaYZ-(sigmaXZ*sigmaXY/sigmaXX);
2667 0 : Double_t covarianceZZ=sigmaZZ-((sigmaXZ*sigmaXZ)/sigmaXX);
2668 :
2669 0 : Double_t newCov[15];
2670 0 : newCov[0]=covarianceYY;
2671 0 : newCov[1]=covarianceYZ;
2672 0 : newCov[2]=covarianceZZ;
2673 0 : for(Int_t i=3;i<15;i++){
2674 0 : newCov[i]=fC[i];
2675 : }
2676 :
2677 : // set the new parameters
2678 :
2679 0 : Set(newX,fAlpha,newParam,newCov);
2680 :
2681 : return kTRUE;
2682 0 : }
2683 :
2684 : void AliExternalTrackParam::CheckCovariance() {
2685 :
2686 : // This function forces the diagonal elements of the covariance matrix to be positive.
2687 : // In case the diagonal element is bigger than the maximal allowed value, it is set to
2688 : // the limit and the off-diagonal elements that correspond to it are set to zero.
2689 :
2690 1539102 : fC[0] = TMath::Abs(fC[0]);
2691 769551 : if (fC[0]>kC0max) {
2692 18 : double scl = TMath::Sqrt(kC0max/fC[0]);
2693 18 : fC[0] = kC0max;
2694 18 : fC[1] *= scl;
2695 18 : fC[3] *= scl;
2696 18 : fC[6] *= scl;
2697 18 : fC[10] *= scl;
2698 18 : }
2699 769551 : fC[2] = TMath::Abs(fC[2]);
2700 769551 : if (fC[2]>kC2max) {
2701 4 : double scl = TMath::Sqrt(kC2max/fC[2]);
2702 4 : fC[2] = kC2max;
2703 4 : fC[1] *= scl;
2704 4 : fC[4] *= scl;
2705 4 : fC[7] *= scl;
2706 4 : fC[11] *= scl;
2707 4 : }
2708 769551 : fC[5] = TMath::Abs(fC[5]);
2709 769551 : if (fC[5]>kC5max) {
2710 6 : double scl = TMath::Sqrt(kC5max/fC[5]);
2711 6 : fC[5] = kC5max;
2712 6 : fC[3] *= scl;
2713 6 : fC[4] *= scl;
2714 6 : fC[8] *= scl;
2715 6 : fC[12] *= scl;
2716 6 : }
2717 769551 : fC[9] = TMath::Abs(fC[9]);
2718 769551 : if (fC[9]>kC9max) {
2719 0 : double scl = TMath::Sqrt(kC9max/fC[9]);
2720 0 : fC[9] = kC9max;
2721 0 : fC[6] *= scl;
2722 0 : fC[7] *= scl;
2723 0 : fC[8] *= scl;
2724 0 : fC[13] *= scl;
2725 0 : }
2726 769551 : fC[14] = TMath::Abs(fC[14]);
2727 769551 : if (fC[14]>kC14max) {
2728 0 : double scl = TMath::Sqrt(kC14max/fC[14]);
2729 0 : fC[14] = kC14max;
2730 0 : fC[10] *= scl;
2731 0 : fC[11] *= scl;
2732 0 : fC[12] *= scl;
2733 0 : fC[13] *= scl;
2734 0 : }
2735 :
2736 : // The part below is used for tests and normally is commented out
2737 : // TMatrixDSym m(5);
2738 : // TVectorD eig(5);
2739 :
2740 : // m(0,0)=fC[0];
2741 : // m(1,0)=fC[1]; m(1,1)=fC[2];
2742 : // m(2,0)=fC[3]; m(2,1)=fC[4]; m(2,2)=fC[5];
2743 : // m(3,0)=fC[6]; m(3,1)=fC[7]; m(3,2)=fC[8]; m(3,3)=fC[9];
2744 : // m(4,0)=fC[10]; m(4,1)=fC[11]; m(4,2)=fC[12]; m(4,3)=fC[13]; m(4,4)=fC[14];
2745 :
2746 : // m(0,1)=m(1,0);
2747 : // m(0,2)=m(2,0); m(1,2)=m(2,1);
2748 : // m(0,3)=m(3,0); m(1,3)=m(3,1); m(2,3)=m(3,2);
2749 : // m(0,4)=m(4,0); m(1,4)=m(4,1); m(2,4)=m(4,2); m(3,4)=m(4,3);
2750 : // m.EigenVectors(eig);
2751 :
2752 : // // assert(eig(0)>=0 && eig(1)>=0 && eig(2)>=0 && eig(3)>=0 && eig(4)>=0);
2753 : // if (!(eig(0)>=0 && eig(1)>=0 && eig(2)>=0 && eig(3)>=0 && eig(4)>=0)) {
2754 : // AliWarning("Negative eigenvalues of the covariance matrix!");
2755 : // this->Print();
2756 : // eig.Print();
2757 : // }
2758 769551 : }
2759 :
2760 : Bool_t AliExternalTrackParam::ConstrainToVertex(const AliVVertex* vtx, Double_t b[3])
2761 : {
2762 : // Constrain TPC inner params constrained
2763 : //
2764 0 : if (!vtx)
2765 0 : return kFALSE;
2766 :
2767 0 : Double_t dz[2], cov[3];
2768 0 : if (!PropagateToDCABxByBz(vtx, b, 3, dz, cov))
2769 0 : return kFALSE;
2770 :
2771 0 : Double_t covar[6];
2772 0 : vtx->GetCovarianceMatrix(covar);
2773 :
2774 0 : Double_t p[2]= { fP[0] - dz[0], fP[1] - dz[1] };
2775 0 : Double_t c[3]= { covar[2], 0., covar[5] };
2776 :
2777 0 : Double_t chi2C = GetPredictedChi2(p,c);
2778 0 : if (chi2C>kVeryBig)
2779 0 : return kFALSE;
2780 :
2781 0 : if (!Update(p,c))
2782 0 : return kFALSE;
2783 :
2784 0 : return kTRUE;
2785 0 : }
2786 :
2787 : //___________________________________________________________________________________________
2788 : Bool_t AliExternalTrackParam::GetXatLabR(Double_t r,Double_t &x, Double_t bz, Int_t dir) const
2789 : {
2790 : // Get local X of the track position estimated at the radius lab radius r.
2791 : // The track curvature is accounted exactly
2792 : //
2793 : // The flag "dir" can be used to remove the ambiguity of which intersection to take (out of 2 possible)
2794 : // 0 - take the intersection closest to the current track position
2795 : // >0 - go along the track (increasing fX)
2796 : // <0 - go backward (decreasing fX)
2797 : //
2798 0 : const Double_t &fy=fP[0], &sn = fP[2];
2799 : const double kEps = 1.e-6;
2800 : //
2801 0 : double crv = GetC(bz);
2802 0 : if (TMath::Abs(crv)>kAlmost0) { // helix
2803 : // get center of the track circle
2804 0 : double tR = 1./crv; // track radius (for the moment signed)
2805 0 : double cs = TMath::Sqrt((1-sn)*(1+sn));
2806 0 : double x0 = fX - sn*tR;
2807 0 : double y0 = fy + cs*tR;
2808 0 : double r0 = TMath::Sqrt(x0*x0+y0*y0);
2809 : // printf("Xc:%+e Yc:%+e tR:%e r0:%e\n",x0,y0,tR,r0);
2810 : //
2811 0 : if (r0<=kAlmost0) return kFALSE; // the track is concentric to circle
2812 0 : tR = TMath::Abs(tR);
2813 : double tR2r0=1.,g=0,tmp=0;
2814 0 : if (TMath::Abs(tR-r0)>kEps) {
2815 0 : tR2r0 = tR/r0;
2816 0 : g = 0.5*(r*r/(r0*tR) - tR2r0 - 1./tR2r0);
2817 0 : tmp = 1.+g*tR2r0;
2818 0 : }
2819 : else {
2820 : tR2r0 = 1.0;
2821 0 : g = 0.5*r*r/(r0*tR) - 1;
2822 0 : tmp = 0.5*r*r/(r0*r0);
2823 : }
2824 0 : double det = (1.-g)*(1.+g);
2825 0 : if (det<0) return kFALSE; // does not reach raduis r
2826 0 : det = TMath::Sqrt(det);
2827 : //
2828 : // the intersection happens in 2 points: {x0+tR*C,y0+tR*S}
2829 : // with C=f*c0+-|s0|*det and S=f*s0-+c0 sign(s0)*det
2830 : // where s0 and c0 make direction for the circle center (=x0/r0 and y0/r0)
2831 : //
2832 0 : x = x0*tmp;
2833 0 : double y = y0*tmp;
2834 0 : if (TMath::Abs(y0)>kAlmost0) { // when y0==0 the x,y is unique
2835 0 : double dfx = tR2r0*TMath::Abs(y0)*det;
2836 0 : double dfy = tR2r0*x0*TMath::Sign(det,y0);
2837 0 : if (dir==0) { // chose the one which corresponds to smallest step
2838 0 : double delta = (x-fX)*dfx-(y-fy)*dfy; // the choice of + in C will lead to smaller step if delta<0
2839 0 : if (delta<0) x += dfx;
2840 0 : else x -= dfx;
2841 0 : }
2842 0 : else if (dir>0) { // along track direction: x must be > fX
2843 0 : x -= dfx; // try the smallest step (dfx is positive)
2844 0 : double dfeps = fX-x; // handle special case of very small step
2845 0 : if (dfeps<-kEps) return kTRUE;
2846 0 : if (TMath::Abs(dfeps)<kEps && // are we already in right r?
2847 0 : TMath::Abs(fX*fX+fy*fy - r*r)<kEps) return fX;
2848 0 : x += dfx+dfx;
2849 0 : if (x-fX>0) return kTRUE;
2850 0 : if (x-fX<-kEps) return kFALSE;
2851 0 : x = fX; // don't move
2852 0 : }
2853 : else { // backward: x must be < fX
2854 0 : x += dfx; // try the smallest step (dfx is positive)
2855 0 : double dfeps = x-fX; // handle special case of very small step
2856 0 : if (dfeps<-kEps) return kTRUE;
2857 0 : if (TMath::Abs(dfeps)<kEps && // are we already in right r?
2858 0 : TMath::Abs(fX*fX+fy*fy - r*r)<kEps) return fX;
2859 0 : x-=dfx+dfx;
2860 0 : if (x-fX<0) return kTRUE;
2861 0 : if (x-fX>kEps) return kFALSE;
2862 0 : x = fX; // don't move
2863 0 : }
2864 0 : }
2865 : else { // special case: track touching the circle just in 1 point
2866 0 : if ( (dir>0&&x<fX) || (dir<0&&x>fX) ) return kFALSE;
2867 : }
2868 0 : }
2869 : else { // this is a straight track
2870 0 : if (TMath::Abs(sn)>=kAlmost1) { // || to Y axis
2871 0 : double det = (r-fX)*(r+fX);
2872 0 : if (det<0) return kFALSE; // does not reach raduis r
2873 0 : x = fX;
2874 0 : if (dir==0) return kTRUE;
2875 0 : det = TMath::Sqrt(det);
2876 0 : if (dir>0) { // along the track direction
2877 0 : if (sn>0) {if (fy>det) return kFALSE;} // track is along Y axis and above the circle
2878 0 : else {if (fy<-det) return kFALSE;} // track is against Y axis amd belo the circle
2879 : }
2880 0 : else if(dir>0) { // agains track direction
2881 0 : if (sn>0) {if (fy<-det) return kFALSE;} // track is along Y axis
2882 0 : else if (fy>det) return kFALSE; // track is against Y axis
2883 : }
2884 0 : }
2885 0 : else if (TMath::Abs(sn)<=kAlmost0) { // || to X axis
2886 0 : double det = (r-fy)*(r+fy);
2887 0 : if (det<0) return kFALSE; // does not reach raduis r
2888 0 : det = TMath::Sqrt(det);
2889 0 : if (!dir) {
2890 0 : x = fX>0 ? det : -det; // choose the solution requiring the smalest step
2891 0 : return kTRUE;
2892 : }
2893 0 : else if (dir>0) { // along the track direction
2894 0 : if (fX > det) return kFALSE; // current point is in on the right from the circle
2895 0 : else if (fX <-det) x = -det; // on the left
2896 0 : else x = det; // within the circle
2897 : }
2898 : else { // against the track direction
2899 0 : if (fX <-det) return kFALSE;
2900 0 : else if (fX > det) x = det;
2901 0 : else x = -det;
2902 : }
2903 0 : }
2904 : else { // general case of straight line
2905 0 : double cs = TMath::Sqrt((1-sn)*(1+sn));
2906 0 : double xsyc = fX*sn-fy*cs;
2907 0 : double det = (r-xsyc)*(r+xsyc);
2908 0 : if (det<0) return kFALSE; // does not reach raduis r
2909 0 : det = TMath::Sqrt(det);
2910 0 : double xcys = fX*cs+fy*sn;
2911 0 : double t = -xcys;
2912 0 : if (dir==0) t += t>0 ? -det:det; // chose the solution requiring the smalest step
2913 0 : else if (dir>0) { // go in increasing fX direction. ( t+-det > 0)
2914 0 : if (t>=-det) t += -det; // take minimal step giving t>0
2915 0 : else return kFALSE; // both solutions have negative t
2916 0 : }
2917 : else { // go in increasing fX direction. (t+-det < 0)
2918 0 : if (t<det) t -= det; // take minimal step giving t<0
2919 0 : else return kFALSE; // both solutions have positive t
2920 : }
2921 0 : x = fX + cs*t;
2922 0 : }
2923 : }
2924 : //
2925 0 : return kTRUE;
2926 0 : }
2927 : //_________________________________________________________
2928 : Bool_t AliExternalTrackParam::GetXYZatR(Double_t xr,Double_t bz, Double_t *xyz, Double_t* alpSect) const
2929 : {
2930 : // This method has 3 modes of behaviour
2931 : // 1) xyz[3] array is provided but alpSect pointer is 0: calculate the position of track intersection
2932 : // with circle of radius xr and fill it in xyz array
2933 : // 2) alpSect pointer is provided: find alpha of the sector where the track reaches local coordinate xr
2934 : // Note that in this case xr is NOT the radius but the local coordinate.
2935 : // If the xyz array is provided, it will be filled by track lab coordinates at local X in this sector
2936 : // 3) Neither alpSect nor xyz pointers are provided: just check if the track reaches radius xr
2937 : //
2938 : //
2939 0 : double crv = GetC(bz);
2940 0 : if ( (TMath::Abs(bz))<kAlmost0Field ) crv=0.;
2941 0 : const double &fy = fP[0];
2942 0 : const double &fz = fP[1];
2943 0 : const double &sn = fP[2];
2944 0 : const double &tgl = fP[3];
2945 : //
2946 : // general circle parameterization:
2947 : // x = (r0+tR)cos(phi0) - tR cos(t+phi0)
2948 : // y = (r0+tR)sin(phi0) - tR sin(t+phi0)
2949 : // where qb is the sign of the curvature, tR is the track's signed radius and r0
2950 : // is the DCA of helix to origin
2951 : //
2952 0 : double tR = 1./crv; // track radius signed
2953 0 : double cs = TMath::Sqrt((1-sn)*(1+sn));
2954 0 : double x0 = fX - sn*tR; // helix center coordinates
2955 0 : double y0 = fy + cs*tR;
2956 0 : double phi0 = TMath::ATan2(y0,x0); // angle of PCA wrt to the origin
2957 0 : if (tR<0) phi0 += TMath::Pi();
2958 0 : if (phi0 > TMath::Pi()) phi0 -= 2.*TMath::Pi();
2959 0 : else if (phi0 <-TMath::Pi()) phi0 += 2.*TMath::Pi();
2960 0 : double cs0 = TMath::Cos(phi0);
2961 0 : double sn0 = TMath::Sin(phi0);
2962 0 : double r0 = x0*cs0 + y0*sn0 - tR; // DCA to origin
2963 0 : double r2R = 1.+r0/tR;
2964 : //
2965 : //
2966 0 : if (r2R<kAlmost0) return kFALSE; // helix is centered at the origin, no specific intersection with other concetric circle
2967 0 : if (!xyz && !alpSect) return kTRUE;
2968 0 : double xr2R = xr/tR;
2969 0 : double r2Ri = 1./r2R;
2970 : // the intersection cos(t) = [1 + (r0/tR+1)^2 - (r0/tR)^2]/[2(1+r0/tR)]
2971 0 : double cosT = 0.5*(r2R + (1-xr2R*xr2R)*r2Ri);
2972 0 : if ( TMath::Abs(cosT)>kAlmost1 ) {
2973 : // printf("Does not reach : %f %f\n",r0,tR);
2974 0 : return kFALSE; // track does not reach the radius xr
2975 : }
2976 : //
2977 0 : double t = TMath::ACos(cosT);
2978 0 : if (tR<0) t = -t;
2979 : // intersection point
2980 0 : double xyzi[3];
2981 0 : xyzi[0] = x0 - tR*TMath::Cos(t+phi0);
2982 0 : xyzi[1] = y0 - tR*TMath::Sin(t+phi0);
2983 0 : if (xyz) { // if postition is requested, then z is needed:
2984 0 : double t0 = TMath::ATan2(cs,-sn) - phi0;
2985 0 : double z0 = fz - t0*tR*tgl;
2986 0 : xyzi[2] = z0 + tR*t*tgl;
2987 0 : }
2988 0 : else xyzi[2] = 0;
2989 : //
2990 0 : Local2GlobalPosition(xyzi,fAlpha);
2991 : //
2992 0 : if (xyz) {
2993 0 : xyz[0] = xyzi[0];
2994 0 : xyz[1] = xyzi[1];
2995 0 : xyz[2] = xyzi[2];
2996 0 : }
2997 : //
2998 0 : if (alpSect) {
2999 : double &alp = *alpSect;
3000 : // determine the sector of crossing
3001 0 : double phiPos = TMath::Pi()+TMath::ATan2(-xyzi[1],-xyzi[0]);
3002 0 : int sect = ((Int_t)(phiPos*TMath::RadToDeg()))/20;
3003 0 : alp = TMath::DegToRad()*(20*sect+10);
3004 0 : double x2r,f1,f2,r1,r2,dx,dy2dx,yloc=0, ylocMax = xr*TMath::Tan(TMath::Pi()/18); // min max Y within sector at given X
3005 : //
3006 0 : while(1) {
3007 0 : Double_t ca=TMath::Cos(alp-fAlpha), sa=TMath::Sin(alp-fAlpha);
3008 0 : if ((cs*ca+sn*sa)<0) {
3009 0 : AliDebug(1,Form("Rotation to target sector impossible: local cos(phi) would become %.2f",cs*ca+sn*sa));
3010 0 : return kFALSE;
3011 : }
3012 : //
3013 0 : f1 = sn*ca - cs*sa;
3014 0 : if (TMath::Abs(f1) >= kAlmost1) {
3015 0 : AliDebug(1,Form("Rotation to target sector impossible: local sin(phi) would become %.2f",f1));
3016 0 : return kFALSE;
3017 : }
3018 : //
3019 0 : double tmpX = fX*ca + fy*sa;
3020 0 : double tmpY = -fX*sa + fy*ca;
3021 : //
3022 : // estimate Y at X=xr
3023 0 : dx=xr-tmpX;
3024 0 : x2r = crv*dx;
3025 0 : f2=f1 + x2r;
3026 0 : if (TMath::Abs(f2) >= kAlmost1) {
3027 0 : AliDebug(1,Form("Propagation in target sector failed ! %.10e",f2));
3028 0 : return kFALSE;
3029 : }
3030 0 : r1 = TMath::Sqrt((1.-f1)*(1.+f1));
3031 0 : r2 = TMath::Sqrt((1.-f2)*(1.+f2));
3032 0 : dy2dx = (f1+f2)/(r1+r2);
3033 0 : yloc = tmpY + dx*dy2dx;
3034 0 : if (yloc>ylocMax) {alp += 2*TMath::Pi()/18; sect++;}
3035 0 : else if (yloc<-ylocMax) {alp -= 2*TMath::Pi()/18; sect--;}
3036 0 : else break;
3037 0 : if (alp >= TMath::Pi()) alp -= 2*TMath::Pi();
3038 0 : else if (alp < -TMath::Pi()) alp += 2*TMath::Pi();
3039 : // if (sect>=18) sect = 0;
3040 : // if (sect<=0) sect = 17;
3041 0 : }
3042 : //
3043 : // if alpha was requested, then recalculate the position at intersection in sector
3044 0 : if (xyz) {
3045 0 : xyz[0] = xr;
3046 0 : xyz[1] = yloc;
3047 0 : if (TMath::Abs(x2r)<0.05) xyz[2] = fz + dx*(r2 + f2*dy2dx)*tgl;
3048 : else {
3049 : // for small dx/R the linear apporximation of the arc by the segment is OK,
3050 : // but at large dx/R the error is very large and leads to incorrect Z propagation
3051 : // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
3052 : // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
3053 : // Similarly, the rotation angle in linear in dx only for dx<<R
3054 0 : double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
3055 0 : double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
3056 0 : xyz[2] = fz + rot/crv*tgl;
3057 : }
3058 0 : Local2GlobalPosition(xyz,alp);
3059 0 : }
3060 0 : }
3061 0 : return kTRUE;
3062 : //
3063 0 : }
3064 :
3065 :
3066 : Double_t AliExternalTrackParam::GetParameterAtRadius(Double_t r, Double_t bz, Int_t parType) const
3067 : {
3068 : //
3069 : // Get track parameters at the radius of interest.
3070 : // Given function is aimed to be used to interactivelly (tree->Draw())
3071 : // access track properties at different radii
3072 : //
3073 : // TO BE USED WITH SPECICAL CARE -
3074 : // it is aimed to be used for rough calculation as constant field and
3075 : // no correction for material is used
3076 : //
3077 : // r - radius of interest
3078 : // bz - magentic field
3079 : // retun values dependens on parType:
3080 : // parType = 0 -gx
3081 : // parType = 1 -gy
3082 : // parType = 2 -gz
3083 : //
3084 : // parType = 3 -pgx
3085 : // parType = 4 -pgy
3086 : // parType = 5 -pgz
3087 : //
3088 : // parType = 6 - r
3089 : // parType = 7 - global position phi
3090 : // parType = 8 - global direction phi
3091 : // parType = 9 - direction phi- positionphi
3092 0 : if (parType<0) {
3093 : parType=-1;
3094 0 : return 0;
3095 : }
3096 0 : Double_t xyz[3];
3097 0 : Double_t pxyz[3];
3098 0 : Double_t localX=0;
3099 0 : Bool_t res = GetXatLabR(r,localX,bz,1);
3100 0 : if (!res) {
3101 : parType=-1;
3102 0 : return 0;
3103 : }
3104 : //
3105 : // position parameters
3106 : //
3107 0 : GetXYZAt(localX,bz,xyz);
3108 0 : if (parType<3) {
3109 0 : return xyz[parType];
3110 : }
3111 :
3112 0 : if (parType==6) return TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
3113 0 : if (parType==7) return TMath::ATan2(xyz[1],xyz[0]);
3114 : //
3115 : // momenta parameters
3116 : //
3117 0 : GetPxPyPzAt(localX,bz,pxyz);
3118 0 : if (parType==8) return TMath::ATan2(pxyz[1],pxyz[0]);
3119 0 : if (parType==9) {
3120 0 : Double_t diff = TMath::ATan2(pxyz[1],pxyz[0])-TMath::ATan2(xyz[1],xyz[0]);
3121 0 : if (diff>TMath::Pi()) diff-=TMath::TwoPi();
3122 0 : if (diff<-TMath::Pi()) diff+=TMath::TwoPi();
3123 : return diff;
3124 : }
3125 0 : if (parType>=3&&parType<6) {
3126 0 : return pxyz[parType%3];
3127 : }
3128 0 : return 0;
3129 0 : }
|