2 // **************************************************************************
3 // This file is property of and copyright by the ALICE HLT Project *
4 // ALICE Experiment at CERN, All rights reserved. *
6 // Primary Authors: Sergey Gorbunov <sergey.gorbunov@kip.uni-heidelberg.de> *
7 // Ivan Kisel <kisel@kip.uni-heidelberg.de> *
8 // for The ALICE HLT Project. *
10 // Permission to use, copy, modify and distribute this software and its *
11 // documentation strictly for non-commercial purposes is hereby granted *
12 // without fee, provided that the above copyright notice appears in all *
13 // copies and that both the copyright notice and this permission notice *
14 // appear in the supporting documentation. The authors make no claims *
15 // about the suitability of this software for any purpose. It is *
16 // provided "as is" without express or implied warranty. *
18 //***************************************************************************
21 #include "AliHLTTPCCATrackParam.h"
22 #include "AliHLTTPCCAMath.h"
23 #include "AliHLTTPCCATrackLinearisation.h"
28 // kCLight = 0.000299792458;
29 // Kappa = -Bz*kCLight*QPt;
30 // R = 1/TMath::Abs(Kappa);
31 // Xc = X - sin(Phi)/Kappa;
32 // Yc = Y + cos(Phi)/Kappa;
35 GPUd() float AliHLTTPCCATrackParam::GetDist2( const AliHLTTPCCATrackParam &t ) const
37 // get squared distance between tracks
39 float dx = GetX() - t.GetX();
40 float dy = GetY() - t.GetY();
41 float dz = GetZ() - t.GetZ();
42 return dx*dx + dy*dy + dz*dz;
45 GPUd() float AliHLTTPCCATrackParam::GetDistXZ2( const AliHLTTPCCATrackParam &t ) const
47 // get squared distance between tracks in X&Z
49 float dx = GetX() - t.GetX();
50 float dz = GetZ() - t.GetZ();
55 GPUd() float AliHLTTPCCATrackParam::GetS( float x, float y, float Bz ) const
57 //* Get XY path length to the given point
59 float k = GetKappa( Bz );
60 float ex = GetCosPhi();
61 float ey = GetSinPhi();
64 float dS = x * ex + y * ey;
65 if ( CAMath::Abs( k ) > 1.e-4 ) dS = CAMath::ATan2( k * dS, 1 + k * ( x * ey - y * ex ) ) / k;
69 GPUd() void AliHLTTPCCATrackParam::GetDCAPoint( float x, float y, float z,
70 float &xp, float &yp, float &zp,
73 //* Get the track point closest to the (x,y,z)
77 float k = GetKappa( Bz );
78 float ex = GetCosPhi();
79 float ey = GetSinPhi();
82 float ax = dx * k + ey;
83 float ay = dy * k - ex;
84 float a = sqrt( ax * ax + ay * ay );
85 xp = x0 + ( dx - ey * ( ( dx * dx + dy * dy ) * k - 2 * ( -dx * ey + dy * ex ) ) / ( a + 1 ) ) / a;
86 yp = y0 + ( dy + ex * ( ( dx * dx + dy * dy ) * k - 2 * ( -dx * ey + dy * ex ) ) / ( a + 1 ) ) / a;
87 float s = GetS( x, y, Bz );
88 zp = GetZ() + GetDzDs() * s;
89 if ( CAMath::Abs( k ) > 1.e-2 ) {
90 float dZ = CAMath::Abs( GetDzDs() * CAMath::TwoPi() / k );
92 zp += CAMath::Nint( ( z - zp ) / dZ ) * dZ;
99 //* Transport routines
103 GPUd() bool AliHLTTPCCATrackParam::TransportToX( float x, AliHLTTPCCATrackLinearisation &t0, float Bz, float maxSinPhi, float *DL )
105 //* Transport the track parameters to X=x, using linearization at t0, and the field value Bz
106 //* maxSinPhi is the max. allowed value for |t0.SinPhi()|
107 //* linearisation of trajectory t0 is also transported to X=x,
111 float ex = t0.CosPhi();
112 float ey = t0.SinPhi();
113 float k =-t0.QPt() * Bz;
116 float ey1 = k * dx + ey;
119 // check for intersection with X=x
121 if ( CAMath::Abs( ey1 ) > maxSinPhi ) return 0;
123 ex1 = CAMath::Sqrt( 1 - ey1 * ey1 );
124 if ( ex < 0 ) ex1 = -ex1;
130 if ( CAMath::Abs( cc ) < 1.e-4 || CAMath::Abs( ex ) < 1.e-4 || CAMath::Abs( ex1 ) < 1.e-4 ) return 0;
132 float tg = ss / cc; // tan((phi1+phi)/2)
135 float dl = dx * CAMath::Sqrt( 1 + tg * tg );
137 if ( cc < 0 ) dl = -dl;
138 float dSin = dl * k / 2;
139 if ( dSin > 1 ) dSin = 1;
140 if ( dSin < -1 ) dSin = -1;
141 float dS = ( CAMath::Abs( k ) > 1.e-4 ) ? ( 2 * CAMath::ASin( dSin ) / k ) : dl;
142 float dz = dS * t0.DzDs();
144 if ( DL ) *DL = -dS * CAMath::Sqrt( 1 + t0.DzDs() * t0.DzDs() );
148 float ex1i = 1. / ex1;
152 GetPar(2) - t0.SinPhi(),
153 GetPar(3) - t0.DzDs(),
157 //float H0[5] = { 1,0, h2, 0, h4 };
158 //float H1[5] = { 0, 1, 0, dS, 0 };
159 //float H2[5] = { 0, 0, 1, 0, dxBz };
160 //float H3[5] = { 0, 0, 0, 1, 0 };
161 //float H4[5] = { 0, 0, 0, 0, 1 };
163 float h2 = dx * ( 1 + ey * ey1 + ex * ex1 ) * exi * ex1i * cci;
164 float h4 = dx2 * ( cc + ss * ey1 * ex1i ) * cci * cci * (-Bz);
165 float dxBz = dx * (-Bz);
171 SetPar(0, Y() + dy + h2 * d[2] + h4 * d[4]);
172 SetPar(1, Z() + dz + dS * d[3]);
173 SetPar(2, t0.SinPhi() + d[2] + dxBz * d[4]);
191 fC[0] = ( c00 + h2 * h2 * c22 + h4 * h4 * c44
192 + 2 * ( h2 * c20 + h4 * c40 + h2 * h4 * c42 ) );
194 fC[1] = c10 + h2 * c21 + h4 * c41 + dS * ( c30 + h2 * c32 + h4 * c43 );
195 fC[2] = c11 + 2 * dS * c31 + dS * dS * c33;
197 fC[3] = c20 + h2 * c22 + h4 * c42 + dxBz * ( c40 + h2 * c42 + h4 * c44 );
198 fC[4] = c21 + dS * c32 + dxBz * ( c41 + dS * c43 );
199 fC[5] = c22 + 2 * dxBz * c42 + dxBz * dxBz * c44;
201 fC[6] = c30 + h2 * c32 + h4 * c43;
202 fC[7] = c31 + dS * c33;
203 fC[8] = c32 + dxBz * c43;
206 fC[10] = c40 + h2 * c42 + h4 * c44;
207 fC[11] = c41 + dS * c43;
208 fC[12] = c42 + dxBz * c44;
216 GPUd() bool AliHLTTPCCATrackParam::TransportToX( float x, float sinPhi0, float cosPhi0, float Bz, float maxSinPhi )
218 //* Transport the track parameters to X=x, using linearization at phi0 with 0 curvature,
219 //* and the field value Bz
220 //* maxSinPhi is the max. allowed value for |t0.SinPhi()|
221 //* linearisation of trajectory t0 is also transported to X=x,
229 if ( CAMath::Abs( ex ) < 1.e-4 ) return 0;
232 float dxBz = dx * (-Bz);
234 float h2 = dS * exi * exi;
235 float h4 = .5 * h2 * dxBz;
237 //float H0[5] = { 1,0, h2, 0, h4 };
238 //float H1[5] = { 0, 1, 0, dS, 0 };
239 //float H2[5] = { 0, 0, 1, 0, dxBz };
240 //float H3[5] = { 0, 0, 0, 1, 0 };
241 //float H4[5] = { 0, 0, 0, 0, 1 };
243 float sinPhi = SinPhi() + dxBz * QPt();
244 if ( maxSinPhi > 0 && CAMath::Abs( sinPhi ) > maxSinPhi ) return 0;
247 SetPar(0, GetPar(0) + dS * ey + h2 * ( SinPhi() - ey ) + h4 * QPt());
248 SetPar(1, GetPar(1) + dS * DzDs());
269 fC[0] = ( c00 + h2 * h2 * c22 + h4 * h4 * c44
270 + 2 * ( h2 * c20 + h4 * c40 + h2 * h4 * c42 ) );
272 fC[1] = c10 + h2 * c21 + h4 * c41 + dS * ( c30 + h2 * c32 + h4 * c43 );
273 fC[2] = c11 + 2 * dS * c31 + dS * dS * c33;
275 fC[3] = c20 + h2 * c22 + h4 * c42 + dxBz * ( c40 + h2 * c42 + h4 * c44 );
276 fC[4] = c21 + dS * c32 + dxBz * ( c41 + dS * c43 );
277 fC[5] = c22 + 2 * dxBz * c42 + dxBz * dxBz * c44;
279 fC[6] = c30 + h2 * c32 + h4 * c43;
280 fC[7] = c31 + dS * c33;
281 fC[8] = c32 + dxBz * c43;
284 fC[10] = c40 + h2 * c42 + h4 * c44;
285 fC[11] = c41 + dS * c43;
286 fC[12] = c42 + dxBz * c44;
298 GPUd() bool AliHLTTPCCATrackParam::TransportToX( float x, float Bz, float maxSinPhi )
300 //* Transport the track parameters to X=x
302 AliHLTTPCCATrackLinearisation t0( *this );
304 return TransportToX( x, t0, Bz, maxSinPhi );
309 GPUd() bool AliHLTTPCCATrackParam::TransportToXWithMaterial( float x, AliHLTTPCCATrackLinearisation &t0, AliHLTTPCCATrackFitParam &par, float Bz, float maxSinPhi )
311 //* Transport the track parameters to X=x taking into account material budget
313 const float kRho = 1.025e-3;//0.9e-3;
314 const float kRadLen = 29.532;//28.94;
315 const float kRhoOverRadLen = kRho / kRadLen;
318 if ( !TransportToX( x, t0, Bz, maxSinPhi, &dl ) ) return 0;
320 CorrectForMeanMaterial( dl*kRhoOverRadLen, dl*kRho, par );
325 GPUd() bool AliHLTTPCCATrackParam::TransportToXWithMaterial( float x, AliHLTTPCCATrackFitParam &par, float Bz, float maxSinPhi )
327 //* Transport the track parameters to X=x taking into account material budget
329 AliHLTTPCCATrackLinearisation t0( *this );
330 return TransportToXWithMaterial( x, t0, par, Bz, maxSinPhi );
333 GPUd() bool AliHLTTPCCATrackParam::TransportToXWithMaterial( float x, float Bz, float maxSinPhi )
335 //* Transport the track parameters to X=x taking into account material budget
337 AliHLTTPCCATrackFitParam par;
338 CalculateFitParameters( par );
339 return TransportToXWithMaterial( x, par, Bz, maxSinPhi );
344 //* Multiple scattering and energy losses
348 float AliHLTTPCCATrackParam::BetheBlochGeant( float bg2,
356 // This is the parameterization of the Bethe-Bloch formula inspired by Geant.
358 // bg2 - (beta*gamma)^2
359 // kp0 - density [g/cm^3]
360 // kp1 - density effect first junction point
361 // kp2 - density effect second junction point
362 // kp3 - mean excitation energy [GeV]
365 // The default values for the kp* parameters are for silicon.
366 // The returned value is in [GeV/(g/cm^2)].
369 const float mK = 0.307075e-3; // [GeV*cm^2/g]
370 const float me = 0.511e-3; // [GeV/c^2]
371 const float rho = kp0;
372 const float x0 = kp1 * 2.303;
373 const float x1 = kp2 * 2.303;
374 const float mI = kp3;
375 const float mZA = kp4;
376 const float maxT = 2 * me * bg2; // neglecting the electron mass
380 const float x = 0.5 * AliHLTTPCCAMath::Log( bg2 );
381 const float lhwI = AliHLTTPCCAMath::Log( 28.816 * 1e-9 * AliHLTTPCCAMath::Sqrt( rho * mZA ) / mI );
384 } else if ( x > x0 ) {
385 const float r = ( x1 - x ) / ( x1 - x0 );
386 d2 = lhwI + x - 0.5 + ( 0.5 - lhwI - x0 ) * r * r * r;
389 return mK*mZA*( 1 + bg2 ) / bg2*( 0.5*AliHLTTPCCAMath::Log( 2*me*bg2*maxT / ( mI*mI ) ) - bg2 / ( 1 + bg2 ) - d2 );
392 float AliHLTTPCCATrackParam::BetheBlochSolid( float bg )
394 //------------------------------------------------------------------
395 // This is an approximation of the Bethe-Bloch formula,
396 // reasonable for solid materials.
397 // All the parameters are, in fact, for Si.
398 // The returned value is in [GeV]
399 //------------------------------------------------------------------
401 return BetheBlochGeant( bg );
404 float AliHLTTPCCATrackParam::BetheBlochGas( float bg )
406 //------------------------------------------------------------------
407 // This is an approximation of the Bethe-Bloch formula,
408 // reasonable for gas materials.
409 // All the parameters are, in fact, for Ne.
410 // The returned value is in [GeV]
411 //------------------------------------------------------------------
413 const float rho = 0.9e-3;
416 const float mI = 140.e-9;
417 const float mZA = 0.49555;
419 return BetheBlochGeant( bg, rho, x0, x1, mI, mZA );
425 GPUd() float AliHLTTPCCATrackParam::ApproximateBetheBloch( float beta2 )
427 //------------------------------------------------------------------
428 // This is an approximation of the Bethe-Bloch formula with
429 // the density effect taken into account at beta*gamma > 3.5
430 // (the approximation is reasonable only for solid materials)
431 //------------------------------------------------------------------
432 if ( beta2 >= 1 ) return 0;
434 if ( beta2 / ( 1 - beta2 ) > 3.5*3.5 )
435 return 0.153e-3 / beta2*( log( 3.5*5940 ) + 0.5*log( beta2 / ( 1 - beta2 ) ) - beta2 );
436 return 0.153e-3 / beta2*( log( 5940*beta2 / ( 1 - beta2 ) ) - beta2 );
440 GPUd() void AliHLTTPCCATrackParam::CalculateFitParameters( AliHLTTPCCATrackFitParam &par, float mass )
444 float qpt = GetPar(4);
445 if( fC[14]>=1. ) qpt = 1./0.35;
447 float p2 = ( 1. + GetPar(3) * GetPar(3) );
448 float k2 = qpt * qpt;
449 float mass2 = mass * mass;
450 float beta2 = p2 / ( p2 + mass2 * k2 );
452 float pp2 = ( k2 > 1.e-8 ) ? p2 / k2 : 10000; // impuls 2
454 //par.fBethe = BetheBlochGas( pp2/mass2);
455 par.fBethe = ApproximateBetheBloch( pp2 / mass2 );
456 par.fE = CAMath::Sqrt( pp2 + mass2 );
457 par.fTheta2 = 14.1 * 14.1 / ( beta2 * pp2 * 1e6 );
458 par.fEP2 = par.fE / pp2;
460 // Approximate energy loss fluctuation (M.Ivanov)
462 const float knst = 0.07; // To be tuned.
463 par.fSigmadE2 = knst * par.fEP2 * qpt;
464 par.fSigmadE2 = par.fSigmadE2 * par.fSigmadE2;
466 par.fK22 = ( 1. + GetPar(3) * GetPar(3) );
467 par.fK33 = par.fK22 * par.fK22;
469 par.fK44 = GetPar(3) * GetPar(3) * k2;
474 GPUd() bool AliHLTTPCCATrackParam::CorrectForMeanMaterial( float xOverX0, float xTimesRho, const AliHLTTPCCATrackFitParam &par )
476 //------------------------------------------------------------------
477 // This function corrects the track parameters for the crossed material.
478 // "xOverX0" - X/X0, the thickness in units of the radiation length.
479 // "xTimesRho" - is the product length*density (g/cm^2).
480 //------------------------------------------------------------------
484 float &fC40 = fC[10];
485 float &fC41 = fC[11];
486 float &fC42 = fC[12];
487 float &fC43 = fC[13];
488 float &fC44 = fC[14];
490 //Energy losses************************
492 float dE = par.fBethe * xTimesRho;
493 if ( CAMath::Abs( dE ) > 0.3*par.fE ) return 0; //30% energy loss is too much!
494 float corr = ( 1. - par.fEP2 * dE );
495 if ( corr < 0.3 || corr > 1.3 ) return 0;
497 SetPar(4, GetPar(4) * corr);
503 fC44 += par.fSigmadE2 * CAMath::Abs( dE );
505 //Multiple scattering******************
507 float theta2 = par.fTheta2 * CAMath::Abs( xOverX0 );
508 fC22 += theta2 * par.fK22 * (1.-GetPar(2))*(1.+GetPar(2));
509 fC33 += theta2 * par.fK33;
510 fC43 += theta2 * par.fK43;
511 fC44 += theta2 * par.fK44;
522 GPUd() bool AliHLTTPCCATrackParam::Rotate( float alpha, float maxSinPhi )
524 //* Rotate the coordinate system in XY on the angle alpha
526 float cA = CAMath::Cos( alpha );
527 float sA = CAMath::Sin( alpha );
528 float x = X(), y = Y(), sP = SinPhi(), cP = GetCosPhi();
529 float cosPhi = cP * cA + sP * sA;
530 float sinPhi = -cP * sA + sP * cA;
532 if ( CAMath::Abs( sinPhi ) > maxSinPhi || CAMath::Abs( cosPhi ) < 1.e-2 || CAMath::Abs( cP ) < 1.e-2 ) return 0;
534 float j0 = cP / cosPhi;
535 float j2 = cosPhi / cP;
538 SetY( -x*sA + y*cA );
539 SetSignCosPhi( cosPhi );
543 //float J[5][5] = { { j0, 0, 0, 0, 0 }, // Y
544 // { 0, 1, 0, 0, 0 }, // Z
545 // { 0, 0, j2, 0, 0 }, // SinPhi
546 // { 0, 0, 0, 1, 0 }, // DzDs
547 // { 0, 0, 0, 0, 1 } }; // Kappa
548 //cout<<"alpha="<<alpha<<" "<<x<<" "<<y<<" "<<sP<<" "<<cP<<" "<<j0<<" "<<j2<<endl;
549 //cout<<" "<<fC[0]<<" "<<fC[1]<<" "<<fC[6]<<" "<<fC[10]<<" "<<fC[4]<<" "<<fC[5]<<" "<<fC[8]<<" "<<fC[12]<<endl;
561 //cout<<" "<<fC[0]<<" "<<fC[1]<<" "<<fC[6]<<" "<<fC[10]<<" "<<fC[4]<<" "<<fC[5]<<" "<<fC[8]<<" "<<fC[12]<<endl;
565 GPUd() bool AliHLTTPCCATrackParam::Rotate( float alpha, AliHLTTPCCATrackLinearisation &t0, float maxSinPhi )
567 //* Rotate the coordinate system in XY on the angle alpha
569 float cA = CAMath::Cos( alpha );
570 float sA = CAMath::Sin( alpha );
571 float x0 = X(), y0 = Y(), sP = t0.SinPhi(), cP = t0.CosPhi();
572 float cosPhi = cP * cA + sP * sA;
573 float sinPhi = -cP * sA + sP * cA;
575 if ( CAMath::Abs( sinPhi ) > maxSinPhi || CAMath::Abs( cosPhi ) < 1.e-2 || CAMath::Abs( cP ) < 1.e-2 ) return 0;
577 //float J[5][5] = { { j0, 0, 0, 0, 0 }, // Y
578 // { 0, 1, 0, 0, 0 }, // Z
579 // { 0, 0, j2, 0, 0 }, // SinPhi
580 // { 0, 0, 0, 1, 0 }, // DzDs
581 // { 0, 0, 0, 0, 1 } }; // Kappa
583 float j0 = cP / cosPhi;
584 float j2 = cosPhi / cP;
585 float d[2] = {Y() - y0, SinPhi() - sP};
587 SetX( x0*cA + y0*sA );
588 SetY( -x0*sA + y0*cA + j0*d[0] );
589 t0.SetCosPhi( cosPhi );
590 t0.SetSinPhi( sinPhi );
592 SetSinPhi( sinPhi + j2*d[1] );
609 GPUd() bool AliHLTTPCCATrackParam::Filter( float y, float z, float err2Y, float err2Z, float maxSinPhi )
611 //* Add the y,z measurement with the Kalman filter
627 if ( err2Y < 1.e-8 || err2Z < 1.e-8 ) return 0;
629 float mS0 = 1. / err2Y;
630 float mS2 = 1. / err2Z;
634 float k00, k11, k20, k31, k40;
643 float sinPhi = GetPar(2) + k20 * z0 ;
645 if ( maxSinPhi > 0 && CAMath::Abs( sinPhi ) >= maxSinPhi ) return 0;
648 fChi2 += mS0 * z0 * z0 + mS2 * z1 * z1 ;
650 SetPar(0, GetPar(0) + k00 * z0);
651 SetPar(1, GetPar(1) + k11 * z1);
653 SetPar(3, GetPar(3) + k31 * z1);
654 SetPar(4, GetPar(4) + k40 * z0);
656 fC[ 0] -= k00 * c00 ;
657 fC[ 3] -= k20 * c00 ;
658 fC[ 5] -= k20 * c20 ;
659 fC[10] -= k40 * c00 ;
660 fC[12] -= k40 * c20 ;
661 fC[14] -= k40 * c40 ;
663 fC[ 2] -= k11 * c11 ;
664 fC[ 7] -= k31 * c11 ;
665 fC[ 9] -= k31 * c31 ;
670 GPUd() bool AliHLTTPCCATrackParam::CheckNumericalQuality() const
672 //* Check that the track parameters and covariance matrix are reasonable
674 bool ok = AliHLTTPCCAMath::Finite( GetX() ) && AliHLTTPCCAMath::Finite( fSignCosPhi ) && AliHLTTPCCAMath::Finite( fChi2 ) && AliHLTTPCCAMath::Finite( fNDF );
676 const float *c = Cov();
677 for ( int i = 0; i < 15; i++ ) ok = ok && AliHLTTPCCAMath::Finite( c[i] );
678 for ( int i = 0; i < 5; i++ ) ok = ok && AliHLTTPCCAMath::Finite( Par()[i] );
680 if ( c[0] <= 0 || c[2] <= 0 || c[5] <= 0 || c[9] <= 0 || c[14] <= 0 ) ok = 0;
681 if ( c[0] > 5. || c[2] > 5. || c[5] > 2. || c[9] > 2
682 //|| ( CAMath::Abs( QPt() ) > 1.e-2 && c[14] > 2. )
685 if ( CAMath::Abs( SinPhi() ) > .99 ) ok = 0;
686 if ( CAMath::Abs( QPt() ) > 1. / 0.05 ) ok = 0;
689 && ( c[1]*c[1]<=c[2]*c[0] )
690 && ( c[3]*c[3]<=c[5]*c[0] )
691 && ( c[4]*c[4]<=c[5]*c[2] )
692 && ( c[6]*c[6]<=c[9]*c[0] )
693 && ( c[7]*c[7]<=c[9]*c[2] )
694 && ( c[8]*c[8]<=c[9]*c[5] )
695 && ( c[10]*c[10]<=c[14]*c[0] )
696 && ( c[11]*c[11]<=c[14]*c[2] )
697 && ( c[12]*c[12]<=c[14]*c[5] )
698 && ( c[13]*c[13]<=c[14]*c[9] );
704 #if !defined(HLTCA_GPUCODE)
708 GPUd() void AliHLTTPCCATrackParam::Print() const
712 #if !defined(HLTCA_GPUCODE)
713 std::cout << "track: x=" << GetX() << " c=" << GetSignCosPhi() << ", P= " << GetY() << " " << GetZ() << " " << GetSinPhi() << " " << GetDzDs() << " " << GetQPt() << std::endl;
714 std::cout << "errs2: " << GetErr2Y() << " " << GetErr2Z() << " " << GetErr2SinPhi() << " " << GetErr2DzDs() << " " << GetErr2QPt() << std::endl;