File indexing completed on 2025-01-18 09:11:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "Acts/Geometry/Extent.hpp"
0013 #include "Acts/Seeding/SeedFilter.hpp"
0014 #include "Acts/Seeding/SeedFinder.hpp"
0015 #include "Acts/Seeding/SeedFinderGbtsConfig.hpp"
0016 #include "Acts/Seeding/SeedFinderUtils.hpp"
0017 #include "Acts/Utilities/BinningType.hpp"
0018
0019 #include <algorithm>
0020 #include <cmath>
0021 #include <fstream>
0022 #include <functional>
0023 #include <iostream>
0024 #include <list>
0025 #include <numbers>
0026 #include <numeric>
0027 #include <type_traits>
0028 #include <vector>
0029
0030
0031
0032 namespace Acts {
0033
0034 template <typename external_spacepoint_t>
0035 SeedFinderGbts<external_spacepoint_t>::SeedFinderGbts(
0036 const SeedFinderGbtsConfig<external_spacepoint_t>& config,
0037 const GbtsGeometry<external_spacepoint_t>& gbtsGeo,
0038 std::unique_ptr<const Acts::Logger> logger)
0039 : m_config(config),
0040 m_storage(
0041 std::make_unique<GbtsDataStorage<external_spacepoint_t>>(gbtsGeo)),
0042 m_logger(std::move(logger)) {}
0043
0044
0045 template <typename external_spacepoint_t>
0046 void SeedFinderGbts<external_spacepoint_t>::loadSpacePoints(
0047 const std::vector<GbtsSP<external_spacepoint_t>>& gbtsSPvect) {
0048 ACTS_VERBOSE("Loading space points");
0049 for (const auto& gbtssp : gbtsSPvect) {
0050 bool is_Pixel = gbtssp.isPixel();
0051 if (!is_Pixel) {
0052 continue;
0053 }
0054 m_storage->addSpacePoint(gbtssp, (m_config.m_useClusterWidth > 0));
0055 }
0056
0057 m_config.m_phiSliceWidth = 2 * std::numbers::pi / m_config.m_nMaxPhiSlice;
0058
0059 m_storage->sortByPhi();
0060
0061 m_storage->generatePhiIndexing(1.5 * m_config.m_phiSliceWidth);
0062 }
0063
0064 template <typename external_spacepoint_t>
0065 void SeedFinderGbts<external_spacepoint_t>::runGbts_TrackFinder(
0066 std::vector<GbtsTrigTracklet<external_spacepoint_t>>& vTracks,
0067 const Acts::RoiDescriptor& roi,
0068 const Acts::GbtsGeometry<external_spacepoint_t>& gbtsGeo) {
0069 ACTS_VERBOSE("Running GBTS Track Finder");
0070 const float min_z0 = roi.zedMinus();
0071 const float max_z0 = roi.zedPlus();
0072 const float cut_zMinU = min_z0 + m_config.maxOuterRadius * roi.dzdrMinus();
0073 const float cut_zMaxU = max_z0 + m_config.maxOuterRadius * roi.dzdrPlus();
0074 float m_minR_squ = m_config.m_tripletPtMin * m_config.m_tripletPtMin /
0075 std::pow(m_config.ptCoeff, 2);
0076 float m_maxCurv = m_config.ptCoeff / m_config.m_tripletPtMin;
0077 const float maxKappa_high_eta = 0.8 / m_minR_squ;
0078 const float maxKappa_low_eta = 0.6 / m_minR_squ;
0079
0080
0081
0082 int currentStage = 0;
0083
0084 const Acts::GbtsConnector& connector = *(gbtsGeo.connector());
0085
0086 std::vector<Acts::GbtsEdge<external_spacepoint_t>> edgeStorage;
0087
0088 edgeStorage.reserve(m_config.MaxEdges);
0089
0090 int nEdges = 0;
0091
0092 for (std::map<int, std::vector<GbtsConnector::LayerGroup>>::const_iterator
0093 it = connector.m_layerGroups.begin();
0094 it != connector.m_layerGroups.end(); ++it, currentStage++) {
0095
0096
0097 for (const auto& layerGroup : (*it).second) {
0098 unsigned int dst = layerGroup.m_dst;
0099
0100 const GbtsLayer<external_spacepoint_t>* pL1 =
0101 gbtsGeo.getGbtsLayerByKey(dst);
0102
0103 if (pL1 == nullptr) {
0104 continue;
0105 }
0106
0107 for (const auto& conn :
0108 layerGroup.m_sources) {
0109
0110 unsigned int src = conn->m_src;
0111
0112 const GbtsLayer<external_spacepoint_t>* pL2 =
0113 gbtsGeo.getGbtsLayerByKey(src);
0114
0115 if (pL2 == nullptr) {
0116 continue;
0117 }
0118 int nDstBins = pL1->m_bins.size();
0119 int nSrcBins = pL2->m_bins.size();
0120
0121 for (int b1 = 0; b1 < nDstBins; b1++) {
0122
0123 const GbtsEtaBin<external_spacepoint_t>& B1 =
0124 m_storage->getEtaBin(pL1->m_bins.at(b1));
0125
0126 if (B1.empty()) {
0127 continue;
0128 }
0129
0130 float rb1 = pL1->getMinBinRadius(b1);
0131
0132
0133
0134 for (int b2 = 0; b2 < nSrcBins; b2++) {
0135
0136 if (m_config.m_useEtaBinning && (nSrcBins + nDstBins > 2)) {
0137 if (conn->m_binTable[b1 + b2 * nDstBins] != 1) {
0138 continue;
0139 }
0140 }
0141
0142 const GbtsEtaBin<external_spacepoint_t>& B2 =
0143 m_storage->getEtaBin(pL2->m_bins.at(b2));
0144
0145 if (B2.empty()) {
0146 continue;
0147 }
0148
0149 float rb2 = pL2->getMaxBinRadius(b2);
0150
0151
0152
0153 float deltaPhi =
0154 0.5f *
0155 m_config
0156 .m_phiSliceWidth;
0157
0158 if (m_config.m_useEtaBinning) {
0159 deltaPhi = 0.001f + m_maxCurv * std::abs(rb2 - rb1);
0160 }
0161
0162 unsigned int first_it = 0;
0163 for (const auto& n1 : B1.m_vn) {
0164
0165 if (n1->m_in.size() >= MAX_SEG_PER_NODE) {
0166 continue;
0167 }
0168
0169 float r1 = n1->m_spGbts.SP->r();
0170 float x1 = n1->m_spGbts.SP->x();
0171 float y1 = n1->m_spGbts.SP->y();
0172 float z1 = n1->m_spGbts.SP->z();
0173 float phi1 = std::atan(x1 / y1);
0174
0175 float minPhi = phi1 - deltaPhi;
0176 float maxPhi = phi1 + deltaPhi;
0177
0178 for (unsigned int n2PhiIdx = first_it;
0179 n2PhiIdx < B2.m_vPhiNodes.size();
0180 n2PhiIdx++) {
0181
0182 float phi2 = B2.m_vPhiNodes.at(n2PhiIdx).first;
0183
0184 if (phi2 < minPhi) {
0185 first_it = n2PhiIdx;
0186 continue;
0187 }
0188 if (phi2 > maxPhi) {
0189 break;
0190 }
0191
0192 GbtsNode<external_spacepoint_t>* n2 =
0193 B2.m_vn.at(B2.m_vPhiNodes.at(n2PhiIdx).second).get();
0194
0195 if (n2->m_out.size() >= MAX_SEG_PER_NODE) {
0196 continue;
0197 }
0198 if (n2->isFull()) {
0199 continue;
0200 }
0201
0202 float r2 = n2->m_spGbts.SP->r();
0203
0204 float dr = r2 - r1;
0205
0206 if (dr < m_config.m_minDeltaRadius) {
0207 continue;
0208 }
0209
0210 float z2 = n2->m_spGbts.SP->z();
0211
0212 float dz = z2 - z1;
0213 float tau = dz / dr;
0214 float ftau = std::abs(tau);
0215 if (ftau > 36.0) {
0216 continue;
0217 }
0218
0219 if (ftau < n1->m_minCutOnTau) {
0220 continue;
0221 }
0222 if (ftau < n2->m_minCutOnTau) {
0223 continue;
0224 }
0225 if (ftau > n1->m_maxCutOnTau) {
0226 continue;
0227 }
0228 if (ftau > n2->m_maxCutOnTau) {
0229 continue;
0230 }
0231
0232 if (m_config.m_doubletFilterRZ) {
0233 float z0 = z1 - r1 * tau;
0234
0235 if (z0 < min_z0 || z0 > max_z0) {
0236 continue;
0237 }
0238
0239 float zouter = z0 + m_config.maxOuterRadius * tau;
0240
0241 if (zouter < cut_zMinU || zouter > cut_zMaxU) {
0242 continue;
0243 }
0244 }
0245
0246 float dx = n2->m_spGbts.SP->x() - x1;
0247 float dy = n2->m_spGbts.SP->y() - y1;
0248
0249 float L2 = 1 / (dx * dx + dy * dy);
0250
0251 float D =
0252 (n2->m_spGbts.SP->y() * x1 - y1 * n2->m_spGbts.SP->x()) /
0253 (r1 * r2);
0254
0255 float kappa = D * D * L2;
0256
0257 if (ftau < 4.0) {
0258 if (kappa > maxKappa_low_eta) {
0259 continue;
0260 }
0261
0262 } else {
0263 if (kappa > maxKappa_high_eta) {
0264 continue;
0265 }
0266 }
0267
0268
0269
0270 float exp_eta = std::sqrt(1 + tau * tau) - tau;
0271
0272 bool isGood =
0273 n2->m_in.size() <=
0274 2;
0275
0276 if (!isGood) {
0277 float uat_1 = 1.0f / exp_eta;
0278
0279 for (const auto& n2_in_idx : n2->m_in) {
0280 float tau2 = edgeStorage.at(n2_in_idx).m_p[0];
0281 float tau_ratio = tau2 * uat_1 - 1.0f;
0282
0283
0284 if (std::abs(tau_ratio) > m_config.cut_tau_ratio_max) {
0285 continue;
0286 }
0287
0288
0289 isGood = true;
0290 break;
0291 }
0292 }
0293 if (!isGood) {
0294 continue;
0295 }
0296
0297 float curv = D * std::sqrt(L2);
0298 float dPhi2 = std::asin(curv * r2);
0299 float dPhi1 = std::asin(curv * r1);
0300
0301 if (nEdges < m_config.MaxEdges) {
0302 edgeStorage.emplace_back(n1.get(), n2, exp_eta, curv,
0303 phi1 + dPhi1, phi2 + dPhi2);
0304
0305 n1->addIn(nEdges);
0306 n2->addOut(nEdges);
0307
0308 nEdges++;
0309 }
0310 }
0311 }
0312 }
0313 }
0314 }
0315 }
0316 }
0317
0318 std::vector<const GbtsNode<external_spacepoint_t>*> vNodes;
0319
0320 m_storage->getConnectingNodes(vNodes);
0321
0322 if (vNodes.empty()) {
0323 ACTS_VERBOSE("No nodes");
0324 return;
0325 }
0326
0327 int nNodes = vNodes.size();
0328
0329 for (int nodeIdx = 0; nodeIdx < nNodes; nodeIdx++) {
0330 const GbtsNode<external_spacepoint_t>& pN = *vNodes.at(nodeIdx);
0331
0332 std::vector<std::pair<float, int>> in_sort, out_sort;
0333 in_sort.resize(pN.m_in.size());
0334 out_sort.resize(pN.m_out.size());
0335
0336 for (int inIdx = 0; inIdx < static_cast<int>(pN.m_in.size()); inIdx++) {
0337 int inEdgeIdx = pN.m_in.at(inIdx);
0338 Acts::GbtsEdge<external_spacepoint_t>* pS = &(edgeStorage.at(inEdgeIdx));
0339 in_sort[inIdx].second = inEdgeIdx;
0340 in_sort[inIdx].first = pS->m_p[0];
0341 }
0342 for (int outIdx = 0; outIdx < static_cast<int>(pN.m_out.size()); outIdx++) {
0343 int outEdgeIdx = pN.m_out.at(outIdx);
0344 Acts::GbtsEdge<external_spacepoint_t>* pS = &(edgeStorage.at(outEdgeIdx));
0345 out_sort[outIdx].second = outEdgeIdx;
0346 out_sort[outIdx].first = pS->m_p[0];
0347 }
0348
0349 std::ranges::sort(in_sort);
0350 std::ranges::sort(out_sort);
0351
0352 unsigned int last_out = 0;
0353
0354 for (unsigned int in_idx = 0; in_idx < in_sort.size();
0355 in_idx++) {
0356
0357 int inEdgeIdx = in_sort[in_idx].second;
0358
0359 Acts::GbtsEdge<external_spacepoint_t>* pS = &(edgeStorage.at(inEdgeIdx));
0360
0361 pS->m_nNei = 0;
0362 float tau1 = pS->m_p[0];
0363 float uat_1 = 1.0f / tau1;
0364 float curv1 = pS->m_p[1];
0365 float Phi1 = pS->m_p[2];
0366
0367 for (unsigned int out_idx = last_out; out_idx < out_sort.size();
0368 out_idx++) {
0369 int outEdgeIdx = out_sort[out_idx].second;
0370
0371 Acts::GbtsEdge<external_spacepoint_t>* pNS =
0372 &(edgeStorage.at(outEdgeIdx));
0373
0374 float tau2 = pNS->m_p[0];
0375 float tau_ratio = tau2 * uat_1 - 1.0f;
0376
0377 if (tau_ratio < -m_config.cut_tau_ratio_max) {
0378 last_out = out_idx;
0379 continue;
0380 }
0381 if (tau_ratio > m_config.cut_tau_ratio_max) {
0382 break;
0383 }
0384
0385 float dPhi = pNS->m_p[3] - Phi1;
0386
0387 if (dPhi < -std::numbers::pi_v<float>) {
0388 dPhi += static_cast<float>(2 * std::numbers::pi);
0389 } else if (dPhi > std::numbers::pi_v<float>) {
0390 dPhi -= static_cast<float>(2 * std::numbers::pi);
0391 }
0392
0393 if (dPhi < -m_config.cut_dphi_max || dPhi > m_config.cut_dphi_max) {
0394 continue;
0395 }
0396
0397 float curv2 = pNS->m_p[1];
0398 float dcurv = curv2 - curv1;
0399
0400 if (dcurv < -m_config.cut_dcurv_max || dcurv > m_config.cut_dcurv_max) {
0401 continue;
0402 }
0403
0404 pS->m_vNei[pS->m_nNei++] = outEdgeIdx;
0405 if (pS->m_nNei >= N_SEG_CONNS) {
0406 break;
0407 }
0408 }
0409 }
0410 }
0411
0412 const int maxIter = 15;
0413
0414 int maxLevel = 0;
0415
0416 int iter = 0;
0417
0418 std::vector<Acts::GbtsEdge<external_spacepoint_t>*> v_old;
0419
0420 for (int edgeIndex = 0; edgeIndex < nEdges; edgeIndex++) {
0421 Acts::GbtsEdge<external_spacepoint_t>* pS = &(edgeStorage.at(edgeIndex));
0422 if (pS->m_nNei == 0) {
0423 continue;
0424 }
0425 v_old.push_back(pS);
0426
0427 }
0428
0429 for (; iter < maxIter; iter++) {
0430
0431 std::vector<Acts::GbtsEdge<external_spacepoint_t>*> v_new;
0432 v_new.clear();
0433
0434 for (auto pS : v_old) {
0435 int next_level = pS->m_level;
0436
0437 for (int nIdx = 0; nIdx < pS->m_nNei; nIdx++) {
0438 unsigned int nextEdgeIdx = pS->m_vNei[nIdx];
0439
0440 Acts::GbtsEdge<external_spacepoint_t>* pN =
0441 &(edgeStorage.at(nextEdgeIdx));
0442
0443 if (pS->m_level == pN->m_level) {
0444 next_level = pS->m_level + 1;
0445 v_new.push_back(pS);
0446 break;
0447 }
0448 }
0449
0450 pS->m_next = next_level;
0451 }
0452
0453
0454 int nChanges = 0;
0455
0456 for (auto pS : v_new) {
0457 if (pS->m_next != pS->m_level) {
0458 nChanges++;
0459 pS->m_level = pS->m_next;
0460 if (maxLevel < pS->m_level) {
0461 maxLevel = pS->m_level;
0462 }
0463 }
0464 }
0465
0466 if (nChanges == 0) {
0467 break;
0468 }
0469
0470 v_old = std::move(v_new);
0471 v_new.clear();
0472 }
0473
0474 int minLevel = 3;
0475
0476 std::vector<Acts::GbtsEdge<external_spacepoint_t>*> vSeeds;
0477
0478 vSeeds.reserve(m_config.MaxEdges / 2);
0479
0480 for (int edgeIndex = 0; edgeIndex < nEdges; edgeIndex++) {
0481 Acts::GbtsEdge<external_spacepoint_t>* pS = &(edgeStorage.at(edgeIndex));
0482
0483 if (pS->m_level < minLevel) {
0484 continue;
0485 }
0486
0487 vSeeds.push_back(pS);
0488 }
0489
0490 m_triplets.clear();
0491
0492 std::ranges::sort(
0493 vSeeds, typename Acts::GbtsEdge<external_spacepoint_t>::CompareLevel());
0494
0495 if (vSeeds.empty()) {
0496 return;
0497 }
0498
0499
0500
0501 GbtsTrackingFilter<external_spacepoint_t> tFilter(
0502 m_config.m_layerGeometry, edgeStorage,
0503 logger().cloneWithSuffix("GbtsFilter"));
0504
0505 for (auto pS : vSeeds) {
0506 if (pS->m_level == -1) {
0507 continue;
0508 }
0509
0510 GbtsEdgeState<external_spacepoint_t> rs(false);
0511
0512 tFilter.followTrack(pS, rs);
0513
0514 if (!rs.m_initialized) {
0515 continue;
0516 }
0517
0518 if (static_cast<int>(rs.m_vs.size()) < minLevel) {
0519 continue;
0520 }
0521
0522 std::vector<const GbtsSP<external_spacepoint_t>*> vSP;
0523
0524 for (typename std::vector<
0525 Acts::GbtsEdge<external_spacepoint_t>*>::reverse_iterator sIt =
0526 rs.m_vs.rbegin();
0527 sIt != rs.m_vs.rend(); ++sIt) {
0528 (*sIt)->m_level = -1;
0529
0530 if (sIt == rs.m_vs.rbegin()) {
0531 vSP.push_back(&(*sIt)->m_n1->m_spGbts);
0532 }
0533 vSP.push_back(&(*sIt)->m_n2->m_spGbts);
0534 }
0535
0536 if (vSP.size() < 3) {
0537 continue;
0538 }
0539
0540
0541
0542 unsigned int nTriplets = 0;
0543
0544 std::vector<TrigInDetTriplet<external_spacepoint_t>> output;
0545
0546 for (unsigned int idx_m = 1; idx_m < vSP.size() - 1; idx_m++) {
0547 const GbtsSP<external_spacepoint_t>& spM = *vSP.at(idx_m);
0548 const double pS_r = spM.SP->r();
0549 const double pS_x = spM.SP->x();
0550 const double pS_y = spM.SP->y();
0551 const double cosA = pS_x / pS_r;
0552 const double sinA = pS_y / pS_r;
0553
0554 for (unsigned int idx_o = idx_m + 1; idx_o < vSP.size(); idx_o++) {
0555 const GbtsSP<external_spacepoint_t>& spO = *vSP.at(idx_o);
0556
0557 double dx = spO.SP->x() - pS_x;
0558 double dy = spO.SP->y() - pS_y;
0559 double R2inv = 1.0 / (dx * dx + dy * dy);
0560 double xn = dx * cosA + dy * sinA;
0561 double yn = -dx * sinA + dy * cosA;
0562
0563 const double uo = xn * R2inv;
0564 const double vo = yn * R2inv;
0565
0566 for (unsigned int idx_i = 0; idx_i < idx_m; idx_i++) {
0567 const GbtsSP<external_spacepoint_t>& spI = *vSP.at(idx_i);
0568
0569 dx = spI.SP->x() - pS_x;
0570 dy = spI.SP->y() - pS_y;
0571 R2inv = 1.0 / (dx * dx + dy * dy);
0572
0573 xn = dx * cosA + dy * sinA;
0574 yn = -dx * sinA + dy * cosA;
0575
0576 const double ui = xn * R2inv;
0577 const double vi = yn * R2inv;
0578
0579
0580
0581 const double du = uo - ui;
0582 if (du == 0.0) {
0583 continue;
0584 }
0585 const double A = (vo - vi) / du;
0586 const double B = vi - A * ui;
0587
0588 if ((1 + A * A) < (B * B) * m_minR_squ) {
0589 continue;
0590 }
0591
0592
0593
0594 const double fabs_d0 = std::abs(pS_r * (B * pS_r - A));
0595
0596 if (fabs_d0 > m_config.m_tripletD0Max) {
0597 continue;
0598 }
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614 const double Q = fabs_d0 * fabs_d0;
0615
0616 output.emplace_back(spI, spM, spO, Q);
0617
0618 nTriplets++;
0619
0620 if (nTriplets >= m_config.m_maxTripletBufferLength) {
0621 break;
0622 }
0623 }
0624 if (nTriplets >= m_config.m_maxTripletBufferLength) {
0625 break;
0626 }
0627 }
0628 if (nTriplets >= m_config.m_maxTripletBufferLength) {
0629 break;
0630 }
0631 }
0632
0633 if (output.empty()) {
0634 continue;
0635 }
0636
0637 vTracks.emplace_back(vSP, output);
0638 }
0639 }
0640
0641 template <typename external_spacepoint_t>
0642 template <typename output_container_t>
0643 void SeedFinderGbts<external_spacepoint_t>::createSeeds(
0644 const Acts::RoiDescriptor& roi,
0645 const Acts::GbtsGeometry<external_spacepoint_t>& gbtsGeo,
0646 output_container_t& out_cont) {
0647 ACTS_VERBOSE("Creating seeds");
0648 std::vector<GbtsTrigTracklet<external_spacepoint_t>>
0649 vTracks;
0650
0651 vTracks.reserve(5000);
0652
0653 runGbts_TrackFinder(vTracks, roi, gbtsGeo);
0654
0655 if (vTracks.empty()) {
0656 return;
0657 }
0658
0659 m_triplets.clear();
0660
0661 for (auto& track : vTracks) {
0662 for (auto& seed : track.m_seeds) {
0663
0664 float newQ = seed.Q();
0665 if (m_config.m_LRTmode) {
0666
0667 if (seed.s1().isPixel()) {
0668 newQ += 1000;
0669 }
0670 if (seed.s2().isPixel()) {
0671 newQ += 1000;
0672 }
0673 if (seed.s3().isPixel()) {
0674 newQ += 1000;
0675 }
0676 } else {
0677
0678
0679 if (seed.s3().isSCT()) {
0680 newQ += seed.s1().isSCT() ? 1000.0 : 10000.0;
0681 }
0682 }
0683 seed.Q(newQ);
0684 m_triplets.emplace_back(seed);
0685 }
0686 }
0687 vTracks.clear();
0688
0689 for (auto& triplet : m_triplets) {
0690 const external_spacepoint_t* S1 =
0691 triplet.s1().SP;
0692 const external_spacepoint_t* S2 = triplet.s2().SP;
0693 const external_spacepoint_t* S3 = triplet.s3().SP;
0694
0695
0696 float Vertex = 0;
0697 float Quality = triplet.Q();
0698
0699 out_cont.emplace_back(*S1, *S2, *S3);
0700 out_cont.back().setVertexZ(Vertex);
0701 out_cont.back().setQuality(Quality);
0702 }
0703 }
0704
0705
0706 template <typename external_spacepoint_t>
0707 std::vector<Seed<external_spacepoint_t>>
0708 SeedFinderGbts<external_spacepoint_t>::createSeeds(
0709 const Acts::RoiDescriptor& roi,
0710 const Acts::GbtsGeometry<external_spacepoint_t>& gbtsGeo) {
0711 std::vector<seed_t> r;
0712 createSeeds(roi, gbtsGeo, r);
0713 return r;
0714 }
0715
0716 }