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