File indexing completed on 2025-08-06 08:18:23
0001 #include "ALICEKF.h"
0002
0003 #include "GPUTPCTrackLinearisation.h"
0004 #include "GPUTPCTrackParam.h"
0005
0006 #include <trackbase/ClusterErrorPara.h>
0007 #include <trackbase/TrackFitUtils.h>
0008 #include <trackbase/TrkrCluster.h>
0009 #include <trackbase_historic/ActsTransformations.h>
0010
0011 #include <Geant4/G4SystemOfUnits.hh>
0012
0013 #include <TMatrixFfwd.h>
0014 #include <TMatrixT.h>
0015 #include <TMatrixTUtils.h>
0016
0017 #include <omp.h>
0018
0019
0020
0021 #if defined(_DEBUG_)
0022 #define LogDebug(exp) std::cout << "DEBUG: " << __FILE__ << ": " << __LINE__ << ": " << exp
0023 #else
0024 #define LogDebug(exp) (void) 0
0025 #endif
0026
0027 #define LogError(exp) \
0028 if (Verbosity() > 0) std::cout << "ERROR: " << __FILE__ << ": " << __LINE__ << ": " << exp
0029 #define LogWarning(exp) \
0030 if (Verbosity() > 0) std::cout << "WARNING: " << __FILE__ << ": " << __LINE__ << ": " << exp
0031
0032 using keylist = std::vector<TrkrDefs::cluskey>;
0033
0034
0035 namespace
0036 {
0037
0038 template <class T>
0039 inline constexpr T square(const T& x)
0040 {
0041 return x * x;
0042 }
0043 }
0044
0045 bool ALICEKF::checknan(double val, const std::string& name, int num) const
0046 {
0047 if (std::isnan(val))
0048 {
0049 if (Verbosity() > 0)
0050 {
0051 std::cout << "WARNING: " << name << " is NaN for seed " << num << ". Aborting this seed.\n";
0052 }
0053 }
0054 return std::isnan(val);
0055 }
0056
0057 double ALICEKF::get_Bz(double x, double y, double z) const
0058 {
0059
0060 if (_use_const_field || fabs(z) > 105.5)
0061 {
0062 return _const_field;
0063 }
0064 double p[4] = {x * cm, y * cm, z * cm, 0. * cm};
0065 double bfield[3];
0066
0067
0068 if( omp_get_thread_num() == 0 )
0069 {
0070 _B->GetFieldValue(p, bfield);
0071 } else {
0072 _B->GetFieldValue_nocache(p, bfield);
0073 }
0074
0075 return bfield[2] / tesla;
0076 }
0077
0078 double ALICEKF::getClusterError(TrkrCluster* c, TrkrDefs::cluskey key, Acts::Vector3 global, int i, int j) const
0079 {
0080 if (_use_fixed_clus_error)
0081 {
0082 if (i == j)
0083 {
0084 return _fixed_clus_error.at(i) * _fixed_clus_error.at(i);
0085 }
0086 else
0087 {
0088 return 0.;
0089 }
0090 }
0091 else
0092 {
0093 TMatrixF localErr(3, 3);
0094
0095 double clusRadius = sqrt(global[0] * global[0] + global[1] * global[1]);
0096 auto para_errors = _ClusErrPara->get_clusterv5_modified_error(c, clusRadius, key);
0097
0098 localErr[0][0] = 0.;
0099 localErr[0][1] = 0.;
0100 localErr[0][2] = 0.;
0101 localErr[1][0] = 0.;
0102 localErr[1][1] = para_errors.first;
0103 localErr[1][2] = 0.;
0104 localErr[2][0] = 0.;
0105 localErr[2][1] = 0.;
0106 localErr[2][2] = para_errors.second;
0107
0108 float clusphi = atan2(global(1), global(0));
0109 TMatrixF ROT(3, 3);
0110 ROT[0][0] = cos(clusphi);
0111 ROT[0][1] = -sin(clusphi);
0112 ROT[0][2] = 0.0;
0113 ROT[1][0] = sin(clusphi);
0114 ROT[1][1] = cos(clusphi);
0115 ROT[1][2] = 0.0;
0116 ROT[2][0] = 0.0;
0117 ROT[2][1] = 0.0;
0118 ROT[2][2] = 1.0;
0119 TMatrixF ROT_T(3, 3);
0120 ROT_T.Transpose(ROT);
0121
0122 TMatrixF err(3, 3);
0123 err = ROT * localErr * ROT_T;
0124
0125 return err[i][j];
0126 }
0127 }
0128
0129 bool ALICEKF::TransportAndRotate(double old_radius, double new_radius, double& phi, GPUTPCTrackParam& kftrack, GPUTPCTrackParam::GPUTPCTrackFitParam& fp) const
0130 {
0131 const double transport_spacing = .05;
0132 const int Ndivisions = floor(fabs(new_radius - old_radius) / transport_spacing);
0133 if (Verbosity() > 2)
0134 {
0135 std::cout << "old_radius: " << old_radius << ", new_radius: " << new_radius << std::endl;
0136 }
0137 if (Verbosity() > 2)
0138 {
0139 std::cout << "Ndivisions: " << Ndivisions << std::endl;
0140 }
0141 for (int i = 1; i <= Ndivisions + 1; i++)
0142 {
0143 if (std::isnan(kftrack.GetX()) ||
0144 std::isnan(kftrack.GetY()) ||
0145 std::isnan(kftrack.GetZ()))
0146 {
0147 if (Verbosity() > 0)
0148 {
0149 std::cout << "position is NaN, exiting" << std::endl;
0150 }
0151 return false;
0152 }
0153
0154 if (new_radius > 78.)
0155 {
0156 if (Verbosity() > 1)
0157 {
0158 std::cout << "outside TPC, exiting" << std::endl;
0159 }
0160 return false;
0161 }
0162
0163 double r_div;
0164 if (i == Ndivisions + 1)
0165 {
0166 r_div = new_radius;
0167 }
0168 else if (old_radius < new_radius)
0169 {
0170 r_div = old_radius + transport_spacing * i;
0171 }
0172 else
0173 {
0174 r_div = old_radius - transport_spacing * i;
0175 }
0176
0177
0178 const double tX = kftrack.GetX();
0179 const double tY = kftrack.GetY();
0180 const double tz = kftrack.GetZ();
0181
0182
0183 const double tx = tX * cos(phi) - tY * sin(phi);
0184 const double ty = tX * sin(phi) + tY * cos(phi);
0185
0186 const double Bz = _Bzconst * get_Bz(tx, ty, tz);
0187
0188 kftrack.CalculateFitParameters(fp);
0189
0190
0191 if (!kftrack.TransportToXWithMaterial(r_div, fp, Bz, 1.))
0192 {
0193 if (Verbosity() > 1)
0194 {
0195 std::cout << "transport failed" << std::endl;
0196 }
0197 return false;
0198 }
0199
0200
0201 const double new_tX = kftrack.GetX();
0202 const double new_tY = kftrack.GetY();
0203 const double new_tx = new_tX * cos(phi) - new_tY * sin(phi);
0204 const double new_ty = new_tX * sin(phi) + new_tY * cos(phi);
0205 const double new_phi = atan2(new_ty, new_tx);
0206 const double alpha = new_phi - phi;
0207 if (!kftrack.Rotate(alpha, 1.))
0208 {
0209 if (Verbosity() > 1)
0210 {
0211 std::cout << "rotate failed" << std::endl;
0212 }
0213 return false;
0214 }
0215 phi = new_phi;
0216 }
0217
0218 const double final_tX = kftrack.GetX();
0219 const double final_tY = kftrack.GetY();
0220 const double final_tx = final_tX * cos(phi) - final_tY * sin(phi);
0221 const double final_ty = final_tX * sin(phi) + final_tY * cos(phi);
0222 const double final_tz = kftrack.GetZ();
0223
0224 if (Verbosity() > 1)
0225 {
0226 std::cout << "track position after transport: (" << final_tx << ", " << final_ty << ", " << final_tz << ")" << std::endl;
0227 }
0228 return true;
0229 }
0230
0231 bool ALICEKF::FilterStep(TrkrDefs::cluskey ckey, keylist& keys, double& current_phi, GPUTPCTrackParam& kftrack, GPUTPCTrackParam::GPUTPCTrackFitParam& fp, const PositionMap& globalPositions) const
0232 {
0233
0234 if (std::isnan(kftrack.GetX()) ||
0235 std::isnan(kftrack.GetY()) ||
0236 std::isnan(kftrack.GetZ()))
0237 {
0238 if (Verbosity() > 0)
0239 {
0240 std::cout << "position is NaN, exiting" << std::endl;
0241 }
0242 return false;
0243 }
0244
0245
0246 const double tX = kftrack.GetX();
0247 const double tY = kftrack.GetY();
0248 const double tz = kftrack.GetZ();
0249
0250
0251 const double tx = tX * cos(current_phi) - tY * sin(current_phi);
0252 const double ty = tX * sin(current_phi) + tY * cos(current_phi);
0253
0254 if (Verbosity() > 1)
0255 {
0256 std::cout << std::endl;
0257 std::cout << "current phi: " << current_phi << std::endl;
0258 std::cout << "track position: (" << tx << ", " << ty << ", " << tz << ")" << std::endl;
0259 }
0260
0261 const auto& cluster_pos = globalPositions.at(ckey);
0262 const double cx = cluster_pos(0);
0263 const double cy = cluster_pos(1);
0264 const double cz = cluster_pos(2);
0265
0266 if (Verbosity() > 1)
0267 {
0268 std::cout << "cluster position: (" << cx << ", " << cy << ", " << cz << ")" << std::endl;
0269 }
0270
0271 const double cX = sqrt(cx * cx + cy * cy);
0272
0273 if (Verbosity() > 1)
0274 {
0275 std::cout << "transporting to radius: " << cX << std::endl;
0276 }
0277
0278 if (fabs(tX - cX) < 0.1 || !TransportAndRotate(tX, cX, current_phi, kftrack, fp))
0279 {
0280 if (std::isnan(kftrack.GetX()) ||
0281 std::isnan(kftrack.GetY()) ||
0282 std::isnan(kftrack.GetZ()))
0283 {
0284 return false;
0285 }
0286
0287 if (Verbosity() > 1)
0288 {
0289 std::cout << "track turned around near X=" << kftrack.GetX() << std::endl;
0290 }
0291
0292
0293
0294
0295
0296
0297 double pt = 1. / fabs(kftrack.GetQPt());
0298 double end_tx = kftrack.GetX() * cos(current_phi) - kftrack.GetY() * sin(current_phi);
0299 double end_ty = kftrack.GetX() * sin(current_phi) + kftrack.GetY() * cos(current_phi);
0300 double end_tz = kftrack.GetZ();
0301 if (Verbosity() > 1)
0302 {
0303 std::cout << "current parameters: pt=" << pt << ", (x, y, z) = (" << end_tx << ", " << end_ty << ", " << end_tz << ")" << std::endl;
0304 }
0305
0306 double R = 100. * pt / (0.3 * get_Bz(end_tx, end_ty, end_tz));
0307 if (Verbosity() > 2)
0308 {
0309 std::cout << "R=" << R << std::endl;
0310 }
0311 double pX = pt * kftrack.GetCosPhi();
0312 double pY = pt * kftrack.GetSinPhi();
0313 if (Verbosity() > 2)
0314 {
0315 std::cout << "(pX, pY) = (" << pX << ", " << pY << ")" << std::endl;
0316 }
0317 double px = pX * cos(current_phi) - pY * sin(current_phi);
0318 double py = pX * sin(current_phi) + pY * cos(current_phi);
0319 double tangent_phi = atan2(py, px);
0320 double center_phi;
0321 if (kftrack.GetQPt() > 0)
0322 {
0323 center_phi = tangent_phi + M_PI / 2.;
0324 }
0325 else
0326 {
0327 center_phi = tangent_phi - M_PI / 2.;
0328 }
0329 if (center_phi > M_PI)
0330 {
0331 center_phi -= 2. * M_PI;
0332 }
0333 if (center_phi < -M_PI)
0334 {
0335 center_phi += 2. * M_PI;
0336 }
0337 double xc = end_tx - R * cos(center_phi);
0338 double yc = end_ty - R * sin(center_phi);
0339 if (Verbosity() > 2)
0340 {
0341 std::cout << "(xc, yc) = (" << xc << ", " << yc << ")" << std::endl;
0342 }
0343 auto circle_output = TrackFitUtils::circle_circle_intersection(sqrt(pow(kftrack.GetX(), 2.) + pow(kftrack.GetY(), 2.)), R, xc, yc);
0344
0345 double new_tx;
0346 double new_ty;
0347 double xplus = std::get<0>(circle_output);
0348 double yplus = std::get<1>(circle_output);
0349 double xminus = std::get<2>(circle_output);
0350 double yminus = std::get<3>(circle_output);
0351 if (Verbosity() > 1)
0352 {
0353 std::cout << "circle-circle intersection: (" << xplus << ", " << yplus << "), (" << xminus << ", " << yminus << ")" << std::endl;
0354 }
0355
0356 if (sqrt(pow(end_tx - xplus, 2.) + pow(end_ty - yplus, 2.)) > sqrt(pow(end_tx - xminus, 2.) + pow(end_ty - yminus, 2.)))
0357 {
0358 new_tx = xplus;
0359 new_ty = yplus;
0360 }
0361 else
0362 {
0363 new_tx = xminus;
0364 new_ty = yminus;
0365 }
0366 double rot_phi = atan2(new_ty, new_tx);
0367
0368
0369
0370 double new_tX = new_tx * cos(rot_phi) + new_ty * sin(rot_phi);
0371 double new_tY = -new_tx * sin(rot_phi) + new_ty * cos(rot_phi);
0372 double new_centerphi = atan2(new_ty - yc, new_tx - xc);
0373 double dcenterphi = new_centerphi - center_phi;
0374 if (dcenterphi > M_PI)
0375 {
0376 dcenterphi = 2. * M_PI - dcenterphi;
0377 }
0378 if (dcenterphi < -M_PI)
0379 {
0380 dcenterphi = 2. * M_PI + dcenterphi;
0381 }
0382 double ds = R * fabs(dcenterphi);
0383 double dz = kftrack.GetDzDs() * ds;
0384
0385 current_phi = rot_phi;
0386 kftrack.SetX(new_tX);
0387 kftrack.SetY(new_tY);
0388 kftrack.SetZ(end_tz + dz);
0389
0390
0391
0392
0393 kftrack.SetSignCosPhi(-kftrack.GetSignCosPhi());
0394
0395
0396 if (!TransportAndRotate(kftrack.GetX(), cX, current_phi, kftrack, fp))
0397 {
0398 return false;
0399 }
0400 }
0401
0402 if (Verbosity() > 1)
0403 {
0404 const double new_tX = kftrack.GetX();
0405 const double new_tY = kftrack.GetY();
0406 const double new_tx = new_tX * cos(current_phi) - new_tY * sin(current_phi);
0407 const double new_ty = new_tX * sin(current_phi) + new_tY * cos(current_phi);
0408 const double new_tz = kftrack.GetZ();
0409 std::cout << "cluster position: (" << cx << ", " << cy << ", " << cz << ")" << std::endl;
0410 std::cout << "current phi: " << current_phi << std::endl;
0411 std::cout << "new track position: (" << new_tx << ", " << new_ty << ", " << new_tz << ")" << std::endl;
0412
0413 const double tYerr = sqrt(kftrack.GetCov(0));
0414 const double txerr = fabs(tYerr * sin(current_phi));
0415 const double tyerr = fabs(tYerr * cos(current_phi));
0416 const double tzerr = sqrt(kftrack.GetCov(5));
0417 std::cout << "track position error: (" << txerr << ", " << tyerr << ", " << tzerr << ")" << std::endl;
0418 }
0419
0420 TrkrCluster* cluster = _cluster_map->findCluster(ckey);
0421 const double cxerr = sqrt(getClusterError(cluster, ckey, cluster_pos, 0, 0));
0422 const double cyerr = sqrt(getClusterError(cluster, ckey, cluster_pos, 1, 1));
0423 const double czerr = sqrt(getClusterError(cluster, ckey, cluster_pos, 2, 2));
0424
0425 if (Verbosity() > 1)
0426 {
0427 std::cout << "cluster position error: (" << cxerr << ", " << cyerr << ", " << czerr << ")" << std::endl;
0428 }
0429
0430 const double cY = -cx * sin(current_phi) + cy * cos(current_phi);
0431 const double cxycov2 = getClusterError(cluster, ckey, cluster_pos, 0, 1);
0432 const double cYerr2 = cxerr * cxerr * sin(current_phi) * sin(current_phi) + cxycov2 * sin(current_phi) * cos(current_phi) + cyerr * cyerr * cos(current_phi) * cos(current_phi);
0433 const double czerr2 = czerr * czerr;
0434
0435 if (Verbosity() > 1)
0436 {
0437 std::cout << "Filtering cluster with Y=" << cY << ", z=" << cz << ", Yerr2=" << cYerr2 << ", zerr2=" << czerr2 << std::endl;
0438 }
0439
0440 bool filter_success = kftrack.Filter(cY, cz, cYerr2, czerr2, _max_sin_phi);
0441 if (Verbosity() > 1)
0442 {
0443 std::cout << "position after filter: (" << kftrack.GetX() * cos(current_phi) - kftrack.GetY() * sin(current_phi) << ", " << kftrack.GetX() * sin(current_phi) + kftrack.GetY() * cos(current_phi) << ", " << kftrack.GetZ() << std::endl;
0444 std::cout << "track current parameters:" << std::endl;
0445 std::cout << "(X, Y, Z) = (" << kftrack.GetX() << ", " << kftrack.GetY() << ", " << kftrack.GetZ() << ")" << std::endl;
0446 std::cout << "pt = " << 1. / fabs(kftrack.GetQPt()) << std::endl;
0447 std::cout << "QPt = " << kftrack.GetQPt() << std::endl;
0448 std::cout << "sinPhi = " << kftrack.GetSinPhi() << std::endl;
0449 std::cout << "cosPhi = " << kftrack.GetCosPhi() << std::endl;
0450 std::cout << "dzds = " << kftrack.GetDzDs() << std::endl;
0451 }
0452 if (!filter_success)
0453 {
0454 keys.erase(std::find(keys.begin(), keys.end(), ckey));
0455 }
0456 return true;
0457 }
0458
0459 TrackSeedAliceSeedMap ALICEKF::ALICEKalmanFilter(const std::vector<keylist>& trackSeedKeyLists, bool use_nhits_limit, const PositionMap& globalPositions, std::vector<float>& trackChi2) const
0460 {
0461
0462
0463 std::vector<TrackSeed_v2> seeds_vector;
0464 std::vector<GPUTPCTrackParam> alice_seeds_vector;
0465 int nseeds = 0;
0466 int ncandidates = -1;
0467 if (Verbosity() > 0)
0468 {
0469 std::cout << "min clusters per track: " << _min_clusters_per_track << "\n";
0470 }
0471 for (auto trackKeyChain : trackSeedKeyLists)
0472 {
0473 ++ncandidates;
0474
0475 if (trackKeyChain.size() < 2)
0476 {
0477 continue;
0478 }
0479 if (use_nhits_limit && trackKeyChain.size() < _min_clusters_per_track)
0480 {
0481 continue;
0482 }
0483
0484
0485
0486 const auto& globalpos = globalPositions.at(trackKeyChain.at(0));
0487 double x0 = globalpos(0);
0488 double y0 = globalpos(1);
0489 double z0 = globalpos(2);
0490 ;
0491 LogDebug("Initial (x,y,z): (" << x0 << "," << y0 << "," << z0 << ")" << std::endl);
0492
0493 double alice_x0 = sqrt(x0 * x0 + y0 * y0);
0494 double alice_y0 = 0;
0495 double alice_z0 = z0;
0496
0497 GPUTPCTrackParam trackSeed;
0498 trackSeed.setNeonFraction(Ne_frac);
0499 trackSeed.setArgonFraction(Ar_frac);
0500 trackSeed.setCF4Fraction(CF4_frac);
0501 trackSeed.setNitrogenFraction(N2_frac);
0502 trackSeed.setIsobutaneFraction(isobutane_frac);
0503 trackSeed.InitParam();
0504 trackSeed.SetX(alice_x0);
0505 trackSeed.SetY(alice_y0);
0506 trackSeed.SetZ(alice_z0);
0507 double x = x0;
0508 double y = y0;
0509 #if defined(_DEBUG_)
0510 double z = z0;
0511 double alice_x = sqrt(x0 * x0 + y0 * y0);
0512 #endif
0513
0514 const auto& secondpos = globalPositions.at(trackKeyChain.at(1));
0515
0516 const double second_x = secondpos(0);
0517 const double second_y = secondpos(1);
0518 const double second_z = secondpos(2);
0519 const double first_phi = atan2(y0, x0);
0520 const double second_alice_x = second_x * std::cos(first_phi) + second_y * std::sin(first_phi);
0521 const double delta_alice_x = second_alice_x - alice_x0;
0522
0523 const double second_alice_y = -second_x * std::sin(first_phi) + second_y * std::cos(first_phi);
0524 double init_SinPhi = second_alice_y / std::sqrt(square(delta_alice_x) + square(second_alice_y));
0525 const double delta_z = second_z - z0;
0526 double init_DzDs = delta_z / std::sqrt(square(delta_alice_x) + square(second_alice_y));
0527 if (delta_alice_x < 0.)
0528 {
0529 init_SinPhi *= -1.;
0530 init_DzDs *= -1.;
0531 }
0532 trackSeed.SetSinPhi(init_SinPhi);
0533
0534 LogDebug("Set initial SinPhi to " << init_SinPhi << std::endl);
0535 trackSeed.SetDzDs(init_DzDs);
0536 LogDebug("Set initial DzDs to " << init_DzDs << std::endl);
0537
0538
0539 std::vector<std::pair<double, double>> pts;
0540 std::transform(trackKeyChain.begin(), trackKeyChain.end(), std::back_inserter(pts), [&globalPositions](const TrkrDefs::cluskey& key)
0541 {
0542 const auto& clpos = globalPositions.at(key);
0543 return std::make_pair(clpos(0),clpos(1)); });
0544
0545 const auto [R, x_center, y_center] = TrackFitUtils::circle_fit_by_taubin(pts);
0546 if (Verbosity() > 1)
0547 {
0548 std::cout << std::endl
0549 << "candidate " << ncandidates << " seed " << nseeds << " circle fit parameters: R=" << R << ", X0=" << x_center << ", Y0=" << y_center << std::endl;
0550 }
0551
0552
0553
0554 if (std::isnan(R))
0555 {
0556 continue;
0557 }
0558
0559 double init_QPt = 1. / (0.3 * R / 100. * get_Bz(x0, y0, z0));
0560
0561 double phi_first = atan2(y0, x0);
0562 if (Verbosity() > 1)
0563 {
0564 std::cout << "phi_first: " << phi_first << std::endl;
0565 }
0566 double phi_second = atan2(second_y, second_x);
0567 if (Verbosity() > 1)
0568 {
0569 std::cout << "phi_second: " << phi_second << std::endl;
0570 }
0571 double dphi = phi_second - phi_first;
0572 if (Verbosity() > 1)
0573 {
0574 std::cout << "dphi: " << dphi << std::endl;
0575 }
0576 if (dphi > M_PI)
0577 {
0578 dphi = 2 * M_PI - dphi;
0579 }
0580 if (dphi < -M_PI)
0581 {
0582 dphi = 2 * M_PI + dphi;
0583 }
0584 if (Verbosity() > 1)
0585 {
0586 std::cout << "corrected dphi: " << dphi << std::endl;
0587 }
0588 if ((dphi > 0. && x0 * x0 + y0 * y0 < second_x * second_x + second_y * second_y) ||
0589 (dphi < 0. && x0 * x0 + y0 * y0 > second_x * second_x + second_y * second_y))
0590 {
0591 init_QPt = -1 * init_QPt;
0592 }
0593 LogDebug("initial QPt: " << init_QPt << std::endl);
0594 trackSeed.SetQPt(init_QPt);
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609 GPUTPCTrackLinearisation trackLine(trackSeed);
0610 GPUTPCTrackParam::GPUTPCTrackFitParam fp{};
0611 trackSeed.CalculateFitParameters(fp);
0612
0613 LogDebug(std::endl
0614 << std::endl
0615 << "------------------------" << std::endl
0616 << "seed size: " << trackKeyChain.size() << std::endl
0617 << std::endl
0618 << std::endl);
0619 double current_phi = phi_first;
0620 bool filter_failed = false;
0621 keylist outputKeyChain = trackKeyChain;
0622 for (auto clusterkey = std::next(trackKeyChain.begin()); clusterkey != trackKeyChain.end(); ++clusterkey)
0623 {
0624 if (!FilterStep(*clusterkey, outputKeyChain, current_phi, trackSeed, fp, globalPositions))
0625 {
0626 if (Verbosity() > 0)
0627 {
0628 std::cout << "Kalman filter failed, exiting" << std::endl;
0629 }
0630 filter_failed = true;
0631 break;
0632 }
0633 }
0634 if (filter_failed)
0635 {
0636 continue;
0637 }
0638 if (Verbosity() > 0)
0639 {
0640 std::cout << "finished track\n";
0641 }
0642
0643 double track_phi = atan2(y, x);
0644
0645 if (Verbosity() > 1)
0646 {
0647 std::cout << "final QPt = " << trackSeed.GetQPt() << std::endl;
0648 }
0649
0650 double track_pt = fabs(1. / trackSeed.GetQPt());
0651 #if defined(_DEBUG_)
0652 double track_pY = track_pt * trackSeed.GetSinPhi();
0653 double track_pX = sqrt(track_pt * track_pt - track_pY * track_pY);
0654 double track_px = track_pX * cos(track_phi) - track_pY * sin(track_phi);
0655 double track_py = track_pX * sin(track_phi) + track_pY * cos(track_phi);
0656 double track_pz = track_pt * trackSeed.GetDzDs();
0657 #endif
0658 double track_pterr = sqrt(trackSeed.GetErr2QPt()) / (trackSeed.GetQPt() * trackSeed.GetQPt());
0659
0660
0661 LogDebug("track pt = " << track_pt << " +- " << track_pterr << std::endl);
0662 LogDebug("track ALICE p = (" << track_pX << ", " << track_pY << ", " << track_pz << ")" << std::endl);
0663 LogDebug("track p = (" << track_px << ", " << track_py << ", " << track_pz << ")" << std::endl);
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678 if (checknan(track_pt, "pT", nseeds))
0679 {
0680 continue;
0681 }
0682
0683 if (checknan(track_pterr, "pT err", nseeds))
0684 {
0685 continue;
0686 }
0687 LogDebug("Track pterr = " << track_pterr << std::endl);
0688 double track_x = trackSeed.GetX() * cos(track_phi) - trackSeed.GetY() * sin(track_phi);
0689 double track_y = trackSeed.GetX() * sin(track_phi) + trackSeed.GetY() * cos(track_phi);
0690 double track_z = trackSeed.GetZ();
0691 if (checknan(track_z, "z", nseeds))
0692 {
0693 continue;
0694 }
0695 double track_zerr = sqrt(trackSeed.GetErr2Z());
0696 if (checknan(track_zerr, "zerr", nseeds))
0697 {
0698 continue;
0699 }
0700 auto lcluster = _cluster_map->findCluster(trackKeyChain.back());
0701 const auto& lclusterglob = globalPositions.at(trackKeyChain.back());
0702 const float lclusterrad = sqrt(lclusterglob(0) * lclusterglob(0) + lclusterglob(1) * lclusterglob(1));
0703 double last_cluster_phierr = lcluster->getRPhiError() / lclusterrad;
0704 ;
0705
0706
0707 double track_phierr = sqrt(pow(last_cluster_phierr, 2) + (pow(trackSeed.GetX(), 2) * trackSeed.GetErr2Y()) /
0708 pow(pow(trackSeed.GetX(), 2) + pow(trackSeed.GetY(), 2), 2));
0709 if (checknan(track_phierr, "phierr", nseeds))
0710 {
0711 continue;
0712 }
0713 LogDebug("Track phi = " << atan2(track_py, track_px) << std::endl);
0714 LogDebug("Track phierr = " << track_phierr << std::endl);
0715 double track_curvature = trackSeed.GetKappa(_Bzconst * get_Bz(track_x, track_y, track_z));
0716 if (checknan(track_curvature, "curvature", nseeds))
0717 {
0718 continue;
0719 }
0720 double track_curverr = sqrt(trackSeed.GetErr2QPt()) * _Bzconst * get_Bz(track_x, track_y, track_z);
0721 if (checknan(track_curverr, "curvature error", nseeds))
0722 {
0723 continue;
0724 }
0725 TrackSeed_v2 track;
0726
0727 for (unsigned long j : outputKeyChain)
0728 {
0729 track.insert_cluster_key(j);
0730 }
0731
0732 int track_charge = 0;
0733 if (trackSeed.GetQPt() < 0)
0734 {
0735 track_charge = -1 * trackSeed.GetSignCosPhi();
0736 }
0737 else
0738 {
0739 track_charge = 1 * trackSeed.GetSignCosPhi();
0740 }
0741
0742 double sinphi = sin(track_phi);
0743 double c = cos(track_phi);
0744 double p = trackSeed.GetSinPhi();
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754 double d = trackSeed.GetDzDs();
0755 if (checknan(d, "ALICE dz/ds", nseeds))
0756 {
0757 continue;
0758 }
0759
0760
0761
0762
0763
0764
0765 track.set_qOverR(trackSeed.GetQPt() * (0.3 * _const_field) / 100.);
0766
0767
0768
0769 const double* cov = trackSeed.GetCov();
0770 bool cov_nan = false;
0771 for (int i = 0; i < 15; i++)
0772 {
0773 if (checknan(cov[i], "covariance element " + std::to_string(i), nseeds))
0774 {
0775 cov_nan = true;
0776 }
0777 }
0778 if (cov_nan)
0779 {
0780 continue;
0781 }
0782
0783 Eigen::Matrix<double, 5, 5> ecov;
0784 ecov(0, 0) = cov[0];
0785 ecov(0, 1) = cov[1];
0786 ecov(0, 2) = cov[2];
0787 ecov(0, 3) = cov[3];
0788 ecov(0, 4) = cov[4];
0789 ecov(1, 1) = cov[5];
0790 ecov(1, 2) = cov[6];
0791 ecov(1, 3) = cov[7];
0792 ecov(1, 4) = cov[8];
0793 ecov(2, 2) = cov[9];
0794 ecov(2, 3) = cov[10];
0795 ecov(2, 4) = cov[11];
0796 ecov(3, 3) = cov[12];
0797 ecov(3, 4) = cov[13];
0798 ecov(4, 4) = cov[14];
0799
0800 ecov(1, 0) = ecov(0, 1);
0801 ecov(2, 0) = ecov(0, 2);
0802 ecov(3, 0) = ecov(0, 3);
0803 ecov(4, 0) = ecov(0, 4);
0804 ecov(2, 1) = ecov(1, 2);
0805 ecov(3, 1) = ecov(1, 3);
0806 ecov(4, 1) = ecov(1, 4);
0807 ecov(3, 2) = ecov(2, 3);
0808 ecov(4, 2) = ecov(2, 4);
0809 ecov(4, 3) = ecov(3, 4);
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819 Eigen::Matrix<double, 6, 5> J;
0820 J(0, 0) = -sinphi;
0821 J(0, 1) = 0.;
0822 J(0, 2) = 0.;
0823 J(0, 3) = 0.;
0824 J(0, 4) = 0.;
0825
0826 J(1, 0) = c;
0827 J(1, 1) = 0.;
0828 J(1, 2) = 0.;
0829 J(1, 3) = 0.;
0830 J(1, 4) = 0.;
0831
0832 J(2, 0) = 0.;
0833 J(2, 1) = 1.;
0834 J(2, 2) = 0.;
0835 J(2, 3) = 0.;
0836 J(2, 4) = 0.;
0837
0838 J(3, 0) = 0.;
0839 J(3, 1) = 0.;
0840 J(3, 2) = -track_pt * (p * c / sqrt(1 - p * p) + sinphi);
0841 J(3, 3) = 0.;
0842 J(3, 4) = track_pt * track_pt * track_charge * (p * sinphi - c * sqrt(1 - p * p));
0843
0844 J(4, 0) = 0.;
0845 J(4, 1) = 0.;
0846 J(4, 2) = track_pt * (c - p * sinphi / sqrt(1 - p * p));
0847 J(4, 3) = 0.;
0848 J(4, 4) = -track_pt * track_pt * track_charge * (p * c + sinphi * sqrt(1 - p * p));
0849
0850 J(5, 0) = 0.;
0851 J(5, 1) = 0.;
0852 J(5, 2) = 0.;
0853 J(5, 3) = track_pt;
0854 J(5, 4) = -track_pt * track_pt * track_charge * d;
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870 Eigen::Matrix<double, 6, 6> scov = J * ecov * J.transpose();
0871 if (!covIsPosDef(scov))
0872 {
0873 repairCovariance(scov);
0874 }
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939 seeds_vector.push_back(track);
0940 alice_seeds_vector.push_back(trackSeed);
0941 trackChi2.push_back(trackSeed.GetChi2() / trackSeed.GetNDF());
0942
0943 ++nseeds;
0944 }
0945
0946
0947
0948 if (Verbosity() > 0)
0949 {
0950 std::cout << "number of seeds: " << nseeds << "\n";
0951 }
0952
0953 return std::make_pair(seeds_vector, alice_seeds_vector);
0954 }
0955
0956 bool ALICEKF::covIsPosDef(Eigen::Matrix<double, 6, 6>& cov) const
0957 {
0958
0959 Eigen::LLT<Eigen::Matrix<double, 6, 6>> chDec(cov);
0960
0961 return (chDec.info() != Eigen::NumericalIssue);
0962 }
0963
0964 void ALICEKF::repairCovariance(Eigen::Matrix<double, 6, 6>& cov) const
0965 {
0966 Eigen::Matrix<double, 6, 6> repaircov = cov;
0967
0968 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<double, 6, 6>> solver(repaircov);
0969 const Eigen::Matrix<double, 6, 1>& D = solver.eigenvalues();
0970 Eigen::Matrix<double, 6, 6> Q = solver.eigenvectors();
0971 Eigen::Matrix<double, 6, 1> Dp = D.cwiseMax(1e-15);
0972 Eigen::Matrix<double, 6, 6> Z = Q * Dp.asDiagonal() * Q.transpose();
0973
0974 for (int i = 0; i < 6; i++)
0975 {
0976 for (int j = 0; j < 6; j++)
0977 {
0978 cov(i, j) = Z(i, j);
0979 }
0980 }
0981 }
0982
0983 std::vector<double> ALICEKF::GetCircleClusterResiduals(const std::vector<std::pair<double, double>>& points, double R, double X0, double Y0) const
0984 {
0985 std::vector<double> residues;
0986 std::transform(points.begin(), points.end(), std::back_inserter(residues), [R, X0, Y0](const std::pair<double, double>& point)
0987 {
0988 double x = point.first;
0989 double y = point.second;
0990
0991
0992 return std::sqrt( square(x-X0) + square(y-Y0) ) - R; });
0993 return residues;
0994 }
0995
0996 std::vector<double> ALICEKF::GetLineClusterResiduals(const std::vector<std::pair<double, double>>& points, double A, double B) const
0997 {
0998 std::vector<double> residues;
0999
1000 std::transform(points.begin(), points.end(), std::back_inserter(residues), [A, B](const std::pair<double, double>& point)
1001 {
1002 double r = point.first;
1003 double z = point.second;
1004
1005
1006
1007 double a = -A;
1008 double b = 1.0;
1009 double c = -B;
1010 return std::abs(a*r+b*z+c)/sqrt(square(a)+square(b)); });
1011 return residues;
1012 }