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