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