File indexing completed on 2025-08-06 08:18:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "GPUTPCTrackLinearisation.h"
0015 #include "GPUTPCTrackParam.h"
0016 #include <cmath>
0017 #include <algorithm>
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 double GPUTPCTrackParam::GetDist2(const GPUTPCTrackParam& t) const
0030 {
0031
0032
0033 double dx = GetX() - t.GetX();
0034 double dy = GetY() - t.GetY();
0035 double dz = GetZ() - t.GetZ();
0036 return dx * dx + dy * dy + dz * dz;
0037 }
0038
0039 double GPUTPCTrackParam::GetDistXZ2(const GPUTPCTrackParam& t) const
0040 {
0041
0042
0043 double dx = GetX() - t.GetX();
0044 double dz = GetZ() - t.GetZ();
0045 return dx * dx + dz * dz;
0046 }
0047
0048 double GPUTPCTrackParam::GetS(double x, double y, double Bz) const
0049 {
0050
0051
0052 double k = GetKappa(Bz);
0053 double ex = GetCosPhi();
0054 double ey = GetSinPhi();
0055 x -= GetX();
0056 y -= GetY();
0057 double dS = x * ex + y * ey;
0058 if (std::abs(k) > 1.e-4f) {
0059 dS = atan2(k * dS, 1 + k * (x * ey - y * ex)) / k;
0060 }
0061 return dS;
0062 }
0063
0064 void GPUTPCTrackParam::GetDCAPoint(double x, double y, double z, double& xp, double& yp, double& zp, double Bz) const
0065 {
0066
0067
0068 double x0 = GetX();
0069 double y0 = GetY();
0070 double k = GetKappa(Bz);
0071 double ex = GetCosPhi();
0072 double ey = GetSinPhi();
0073 double dx = x - x0;
0074 double dy = y - y0;
0075 double ax = dx * k + ey;
0076 double ay = dy * k - ex;
0077 double a = std::sqrt(ax * ax + ay * ay);
0078 xp = x0 + (dx - ey * ((dx * dx + dy * dy) * k - 2 * (-dx * ey + dy * ex)) / (a + 1)) / a;
0079 yp = y0 + (dy + ex * ((dx * dx + dy * dy) * k - 2 * (-dx * ey + dy * ex)) / (a + 1)) / a;
0080 double s = GetS(x, y, Bz);
0081 zp = GetZ() + GetDzDs() * s;
0082 if (std::abs(k) > 1.e-2f) {
0083 double dZ = std::abs(GetDzDs() * 2*M_PI / k);
0084 if (dZ > .1f) {
0085 zp += round((z - zp) / dZ) * dZ;
0086 }
0087 }
0088 }
0089
0090
0091
0092
0093
0094 bool GPUTPCTrackParam::TransportToX(double x, GPUTPCTrackLinearisation& t0, double Bz, double maxSinPhi, double* DL)
0095 {
0096
0097
0098
0099
0100
0101
0102 double ex = t0.CosPhi();
0103 double ey = t0.SinPhi();
0104 double k = -t0.QPt() * Bz;
0105
0106 double R = 1./fabs(k);
0107 double phi_center;
0108 if(k>0.) phi_center = atan2(ey,ex) - M_PI/2.;
0109 else phi_center = atan2(ey,ex) + M_PI/2.;
0110 double xc = X() - R*cos(phi_center);
0111 double yc = Y() - R*sin(phi_center);
0112
0113 double dx = x - X();
0114 double xnew = x - xc;
0115 double y0 = Y() - yc;
0116
0117
0118 double discriminant = R*R*y0*y0-xnew*xnew*y0*y0;
0119 if(discriminant<0.) return 0;
0120
0121 double ynew = sqrt(R*R-xnew*xnew);
0122 if(y0<0.) ynew *= -1.;
0123
0124 double dy = ynew - y0;
0125 double new_phi_center = atan2(ynew,xnew);
0126 double ex1, ey1;
0127 if(k>0.)
0128 {
0129 ey1 = sin(new_phi_center+M_PI/2.);
0130 ex1 = cos(new_phi_center+M_PI/2.);
0131 }
0132 else
0133 {
0134 ey1 = sin(new_phi_center-M_PI/2.);
0135 ex1 = cos(new_phi_center-M_PI/2.);
0136 }
0137
0138 if(fabs(ey1) > maxSinPhi) return 0;
0139 double dl = sqrt(dx*dx+dy*dy);
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 double dx2 = dx * dx;
0156 double ss = ey + ey1;
0157 double cc = ex + ex1;
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 double dSin = dl * k / 2;
0173 if (dSin > 1) {
0174 dSin = 1;
0175 }
0176 if (dSin < -1) {
0177 dSin = -1;
0178 }
0179 double dphi_center = new_phi_center-phi_center;
0180 if(dphi_center>M_PI) dphi_center = 2.*M_PI-dphi_center;
0181 if(dphi_center<-M_PI) dphi_center = 2.*M_PI+dphi_center;
0182 double dS = R*fabs(dphi_center);
0183 double dz = dS * t0.DzDs();
0184
0185 if (DL) {
0186 *DL = -dS * std::sqrt(1 + t0.DzDs() * t0.DzDs());
0187 }
0188
0189 double cci = 1.f / cc;
0190 double exi = 1.f / ex;
0191 double ex1i = 1.f / ex1;
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 double h2 = dx * (1 + ey * ey1 + ex * ex1) * exi * ex1i * cci;
0202 double h4 = dx2 * (cc + ss * ey1 * ex1i) * cci * cci * (-Bz);
0203 double dxBz = dx * (-Bz);
0204
0205
0206
0207
0208
0209
0210
0211 SetX(X() + dx);
0212 SetPar(0, Y() + dy);
0213 SetPar(1, Z() + dz);
0214 SetPar(2, ey1);
0215
0216 t0.SetCosPhi(ex1);
0217 t0.SetSinPhi(ey1);
0218
0219 double c00 = mC[0];
0220 double c10 = mC[1];
0221 double c11 = mC[2];
0222 double c20 = mC[3];
0223 double c21 = mC[4];
0224 double c22 = mC[5];
0225 double c30 = mC[6];
0226 double c31 = mC[7];
0227 double c32 = mC[8];
0228 double c33 = mC[9];
0229 double c40 = mC[10];
0230 double c41 = mC[11];
0231 double c42 = mC[12];
0232 double c43 = mC[13];
0233 double c44 = mC[14];
0234
0235 mC[0] = c00 + h2 * h2 * c22 + h4 * h4 * c44 + 2 * (h2 * c20 + h4 * c40 + h2 * h4 * c42);
0236
0237 mC[1] = c10 + h2 * c21 + h4 * c41 + dS * (c30 + h2 * c32 + h4 * c43);
0238 mC[2] = c11 + 2 * dS * c31 + dS * dS * c33;
0239
0240 mC[3] = c20 + h2 * c22 + h4 * c42 + dxBz * (c40 + h2 * c42 + h4 * c44);
0241 mC[4] = c21 + dS * c32 + dxBz * (c41 + dS * c43);
0242 mC[5] = c22 + 2 * dxBz * c42 + dxBz * dxBz * c44;
0243
0244 mC[6] = c30 + h2 * c32 + h4 * c43;
0245 mC[7] = c31 + dS * c33;
0246 mC[8] = c32 + dxBz * c43;
0247 mC[9] = c33;
0248
0249 mC[10] = c40 + h2 * c42 + h4 * c44;
0250 mC[11] = c41 + dS * c43;
0251 mC[12] = c42 + dxBz * c44;
0252 mC[13] = c43;
0253 mC[14] = c44;
0254
0255 return 1;
0256 }
0257
0258 bool GPUTPCTrackParam::TransportToX(double x, double sinPhi0, double cosPhi0, double Bz, double maxSinPhi)
0259 {
0260
0261
0262
0263
0264
0265
0266
0267 double ex = cosPhi0;
0268 double ey = sinPhi0;
0269 double dx = x - X();
0270
0271 if (std::abs(ex) < 1.e-4f) {
0272 return 0;
0273 }
0274 double exi = 1.f / ex;
0275
0276 double dxBz = dx * (-Bz);
0277 double dS = dx * exi;
0278 double h2 = dS * exi * exi;
0279 double h4 = .5f * h2 * dxBz;
0280
0281
0282
0283
0284
0285
0286
0287 double sinPhi = SinPhi() + dxBz * QPt();
0288 if (maxSinPhi > 0 && std::abs(sinPhi) > maxSinPhi) {
0289 return 0;
0290 }
0291
0292 SetX(X() + dx);
0293 SetPar(0, GetPar(0) + dS * ey + h2 * (SinPhi() - ey) + h4 * QPt());
0294 SetPar(1, GetPar(1) + dS * DzDs());
0295 SetPar(2, sinPhi);
0296
0297 double c00 = mC[0];
0298 double c10 = mC[1];
0299 double c11 = mC[2];
0300 double c20 = mC[3];
0301 double c21 = mC[4];
0302 double c22 = mC[5];
0303 double c30 = mC[6];
0304 double c31 = mC[7];
0305 double c32 = mC[8];
0306 double c33 = mC[9];
0307 double c40 = mC[10];
0308 double c41 = mC[11];
0309 double c42 = mC[12];
0310 double c43 = mC[13];
0311 double c44 = mC[14];
0312
0313
0314
0315 mC[0] = std::max(c00, c00 + h2 * h2 * c22 + h4 * h4 * c44 + 2 * (h2 * c20 + h4 * c40 + h2 * h4 * c42));
0316
0317 mC[1] = c10 + h2 * c21 + h4 * c41 + dS * (c30 + h2 * c32 + h4 * c43);
0318 mC[2] = std::max(c11, c11 + 2 * dS * c31 + dS * dS * c33);
0319
0320 mC[3] = c20 + h2 * c22 + h4 * c42 + dxBz * (c40 + h2 * c42 + h4 * c44);
0321 mC[4] = c21 + dS * c32 + dxBz * (c41 + dS * c43);
0322 mC[5] = c22 + 2 * dxBz * c42 + dxBz * dxBz * c44;
0323
0324 mC[6] = c30 + h2 * c32 + h4 * c43;
0325 mC[7] = c31 + dS * c33;
0326 mC[8] = c32 + dxBz * c43;
0327 mC[9] = c33;
0328
0329 mC[10] = c40 + h2 * c42 + h4 * c44;
0330 mC[11] = c41 + dS * c43;
0331 mC[12] = c42 + dxBz * c44;
0332 mC[13] = c43;
0333 mC[14] = c44;
0334
0335 return 1;
0336 }
0337
0338 bool GPUTPCTrackParam::TransportToX(double x, double Bz, double maxSinPhi)
0339 {
0340
0341 GPUTPCTrackLinearisation t0(*this);
0342 return TransportToX(x, t0, Bz, maxSinPhi);
0343 }
0344
0345 bool GPUTPCTrackParam::TransportToXWithMaterial(double x, GPUTPCTrackLinearisation& t0, GPUTPCTrackFitParam& par, double Bz, double maxSinPhi)
0346 {
0347
0348
0349
0350
0351 double Ne_nEff = Ne_frac * Ne_Rho / Ne_mA;
0352 double Ar_nEff = Ar_frac * Ar_Rho / Ar_mA;
0353 double CF4_nEff = CF4_frac * CF4_Rho / CF4_mA;
0354 double N2_nEff = N2_frac * N2_Rho / N2_mA;
0355 double isobutane_nEff = isobutane_frac * isobutane_Rho / isobutane_mA;
0356 double nEff = Ar_nEff + CF4_nEff + N2_nEff + isobutane_nEff;
0357
0358
0359 const double kRho = Ne_frac * Ne_Rho
0360 + Ar_frac * Ar_Rho
0361 + CF4_frac * CF4_Rho
0362 + N2_frac * N2_Rho
0363 + isobutane_frac * isobutane_Rho;
0364
0365 const double kRadLen = (1/nEff) * ((Ne_nEff * Ne_RadLen)
0366 + (Ar_nEff * Ar_RadLen)
0367 + (CF4_nEff * CF4_RadLen)
0368 + (N2_nEff * N2_RadLen)
0369 + (isobutane_nEff * isobutane_RadLen));
0370 const double kRhoOverRadLen = kRho / kRadLen;
0371 double dl;
0372
0373 if (!TransportToX(x, t0, Bz, maxSinPhi, &dl)) {
0374 return 0;
0375 }
0376
0377 CorrectForMeanMaterial(dl * kRhoOverRadLen, dl * kRho, par);
0378 return 1;
0379 }
0380
0381 bool GPUTPCTrackParam::TransportToXWithMaterial(double x, GPUTPCTrackFitParam& par, double Bz, double maxSinPhi)
0382 {
0383
0384
0385 GPUTPCTrackLinearisation t0(*this);
0386 return TransportToXWithMaterial(x, t0, par, Bz, maxSinPhi);
0387 }
0388
0389 bool GPUTPCTrackParam::TransportToXWithMaterial(double x, double Bz, double maxSinPhi)
0390 {
0391
0392
0393 GPUTPCTrackFitParam par;
0394 CalculateFitParameters(par);
0395 return TransportToXWithMaterial(x, par, Bz, maxSinPhi);
0396 }
0397
0398
0399
0400
0401 double GPUTPCTrackParam::BetheBlochGeant(double bg2, double kp0, double kp1, double kp2, double kp3, double kp4)
0402 {
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 const double mK = 0.307075e-3f;
0418 const double me = 0.511e-3f;
0419 const double rho = kp0;
0420 const double x0 = kp1 * 2.303f;
0421 const double x1 = kp2 * 2.303f;
0422 const double mI = kp3;
0423 const double mZA = kp4;
0424 const double maxT = 2 * me * bg2;
0425
0426
0427 double d2 = 0.f;
0428 const double x = 0.5f * log(bg2);
0429 const double lhwI = log(28.816f * 1e-9f * std::sqrt(rho * mZA) / mI);
0430 if (x > x1) {
0431 d2 = lhwI + x - 0.5f;
0432 } else if (x > x0) {
0433 const double r = (x1 - x) / (x1 - x0);
0434 d2 = lhwI + x - 0.5f + (0.5f - lhwI - x0) * r * r * r;
0435 }
0436
0437 return mK * mZA * (1 + bg2) / bg2 * (0.5f * log(2 * me * bg2 * maxT / (mI * mI)) - bg2 / (1 + bg2) - d2);
0438 }
0439
0440 double GPUTPCTrackParam::BetheBlochSolid(double bg)
0441 {
0442
0443
0444
0445
0446
0447
0448
0449 return BetheBlochGeant(bg);
0450 }
0451
0452 double GPUTPCTrackParam::BetheBlochGas(double bg)
0453 {
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467 double Ne_nEff = Ne_frac * Ne_Rho / Ne_mA;
0468 double Ar_nEff = Ar_frac * Ar_Rho / Ar_mA;
0469 double CF4_nEff = CF4_frac * CF4_Rho / CF4_mA;
0470 double N2_nEff = N2_frac * N2_Rho / N2_mA;
0471 double isobutane_nEff = isobutane_frac * isobutane_Rho / isobutane_mA;
0472 double nEff = Ar_nEff + CF4_nEff + N2_nEff + isobutane_nEff;
0473
0474
0475
0476
0477
0478
0479
0480
0481 const double rho = Ne_frac * Ne_Rho
0482 + Ar_frac * Ar_Rho
0483 + CF4_frac * CF4_Rho
0484 + N2_frac * N2_Rho
0485 + isobutane_frac * isobutane_Rho;
0486
0487 const double x0 = (1/nEff) * ((Ne_nEff * Ne_x0)
0488 + (Ar_nEff * Ar_x0)
0489 + (CF4_nEff * CF4_x0)
0490 + (N2_nEff * N2_x0)
0491 + (isobutane_nEff * isobutane_x0));
0492
0493 const double x1 = (1/nEff) * ((Ne_nEff * Ne_x1)
0494 + (Ar_nEff * Ar_x1)
0495 + (CF4_nEff * CF4_x1)
0496 + (N2_nEff * N2_x1)
0497 + (isobutane_nEff * isobutane_x1));
0498
0499 const double mI = (1/nEff) * ((Ne_nEff * Ne_mI)
0500 + (Ar_nEff * Ar_mI)
0501 + (CF4_nEff * CF4_mI)
0502 + (N2_nEff * N2_mI)
0503 + (isobutane_nEff * isobutane_mI));
0504
0505 const double mZA = (1/nEff) * ((Ne_nEff * Ne_mZA)
0506 + (Ar_nEff * Ar_mZA)
0507 + (CF4_nEff * CF4_mZA)
0508 + (N2_nEff * N2_mZA)
0509 + (isobutane_nEff * isobutane_mZA));
0510 return BetheBlochGeant(bg, rho, x0, x1, mI, mZA);
0511 }
0512
0513 double GPUTPCTrackParam::ApproximateBetheBloch(double beta2)
0514 {
0515
0516
0517
0518
0519
0520 if (beta2 >= 1) {
0521 return 0;
0522 }
0523
0524 if (beta2 / (1 - beta2) > 3.5f * 3.5f) {
0525 return 0.153e-3f / beta2 * (log(3.5f * 5940) + 0.5f * log(beta2 / (1 - beta2)) - beta2);
0526 }
0527 return 0.153e-3f / beta2 * (log(5940 * beta2 / (1 - beta2)) - beta2);
0528 }
0529
0530 void GPUTPCTrackParam::CalculateFitParameters(GPUTPCTrackFitParam& par, double mass)
0531 {
0532
0533
0534 double qpt = GetPar(4);
0535
0536
0537
0538
0539 double p2 = (1.f + GetPar(3) * GetPar(3));
0540 double k2 = qpt * qpt;
0541 double mass2 = mass * mass;
0542 double beta2 = p2 / (p2 + mass2 * k2);
0543
0544 double pp2 = (k2 > 1.e-8f) ? p2 / k2 : 10000;
0545
0546 par.bethe = BetheBlochGas( beta2/(1+beta2) );
0547
0548 par.e = std::sqrt(pp2 + mass2);
0549 par.theta2 = 14.1f * 14.1f / (beta2 * pp2 * 1e6f);
0550 par.EP2 = par.e / pp2;
0551
0552
0553
0554 const double knst = 0.0007f;
0555 par.sigmadE2 = knst * par.EP2 * qpt;
0556 par.sigmadE2 = par.sigmadE2 * par.sigmadE2;
0557
0558 par.k22 = (1.f + GetPar(3) * GetPar(3));
0559 par.k33 = par.k22 * par.k22;
0560 par.k43 = 0;
0561 par.k44 = GetPar(3) * GetPar(3) * k2;
0562 }
0563
0564 bool GPUTPCTrackParam::CorrectForMeanMaterial(double xOverX0, double xTimesRho, const GPUTPCTrackFitParam& par)
0565 {
0566
0567
0568
0569
0570
0571
0572 double& mC22 = mC[5];
0573 double& mC33 = mC[9];
0574 double& mC40 = mC[10];
0575 double& mC41 = mC[11];
0576 double& mC42 = mC[12];
0577 double& mC43 = mC[13];
0578 double& mC44 = mC[14];
0579
0580
0581
0582 double dE = par.bethe * xTimesRho;
0583 if (std::abs(dE) > 0.3f * par.e) {
0584 return 0;
0585 }
0586 double corr = (1.f - par.EP2 * dE);
0587 if (corr < 0.3f || corr > 1.3f) {
0588 return 0;
0589 }
0590
0591 SetPar(4, GetPar(4) * corr);
0592 mC40 *= corr;
0593 mC41 *= corr;
0594 mC42 *= corr;
0595 mC43 *= corr;
0596 mC44 *= corr * corr;
0597 mC44 += par.sigmadE2 * std::abs(dE);
0598
0599
0600
0601 double theta2 = par.theta2 * std::abs(xOverX0);
0602 mC22 += theta2 * par.k22 * (1.f - GetPar(2)) * (1.f + GetPar(2));
0603 mC33 += theta2 * par.k33;
0604 mC43 += theta2 * par.k43;
0605 mC44 += theta2 * par.k44;
0606
0607 return 1;
0608 }
0609
0610
0611
0612
0613 bool GPUTPCTrackParam::Rotate(double alpha, double maxSinPhi)
0614 {
0615
0616
0617 double cA = cos(alpha);
0618 double sA = sin(alpha);
0619 double x = X(), y = Y(), sP = SinPhi(), cP = GetCosPhi();
0620 double cosPhi = cP * cA + sP * sA;
0621 double sinPhi = -cP * sA + sP * cA;
0622
0623 if (std::abs(sinPhi) > maxSinPhi) {
0624 return 0;
0625 }
0626
0627 double j0 = cP / cosPhi;
0628 double j2 = cosPhi / cP;
0629
0630 SetX(x * cA + y * sA);
0631 SetY(-x * sA + y * cA);
0632 SetSignCosPhi(cosPhi);
0633 SetSinPhi(sinPhi);
0634
0635
0636
0637
0638
0639
0640
0641
0642 mC[0] *= j0 * j0;
0643 mC[1] *= j0;
0644 mC[3] *= j0;
0645 mC[6] *= j0;
0646 mC[10] *= j0;
0647
0648 mC[3] *= j2;
0649 mC[4] *= j2;
0650 mC[5] *= j2 * j2;
0651 mC[8] *= j2;
0652 mC[12] *= j2;
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669 return 1;
0670 }
0671
0672 bool GPUTPCTrackParam::Rotate(double alpha, GPUTPCTrackLinearisation& t0, double maxSinPhi)
0673 {
0674
0675
0676 double cA = cos(alpha);
0677 double sA = sin(alpha);
0678 double x0 = X(), y0 = Y(), sP = t0.SinPhi(), cP = t0.CosPhi();
0679 double cosPhi = cP * cA + sP * sA;
0680 double sinPhi = -cP * sA + sP * cA;
0681
0682 if (std::abs(sinPhi) > maxSinPhi || std::abs(cosPhi) < 1.e-2f || std::abs(cP) < 1.e-2f) {
0683 return 0;
0684 }
0685
0686
0687
0688
0689
0690
0691
0692 double j0 = cP / cosPhi;
0693 double j2 = cosPhi / cP;
0694 double d[2] = {Y() - y0, SinPhi() - sP};
0695
0696 SetX(x0 * cA + y0 * sA);
0697 SetY(-x0 * sA + y0 * cA + j0 * d[0]);
0698 t0.SetCosPhi(cosPhi);
0699 t0.SetSinPhi(sinPhi);
0700
0701 SetSinPhi(sinPhi + j2 * d[1]);
0702
0703 mC[0] *= j0 * j0;
0704 mC[1] *= j0;
0705 mC[3] *= j0;
0706 mC[6] *= j0;
0707 mC[10] *= j0;
0708
0709 mC[3] *= j2;
0710 mC[4] *= j2;
0711 mC[5] *= j2 * j2;
0712 mC[8] *= j2;
0713 mC[12] *= j2;
0714
0715 return 1;
0716 }
0717
0718 bool GPUTPCTrackParam::Filter(double y, double z, double err2Y, double err2Z, double maxSinPhi, bool paramOnly)
0719 {
0720
0721
0722 double c00 = mC[0], c11 = mC[2], c20 = mC[3], c31 = mC[7], c40 = mC[10];
0723
0724 err2Y += c00;
0725 err2Z += c11;
0726
0727 double z0 = y - GetPar(0), z1 = z - GetPar(1);
0728
0729 if (err2Y < 1.e-8f || err2Z < 1.e-8f) {
0730 return 0;
0731 }
0732
0733 double mS0 = 1.f / err2Y;
0734 double mS2 = 1.f / err2Z;
0735
0736
0737
0738 double k00, k11, k20, k31, k40;
0739
0740 k00 = c00 * mS0;
0741 k20 = c20 * mS0;
0742 k40 = c40 * mS0;
0743
0744 k11 = c11 * mS2;
0745 k31 = c31 * mS2;
0746
0747 double sinPhi = GetPar(2) + k20 * z0;
0748
0749 if (maxSinPhi > 0 && std::abs(sinPhi) >= maxSinPhi) {
0750 return 0;
0751 }
0752
0753 SetPar(0, GetPar(0) + k00 * z0);
0754 SetPar(1, GetPar(1) + k11 * z1);
0755 SetPar(2, sinPhi);
0756 SetPar(3, GetPar(3) + k31 * z1);
0757 SetPar(4, GetPar(4) + k40 * z0);
0758 if (paramOnly) {
0759 return true;
0760 }
0761
0762 mNDF += 2;
0763 mChi2 += mS0 * z0 * z0 + mS2 * z1 * z1;
0764
0765 mC[0] -= k00 * c00;
0766 mC[3] -= k20 * c00;
0767 mC[5] -= k20 * c20;
0768 mC[10] -= k40 * c00;
0769 mC[12] -= k40 * c20;
0770 mC[14] -= k40 * c40;
0771
0772 mC[2] -= k11 * c11;
0773 mC[7] -= k31 * c11;
0774 mC[9] -= k31 * c31;
0775
0776 return 1;
0777 }
0778
0779 bool GPUTPCTrackParam::CheckNumericalQuality() const
0780 {
0781
0782
0783 bool ok = std::isfinite(GetX()) && std::isfinite(mSignCosPhi) && std::isfinite(mChi2);
0784
0785 const double* c = Cov();
0786 for (int i = 0; i < 15; i++) {
0787 ok = ok && std::isfinite(c[i]);
0788 }
0789 for (int i = 0; i < 5; i++) {
0790 ok = ok && std::isfinite(Par()[i]);
0791 }
0792
0793 if (c[0] <= 0 || c[2] <= 0 || c[5] <= 0 || c[9] <= 0 || c[14] <= 0) {
0794 ok = 0;
0795 }
0796 if (c[0] > 5.f || c[2] > 5.f || c[5] > 2.f || c[9] > 2
0797
0798 ) {
0799 ok = 0;
0800 }
0801
0802 if (std::abs(SinPhi()) > GPUCA_MAX_SIN_PHI) {
0803 ok = 0;
0804 }
0805 if (std::abs(QPt()) > 1.f / 0.05f) {
0806 ok = 0;
0807 }
0808 if (ok) {
0809 ok = ok && (c[1] * c[1] <= c[2] * c[0]) && (c[3] * c[3] <= c[5] * c[0]) && (c[4] * c[4] <= c[5] * c[2]) && (c[6] * c[6] <= c[9] * c[0]) && (c[7] * c[7] <= c[9] * c[2]) && (c[8] * c[8] <= c[9] * c[5]) && (c[10] * c[10] <= c[14] * c[0]) && (c[11] * c[11] <= c[14] * c[2]) &&
0810 (c[12] * c[12] <= c[14] * c[5]) && (c[13] * c[13] <= c[14] * c[9]);
0811 }
0812 return ok;
0813 }
0814
0815 #if !defined(GPUCA_GPUCODE)
0816 #include <iostream>
0817 #endif
0818
0819 void GPUTPCTrackParam::Print() const
0820 {
0821
0822
0823 #if !defined(GPUCA_GPUCODE)
0824 std::cout << "track: x=" << GetX() << " c=" << GetSignCosPhi() << ", P= " << GetY() << " " << GetZ() << " " << GetSinPhi() << " " << GetDzDs() << " " << GetQPt() << std::endl;
0825 std::cout << "errs2: " << GetErr2Y() << " " << GetErr2Z() << " " << GetErr2SinPhi() << " " << GetErr2DzDs() << " " << GetErr2QPt() << std::endl;
0826 #endif
0827 }