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