File indexing completed on 2026-09-01 08:38:57
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Seeding/SeedFinder.hpp"
0012
0013 #include "Acts/Utilities/MathHelpers.hpp"
0014
0015 #include <algorithm>
0016 #include <cmath>
0017
0018 namespace Acts {
0019
0020 template <typename external_space_point_t, typename grid_t, typename platform_t>
0021 SeedFinder<external_space_point_t, grid_t, platform_t>::SeedFinder(
0022 const SeedFinderConfig<external_space_point_t>& config,
0023 std::unique_ptr<const Logger> logger)
0024 : m_config(config), m_logger(std::move(logger)) {
0025 if (std::isnan(config.deltaRMaxTopSP)) {
0026 throw std::runtime_error("Value of deltaRMaxTopSP was not initialised");
0027 }
0028 if (std::isnan(config.deltaRMinTopSP)) {
0029 throw std::runtime_error("Value of deltaRMinTopSP was not initialised");
0030 }
0031 if (std::isnan(config.deltaRMaxBottomSP)) {
0032 throw std::runtime_error("Value of deltaRMaxBottomSP was not initialised");
0033 }
0034 if (std::isnan(config.deltaRMinBottomSP)) {
0035 throw std::runtime_error("Value of deltaRMinBottomSP was not initialised");
0036 }
0037 }
0038
0039 template <typename external_space_point_t, typename grid_t, typename platform_t>
0040 template <typename container_t, GridBinCollection sp_range_t>
0041 requires CollectionStoresSeedsTo<container_t, external_space_point_t, 3ul>
0042 void SeedFinder<external_space_point_t, grid_t, platform_t>::
0043 createSeedsForGroup(const SeedFinderOptions& options, SeedingState& state,
0044 const grid_t& grid, container_t& outputCollection,
0045 const sp_range_t& bottomSPsIdx,
0046 const std::size_t middleSPsIdx,
0047 const sp_range_t& topSPsIdx,
0048 const Range1D<float>& rMiddleSPRange) const {
0049
0050 const std::size_t max_num_seeds_per_spm =
0051 m_config.seedFilter->getSeedFilterConfig().maxSeedsPerSpMConf;
0052 const std::size_t max_num_quality_seeds_per_spm =
0053 m_config.seedFilter->getSeedFilterConfig().maxQualitySeedsPerSpMConf;
0054
0055 state.candidatesCollector.setMaxElements(max_num_seeds_per_spm,
0056 max_num_quality_seeds_per_spm);
0057
0058
0059 if (bottomSPsIdx.size() == 0 || topSPsIdx.size() == 0) {
0060 return;
0061 }
0062
0063
0064 const std::vector<const external_space_point_t*>& middleSPs =
0065 grid.at(middleSPsIdx);
0066
0067 if (middleSPs.empty()) {
0068 return;
0069 }
0070
0071
0072
0073 state.bottomNeighbours.clear();
0074 state.topNeighbours.clear();
0075
0076
0077
0078 for (const std::size_t idx : bottomSPsIdx) {
0079
0080 if (grid.at(idx).size() == 0) {
0081 continue;
0082 }
0083 state.bottomNeighbours.emplace_back(
0084 grid, idx, middleSPs.front()->radius() - m_config.deltaRMaxBottomSP);
0085 }
0086
0087 if (state.bottomNeighbours.size() == 0) {
0088 return;
0089 }
0090
0091
0092 for (const std::size_t idx : topSPsIdx) {
0093
0094 if (grid.at(idx).size() == 0) {
0095 continue;
0096 }
0097 state.topNeighbours.emplace_back(
0098 grid, idx, middleSPs.front()->radius() + m_config.deltaRMinTopSP);
0099 }
0100
0101 if (state.topNeighbours.size() == 0) {
0102 return;
0103 }
0104
0105
0106
0107 auto [minRadiusRangeForMiddle, maxRadiusRangeForMiddle] =
0108 retrieveRadiusRangeForMiddle(*middleSPs.front(), rMiddleSPRange);
0109 ACTS_VERBOSE("Current global bin: " << middleSPsIdx << ", z value of "
0110 << middleSPs.front()->z());
0111 ACTS_VERBOSE("Validity range (radius) for the middle space point is ["
0112 << minRadiusRangeForMiddle << ", " << maxRadiusRangeForMiddle
0113 << "]");
0114
0115 for (const external_space_point_t* spM : middleSPs) {
0116 const float rM = spM->radius();
0117
0118
0119 if (rM < minRadiusRangeForMiddle) {
0120 continue;
0121 }
0122 if (rM > maxRadiusRangeForMiddle) {
0123
0124 break;
0125 }
0126
0127 const float zM = spM->z();
0128 const float uIP = -1 / rM;
0129 const float cosPhiM = -spM->x() * uIP;
0130 const float sinPhiM = -spM->y() * uIP;
0131 const float uIP2 = uIP * uIP;
0132
0133
0134 getCompatibleDoublets<SpacePointCandidateType::eTop>(
0135 options, grid, state.spacePointMutableData, state.topNeighbours, *spM,
0136 state.linCircleTop, state.compatTopSP, m_config.deltaRMinTopSP,
0137 m_config.deltaRMaxTopSP, uIP, uIP2, cosPhiM, sinPhiM);
0138
0139
0140 if (state.compatTopSP.empty()) {
0141 ACTS_VERBOSE("No compatible Tops, moving to next middle candidate");
0142 continue;
0143 }
0144
0145
0146 SeedFilterState seedFilterState;
0147 if (m_config.seedConfirmation) {
0148
0149 SeedConfirmationRangeConfig seedConfRange =
0150 (zM > m_config.centralSeedConfirmationRange.zMaxSeedConf ||
0151 zM < m_config.centralSeedConfirmationRange.zMinSeedConf)
0152 ? m_config.forwardSeedConfirmationRange
0153 : m_config.centralSeedConfirmationRange;
0154
0155
0156 seedFilterState.nTopSeedConf = rM > seedConfRange.rMaxSeedConf
0157 ? seedConfRange.nTopForLargeR
0158 : seedConfRange.nTopForSmallR;
0159
0160 seedFilterState.rMaxSeedConf = seedConfRange.rMaxSeedConf;
0161
0162 if (state.compatTopSP.size() < seedFilterState.nTopSeedConf) {
0163 ACTS_VERBOSE(
0164 "Number of top SPs is "
0165 << state.compatTopSP.size()
0166 << " and is smaller than minimum, moving to next middle candidate");
0167 continue;
0168 }
0169 }
0170
0171
0172 getCompatibleDoublets<SpacePointCandidateType::eBottom>(
0173 options, grid, state.spacePointMutableData, state.bottomNeighbours,
0174 *spM, state.linCircleBottom, state.compatBottomSP,
0175 m_config.deltaRMinBottomSP, m_config.deltaRMaxBottomSP, uIP, uIP2,
0176 cosPhiM, sinPhiM);
0177
0178
0179 if (state.compatBottomSP.empty()) {
0180 ACTS_VERBOSE("No compatible Bottoms, moving to next middle candidate");
0181 continue;
0182 }
0183
0184 ACTS_VERBOSE("Candidates: " << state.compatBottomSP.size()
0185 << " bottoms and " << state.compatTopSP.size()
0186 << " tops for middle candidate indexed "
0187 << spM->index());
0188
0189 if (m_config.useDetailedDoubleMeasurementInfo) {
0190 filterCandidates<DetectorMeasurementInfo::eDetailed>(
0191 *spM, options, seedFilterState, state);
0192 } else {
0193 filterCandidates<DetectorMeasurementInfo::eDefault>(
0194 *spM, options, seedFilterState, state);
0195 }
0196
0197 m_config.seedFilter->filterSeeds_1SpFixed(state.spacePointMutableData,
0198 state.candidatesCollector,
0199 outputCollection);
0200
0201 }
0202 }
0203
0204 template <typename external_space_point_t, typename grid_t, typename platform_t>
0205 template <SpacePointCandidateType candidateType, typename out_range_t>
0206 inline void
0207 SeedFinder<external_space_point_t, grid_t, platform_t>::getCompatibleDoublets(
0208 const SeedFinderOptions& options, const grid_t& grid,
0209 SpacePointMutableData& mutableData,
0210 boost::container::small_vector<Neighbour<grid_t>, ipow(3, grid_t::DIM)>&
0211 otherSPsNeighbours,
0212 const external_space_point_t& mediumSP,
0213 std::vector<LinCircle>& linCircleVec, out_range_t& outVec,
0214 const float deltaRMinSP, const float deltaRMaxSP, const float uIP,
0215 const float uIP2, const float cosPhiM, const float sinPhiM) const {
0216 float impactMax = m_config.impactMax;
0217
0218 constexpr bool isBottomCandidate =
0219 candidateType == SpacePointCandidateType::eBottom;
0220
0221 if constexpr (isBottomCandidate) {
0222 impactMax = -impactMax;
0223 }
0224
0225 outVec.clear();
0226 linCircleVec.clear();
0227
0228
0229 std::size_t nsp = 0;
0230 for (const auto& otherSPCol : otherSPsNeighbours) {
0231 nsp += grid.at(otherSPCol.index).size();
0232 }
0233
0234 linCircleVec.reserve(nsp);
0235 outVec.reserve(nsp);
0236
0237 const float rM = mediumSP.radius();
0238 const float xM = mediumSP.x();
0239 const float yM = mediumSP.y();
0240 const float zM = mediumSP.z();
0241 const float varianceRM = mediumSP.varianceR();
0242 const float varianceZM = mediumSP.varianceZ();
0243
0244 float vIPAbs = 0;
0245 if (m_config.interactionPointCut) {
0246
0247 vIPAbs = impactMax * uIP2;
0248 }
0249
0250 float deltaR = 0;
0251 float deltaZ = 0;
0252
0253 const auto outsideRangeCheck = [](const float value, const float min,
0254 const float max) -> bool {
0255
0256
0257 return static_cast<bool>(static_cast<int>(value < min) |
0258 static_cast<int>(value > max));
0259 };
0260
0261 for (auto& otherSPCol : otherSPsNeighbours) {
0262 const std::vector<const external_space_point_t*>& otherSPs =
0263 grid.at(otherSPCol.index);
0264 if (otherSPs.empty()) {
0265 continue;
0266 }
0267
0268
0269
0270 auto min_itr = otherSPCol.itr;
0271
0272
0273
0274 for (; min_itr != otherSPs.end(); ++min_itr) {
0275 const external_space_point_t* otherSP = *min_itr;
0276 if constexpr (candidateType == SpacePointCandidateType::eBottom) {
0277
0278 if ((rM - otherSP->radius()) <= deltaRMaxSP) {
0279 break;
0280 }
0281 } else {
0282
0283 if ((otherSP->radius() - rM) >= deltaRMinSP) {
0284 break;
0285 }
0286 }
0287 }
0288
0289
0290
0291 otherSPCol.itr = min_itr;
0292
0293 for (; min_itr != otherSPs.end(); ++min_itr) {
0294 const external_space_point_t* otherSP = *min_itr;
0295
0296 if constexpr (isBottomCandidate) {
0297 deltaR = (rM - otherSP->radius());
0298
0299
0300 if (deltaR < deltaRMinSP) {
0301 break;
0302 }
0303 } else {
0304 deltaR = (otherSP->radius() - rM);
0305
0306
0307 if (deltaR > deltaRMaxSP) {
0308 break;
0309 }
0310 }
0311
0312 if constexpr (isBottomCandidate) {
0313 deltaZ = (zM - otherSP->z());
0314 } else {
0315 deltaZ = (otherSP->z() - zM);
0316 }
0317
0318
0319
0320
0321
0322 const float zOriginTimesDeltaR = (zM * deltaR - rM * deltaZ);
0323
0324 if (outsideRangeCheck(zOriginTimesDeltaR,
0325 m_config.collisionRegionMin * deltaR,
0326 m_config.collisionRegionMax * deltaR)) {
0327 continue;
0328 }
0329
0330
0331
0332
0333
0334 if (!m_config.interactionPointCut) {
0335
0336
0337
0338 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0339 m_config.cotThetaMax * deltaR)) {
0340 continue;
0341 }
0342
0343 if (outsideRangeCheck(deltaZ, -m_config.deltaZMax,
0344 m_config.deltaZMax)) {
0345 continue;
0346 }
0347
0348
0349 const float deltaX = otherSP->x() - xM;
0350 const float deltaY = otherSP->y() - yM;
0351
0352 const float xNewFrame = deltaX * cosPhiM + deltaY * sinPhiM;
0353 const float yNewFrame = deltaY * cosPhiM - deltaX * sinPhiM;
0354
0355 const float deltaR2 = (deltaX * deltaX + deltaY * deltaY);
0356 const float iDeltaR2 = 1 / deltaR2;
0357
0358 const float uT = xNewFrame * iDeltaR2;
0359 const float vT = yNewFrame * iDeltaR2;
0360
0361 const float iDeltaR = std::sqrt(iDeltaR2);
0362 const float cotTheta = deltaZ * iDeltaR;
0363
0364 const float Er =
0365 ((varianceZM + otherSP->varianceZ()) +
0366 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0367 iDeltaR2;
0368
0369
0370 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0371 yNewFrame);
0372
0373 mutableData.setDeltaR(otherSP->index(),
0374 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0375 outVec.push_back(otherSP);
0376 continue;
0377 }
0378
0379
0380 const float deltaX = otherSP->x() - xM;
0381 const float deltaY = otherSP->y() - yM;
0382
0383 const float xNewFrame = deltaX * cosPhiM + deltaY * sinPhiM;
0384 const float yNewFrame = deltaY * cosPhiM - deltaX * sinPhiM;
0385
0386 const float deltaR2 = deltaX * deltaX + deltaY * deltaY;
0387 const float iDeltaR2 = 1 / deltaR2;
0388
0389 const float uT = xNewFrame * iDeltaR2;
0390 const float vT = yNewFrame * iDeltaR2;
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401 if (std::abs(rM * yNewFrame) <= impactMax * xNewFrame) {
0402
0403
0404
0405 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0406 m_config.cotThetaMax * deltaR)) {
0407 continue;
0408 }
0409
0410 const float iDeltaR = std::sqrt(iDeltaR2);
0411 const float cotTheta = deltaZ * iDeltaR;
0412
0413
0414
0415 if (!m_config.experimentCuts(mediumSP, *otherSP, cotTheta,
0416 isBottomCandidate)) {
0417 continue;
0418 }
0419
0420 const float Er =
0421 ((varianceZM + otherSP->varianceZ()) +
0422 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0423 iDeltaR2;
0424
0425
0426 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0427 yNewFrame);
0428 mutableData.setDeltaR(otherSP->index(),
0429 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0430 outVec.emplace_back(otherSP);
0431 continue;
0432 }
0433
0434
0435
0436 const float vIP = (yNewFrame > 0) ? -vIPAbs : vIPAbs;
0437
0438
0439
0440
0441 const float aCoef = (vT - vIP) / (uT - uIP);
0442 const float bCoef = vIP - aCoef * uIP;
0443
0444
0445
0446 if ((bCoef * bCoef) * options.minHelixDiameter2 > (1 + aCoef * aCoef)) {
0447 continue;
0448 }
0449
0450
0451
0452
0453 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0454 m_config.cotThetaMax * deltaR)) {
0455 continue;
0456 }
0457
0458 const float iDeltaR = std::sqrt(iDeltaR2);
0459 const float cotTheta = deltaZ * iDeltaR;
0460
0461
0462
0463 if (!m_config.experimentCuts(mediumSP, *otherSP, cotTheta,
0464 isBottomCandidate)) {
0465 continue;
0466 }
0467
0468 const float Er =
0469 ((varianceZM + otherSP->varianceZ()) +
0470 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0471 iDeltaR2;
0472
0473
0474 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0475 yNewFrame);
0476
0477 mutableData.setDeltaR(otherSP->index(),
0478 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0479 outVec.emplace_back(otherSP);
0480 }
0481 }
0482 }
0483
0484 template <typename external_space_point_t, typename grid_t, typename platform_t>
0485 template <DetectorMeasurementInfo detailedMeasurement>
0486 inline void
0487 SeedFinder<external_space_point_t, grid_t, platform_t>::filterCandidates(
0488 const external_space_point_t& spM, const SeedFinderOptions& options,
0489 SeedFilterState& seedFilterState, SeedingState& state) const {
0490 const float rM = spM.radius();
0491 const float cosPhiM = spM.x() / rM;
0492 const float sinPhiM = spM.y() / rM;
0493 const float varianceRM = spM.varianceR();
0494 const float varianceZM = spM.varianceZ();
0495
0496 std::size_t numTopSp = state.compatTopSP.size();
0497
0498
0499 std::vector<std::uint32_t> sortedBottoms(state.compatBottomSP.size());
0500 for (std::uint32_t i = 0; i < sortedBottoms.size(); ++i) {
0501 sortedBottoms[i] = i;
0502 }
0503 std::vector<std::uint32_t> sortedTops(state.linCircleTop.size());
0504 for (std::uint32_t i = 0; i < sortedTops.size(); ++i) {
0505 sortedTops[i] = i;
0506 }
0507
0508 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDefault) {
0509 std::vector<float> cotThetaBottoms(state.compatBottomSP.size());
0510 for (std::uint32_t i = 0; i < sortedBottoms.size(); ++i) {
0511 cotThetaBottoms[i] = state.linCircleBottom[i].cotTheta;
0512 }
0513 std::ranges::sort(sortedBottoms, {}, [&](const std::uint32_t s) {
0514 return cotThetaBottoms[s];
0515 });
0516
0517 std::vector<float> cotThetaTops(state.linCircleTop.size());
0518 for (std::uint32_t i = 0; i < sortedTops.size(); ++i) {
0519 cotThetaTops[i] = state.linCircleTop[i].cotTheta;
0520 }
0521 std::ranges::sort(sortedTops, {},
0522 [&](const std::uint32_t s) { return cotThetaTops[s]; });
0523 }
0524
0525
0526 state.topSpVec.reserve(numTopSp);
0527 state.curvatures.reserve(numTopSp);
0528 state.impactParameters.reserve(numTopSp);
0529
0530 std::size_t t0 = 0;
0531
0532
0533 state.candidatesCollector.clear();
0534
0535 for (const std::size_t b : sortedBottoms) {
0536
0537 if (t0 == numTopSp) {
0538 break;
0539 }
0540
0541 auto lb = state.linCircleBottom[b];
0542 float cotThetaB = lb.cotTheta;
0543 float Vb = lb.V;
0544 float Ub = lb.U;
0545 float ErB = lb.Er;
0546 float iDeltaRB = lb.iDeltaR;
0547
0548
0549 float iSinTheta2 = 1 + cotThetaB * cotThetaB;
0550 float sigmaSquaredPtDependent = iSinTheta2 * options.sigmapT2perRadius;
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560 float scatteringInRegion2 = options.multipleScattering2 * iSinTheta2;
0561
0562 float sinTheta = 1 / std::sqrt(iSinTheta2);
0563 float cosTheta = cotThetaB * sinTheta;
0564
0565
0566 state.topSpVec.clear();
0567 state.curvatures.clear();
0568 state.impactParameters.clear();
0569
0570
0571
0572 float rotationTermsUVtoXY[2] = {0, 0};
0573 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0574 rotationTermsUVtoXY[0] = cosPhiM * sinTheta;
0575 rotationTermsUVtoXY[1] = sinPhiM * sinTheta;
0576 }
0577
0578
0579
0580
0581 std::size_t minCompatibleTopSPs = 2;
0582 if (!m_config.seedConfirmation ||
0583 state.compatBottomSP[b]->radius() > seedFilterState.rMaxSeedConf) {
0584 minCompatibleTopSPs = 1;
0585 }
0586 if (m_config.seedConfirmation &&
0587 state.candidatesCollector.nHighQualityCandidates()) {
0588 minCompatibleTopSPs++;
0589 }
0590
0591 for (std::size_t index_t = t0; index_t < numTopSp; index_t++) {
0592 const std::size_t t = sortedTops[index_t];
0593
0594 auto lt = state.linCircleTop[t];
0595
0596 float cotThetaT = lt.cotTheta;
0597 float rMxy = 0;
0598 float ub = 0;
0599 float vb = 0;
0600 float ut = 0;
0601 float vt = 0;
0602 double rMTransf[3];
0603 float xB = 0;
0604 float yB = 0;
0605 float xT = 0;
0606 float yT = 0;
0607 float iDeltaRB2 = 0;
0608 float iDeltaRT2 = 0;
0609
0610 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0611
0612 float dU = lt.U - Ub;
0613 if (dU == 0) {
0614 continue;
0615 }
0616
0617
0618 float A0 = (lt.V - Vb) / dU;
0619
0620 float zPositionMiddle = cosTheta * std::sqrt(1 + A0 * A0);
0621
0622
0623
0624 double positionMiddle[3] = {
0625 rotationTermsUVtoXY[0] - rotationTermsUVtoXY[1] * A0,
0626 rotationTermsUVtoXY[0] * A0 + rotationTermsUVtoXY[1],
0627 zPositionMiddle};
0628
0629 if (!xyzCoordinateCheck(m_config, spM, positionMiddle, rMTransf)) {
0630 continue;
0631 }
0632
0633
0634 float B0 = 2 * (Vb - A0 * Ub);
0635 float Cb = 1 - B0 * lb.y;
0636 float Sb = A0 + B0 * lb.x;
0637 double positionBottom[3] = {
0638 rotationTermsUVtoXY[0] * Cb - rotationTermsUVtoXY[1] * Sb,
0639 rotationTermsUVtoXY[0] * Sb + rotationTermsUVtoXY[1] * Cb,
0640 zPositionMiddle};
0641
0642 auto spB = state.compatBottomSP[b];
0643 double rBTransf[3];
0644 if (!xyzCoordinateCheck(m_config, *spB, positionBottom, rBTransf)) {
0645 continue;
0646 }
0647
0648
0649 float Ct = 1 - B0 * lt.y;
0650 float St = A0 + B0 * lt.x;
0651 double positionTop[3] = {
0652 rotationTermsUVtoXY[0] * Ct - rotationTermsUVtoXY[1] * St,
0653 rotationTermsUVtoXY[0] * St + rotationTermsUVtoXY[1] * Ct,
0654 zPositionMiddle};
0655
0656 auto spT = state.compatTopSP[t];
0657 double rTTransf[3];
0658 if (!xyzCoordinateCheck(m_config, *spT, positionTop, rTTransf)) {
0659 continue;
0660 }
0661
0662
0663 xB = rBTransf[0] - rMTransf[0];
0664 yB = rBTransf[1] - rMTransf[1];
0665 float zB = rBTransf[2] - rMTransf[2];
0666 xT = rTTransf[0] - rMTransf[0];
0667 yT = rTTransf[1] - rMTransf[1];
0668 float zT = rTTransf[2] - rMTransf[2];
0669
0670 iDeltaRB2 = 1 / (xB * xB + yB * yB);
0671 iDeltaRT2 = 1 / (xT * xT + yT * yT);
0672
0673 cotThetaB = -zB * std::sqrt(iDeltaRB2);
0674 cotThetaT = zT * std::sqrt(iDeltaRT2);
0675 }
0676
0677
0678 float cotThetaAvg2 = cotThetaB * cotThetaT;
0679 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0680
0681 float averageCotTheta = 0.5f * (cotThetaB + cotThetaT);
0682 cotThetaAvg2 = averageCotTheta * averageCotTheta;
0683 }
0684
0685
0686
0687 float error2 =
0688 lt.Er + ErB +
0689 2 * (cotThetaAvg2 * varianceRM + varianceZM) * iDeltaRB * lt.iDeltaR;
0690
0691 float deltaCotTheta = cotThetaB - cotThetaT;
0692 float deltaCotTheta2 = deltaCotTheta * deltaCotTheta;
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704 if (deltaCotTheta2 > error2 + scatteringInRegion2) {
0705
0706 if constexpr (detailedMeasurement ==
0707 DetectorMeasurementInfo::eDetailed) {
0708 continue;
0709 }
0710
0711
0712 if (cotThetaB - cotThetaT < 0) {
0713 break;
0714 }
0715 t0 = index_t + 1;
0716 continue;
0717 }
0718
0719 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0720 rMxy = std::sqrt(rMTransf[0] * rMTransf[0] + rMTransf[1] * rMTransf[1]);
0721 float irMxy = 1 / rMxy;
0722 float Ax = rMTransf[0] * irMxy;
0723 float Ay = rMTransf[1] * irMxy;
0724
0725 ub = (xB * Ax + yB * Ay) * iDeltaRB2;
0726 vb = (yB * Ax - xB * Ay) * iDeltaRB2;
0727 ut = (xT * Ax + yT * Ay) * iDeltaRT2;
0728 vt = (yT * Ax - xT * Ay) * iDeltaRT2;
0729 }
0730
0731 float dU = 0;
0732 float A = 0;
0733 float S2 = 0;
0734 float B = 0;
0735 float B2 = 0;
0736
0737 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0738 dU = ut - ub;
0739
0740 if (dU == 0) {
0741 continue;
0742 }
0743 A = (vt - vb) / dU;
0744 S2 = 1 + A * A;
0745 B = vb - A * ub;
0746 B2 = B * B;
0747 } else {
0748 dU = lt.U - Ub;
0749
0750 if (dU == 0) {
0751 continue;
0752 }
0753
0754
0755 A = (lt.V - Vb) / dU;
0756 S2 = 1 + A * A;
0757 B = Vb - A * Ub;
0758 B2 = B * B;
0759 }
0760
0761
0762
0763 if (S2 < B2 * options.minHelixDiameter2) {
0764 continue;
0765 }
0766
0767
0768
0769
0770 float iHelixDiameter2 = B2 / S2;
0771
0772
0773 float p2scatterSigma = iHelixDiameter2 * sigmaSquaredPtDependent;
0774
0775 if (deltaCotTheta2 > error2 + p2scatterSigma) {
0776 if constexpr (detailedMeasurement ==
0777 DetectorMeasurementInfo::eDetailed) {
0778 continue;
0779 }
0780 if (cotThetaB - cotThetaT < 0) {
0781 break;
0782 }
0783 t0 = index_t;
0784 continue;
0785 }
0786
0787
0788
0789 float Im = 0;
0790 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0791 Im = std::abs((A - B * rMxy) * rMxy);
0792 } else {
0793 Im = std::abs((A - B * rM) * rM);
0794 }
0795
0796 if (Im > m_config.impactMax) {
0797 continue;
0798 }
0799
0800 state.topSpVec.push_back(state.compatTopSP[t]);
0801
0802
0803 state.curvatures.push_back(B / std::sqrt(S2));
0804 state.impactParameters.push_back(Im);
0805 }
0806
0807
0808 if (state.topSpVec.size() < minCompatibleTopSPs) {
0809 continue;
0810 }
0811
0812 seedFilterState.zOrigin = spM.z() - rM * lb.cotTheta;
0813
0814 m_config.seedFilter->filterSeeds_2SpFixed(
0815 state.spacePointMutableData, *state.compatBottomSP[b], spM,
0816 state.topSpVec, state.curvatures, state.impactParameters,
0817 seedFilterState, state.candidatesCollector);
0818 }
0819 }
0820
0821 template <typename external_space_point_t, typename grid_t, typename platform_t>
0822 std::pair<float, float> SeedFinder<external_space_point_t, grid_t, platform_t>::
0823 retrieveRadiusRangeForMiddle(const external_space_point_t& spM,
0824 const Range1D<float>& rMiddleSPRange) const {
0825 if (m_config.useVariableMiddleSPRange) {
0826 return {rMiddleSPRange.min(), rMiddleSPRange.max()};
0827 }
0828 if (!m_config.rRangeMiddleSP.empty()) {
0829
0830 auto pVal = std::lower_bound(m_config.zBinEdges.begin(),
0831 m_config.zBinEdges.end(), spM.z());
0832 int zBin = std::distance(m_config.zBinEdges.begin(), pVal);
0833
0834 zBin == 0 ? zBin : --zBin;
0835 return {m_config.rRangeMiddleSP[zBin][0], m_config.rRangeMiddleSP[zBin][1]};
0836 }
0837 return {m_config.rMinMiddle, m_config.rMaxMiddle};
0838 }
0839
0840 }