File indexing completed on 2025-07-09 07:49:44
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_spacepoint_t, typename grid_t, typename platform_t>
0019 SeedFinder<external_spacepoint_t, grid_t, platform_t>::SeedFinder(
0020 const SeedFinderConfig<external_spacepoint_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_spacepoint_t, typename grid_t, typename platform_t>
0038 template <typename container_t, GridBinCollection sp_range_t>
0039 requires CollectionStoresSeedsTo<container_t, external_spacepoint_t, 3ul>
0040 void SeedFinder<external_spacepoint_t, grid_t, platform_t>::createSeedsForGroup(
0041 const SeedFinderOptions& options, SeedingState& state, const grid_t& grid,
0042 container_t& outputCollection, const sp_range_t& bottomSPsIdx,
0043 const std::size_t middleSPsIdx, const sp_range_t& topSPsIdx,
0044 const Range1D<float>& rMiddleSPRange) const {
0045
0046 const std::size_t max_num_seeds_per_spm =
0047 m_config.seedFilter->getSeedFilterConfig().maxSeedsPerSpMConf;
0048 const std::size_t max_num_quality_seeds_per_spm =
0049 m_config.seedFilter->getSeedFilterConfig().maxQualitySeedsPerSpMConf;
0050
0051 state.candidatesCollector.setMaxElements(max_num_seeds_per_spm,
0052 max_num_quality_seeds_per_spm);
0053
0054
0055 if (bottomSPsIdx.size() == 0 || topSPsIdx.size() == 0) {
0056 return;
0057 }
0058
0059
0060 const std::vector<const external_spacepoint_t*>& middleSPs =
0061 grid.at(middleSPsIdx);
0062
0063 if (middleSPs.empty()) {
0064 return;
0065 }
0066
0067
0068
0069 state.bottomNeighbours.clear();
0070 state.topNeighbours.clear();
0071
0072
0073
0074 for (const std::size_t idx : bottomSPsIdx) {
0075
0076 if (grid.at(idx).size() == 0) {
0077 continue;
0078 }
0079 state.bottomNeighbours.emplace_back(
0080 grid, idx, middleSPs.front()->radius() - m_config.deltaRMaxBottomSP);
0081 }
0082
0083 if (state.bottomNeighbours.size() == 0) {
0084 return;
0085 }
0086
0087
0088 for (const std::size_t idx : topSPsIdx) {
0089
0090 if (grid.at(idx).size() == 0) {
0091 continue;
0092 }
0093 state.topNeighbours.emplace_back(
0094 grid, idx, middleSPs.front()->radius() + m_config.deltaRMinTopSP);
0095 }
0096
0097 if (state.topNeighbours.size() == 0) {
0098 return;
0099 }
0100
0101
0102
0103 auto [minRadiusRangeForMiddle, maxRadiusRangeForMiddle] =
0104 retrieveRadiusRangeForMiddle(*middleSPs.front(), rMiddleSPRange);
0105 ACTS_VERBOSE("Current global bin: " << middleSPsIdx << ", z value of "
0106 << middleSPs.front()->z());
0107 ACTS_VERBOSE("Validity range (radius) for the middle space point is ["
0108 << minRadiusRangeForMiddle << ", " << maxRadiusRangeForMiddle
0109 << "]");
0110
0111 for (const external_spacepoint_t* spM : middleSPs) {
0112 const float rM = spM->radius();
0113
0114
0115 if (rM < minRadiusRangeForMiddle) {
0116 continue;
0117 }
0118 if (rM > maxRadiusRangeForMiddle) {
0119
0120 break;
0121 }
0122
0123 const float zM = spM->z();
0124 const float uIP = -1. / rM;
0125 const float cosPhiM = -spM->x() * uIP;
0126 const float sinPhiM = -spM->y() * uIP;
0127 const float uIP2 = uIP * uIP;
0128
0129
0130 getCompatibleDoublets<SpacePointCandidateType::eTop>(
0131 options, grid, state.spacePointMutableData, state.topNeighbours, *spM,
0132 state.linCircleTop, state.compatTopSP, m_config.deltaRMinTopSP,
0133 m_config.deltaRMaxTopSP, uIP, uIP2, cosPhiM, sinPhiM);
0134
0135
0136 if (state.compatTopSP.empty()) {
0137 ACTS_VERBOSE("No compatible Tops, moving to next middle candidate");
0138 continue;
0139 }
0140
0141
0142 SeedFilterState seedFilterState;
0143 if (m_config.seedConfirmation) {
0144
0145 SeedConfirmationRangeConfig seedConfRange =
0146 (zM > m_config.centralSeedConfirmationRange.zMaxSeedConf ||
0147 zM < m_config.centralSeedConfirmationRange.zMinSeedConf)
0148 ? m_config.forwardSeedConfirmationRange
0149 : m_config.centralSeedConfirmationRange;
0150
0151
0152 seedFilterState.nTopSeedConf = rM > seedConfRange.rMaxSeedConf
0153 ? seedConfRange.nTopForLargeR
0154 : seedConfRange.nTopForSmallR;
0155
0156 seedFilterState.rMaxSeedConf = seedConfRange.rMaxSeedConf;
0157
0158 if (state.compatTopSP.size() < seedFilterState.nTopSeedConf) {
0159 ACTS_VERBOSE(
0160 "Number of top SPs is "
0161 << state.compatTopSP.size()
0162 << " and is smaller than minimum, moving to next middle candidate");
0163 continue;
0164 }
0165 }
0166
0167
0168 getCompatibleDoublets<SpacePointCandidateType::eBottom>(
0169 options, grid, state.spacePointMutableData, state.bottomNeighbours,
0170 *spM, state.linCircleBottom, state.compatBottomSP,
0171 m_config.deltaRMinBottomSP, m_config.deltaRMaxBottomSP, uIP, uIP2,
0172 cosPhiM, sinPhiM);
0173
0174
0175 if (state.compatBottomSP.empty()) {
0176 ACTS_VERBOSE("No compatible Bottoms, moving to next middle candidate");
0177 continue;
0178 }
0179
0180 ACTS_VERBOSE("Candidates: " << state.compatBottomSP.size()
0181 << " bottoms and " << state.compatTopSP.size()
0182 << " tops for middle candidate indexed "
0183 << spM->index());
0184
0185 if (m_config.useDetailedDoubleMeasurementInfo) {
0186 filterCandidates<DetectorMeasurementInfo::eDetailed>(
0187 *spM, options, seedFilterState, state);
0188 } else {
0189 filterCandidates<DetectorMeasurementInfo::eDefault>(
0190 *spM, options, seedFilterState, state);
0191 }
0192
0193 m_config.seedFilter->filterSeeds_1SpFixed(state.spacePointMutableData,
0194 state.candidatesCollector,
0195 outputCollection);
0196
0197 }
0198 }
0199
0200 template <typename external_spacepoint_t, typename grid_t, typename platform_t>
0201 template <SpacePointCandidateType candidateType, typename out_range_t>
0202 inline void
0203 SeedFinder<external_spacepoint_t, grid_t, platform_t>::getCompatibleDoublets(
0204 const SeedFinderOptions& options, const grid_t& grid,
0205 SpacePointMutableData& mutableData,
0206 boost::container::small_vector<
0207 Neighbour<grid_t>, detail::ipow(3, grid_t::DIM)>& otherSPsNeighbours,
0208 const external_spacepoint_t& mediumSP, std::vector<LinCircle>& linCircleVec,
0209 out_range_t& outVec, const float deltaRMinSP, const float deltaRMaxSP,
0210 const float uIP, const float uIP2, const float cosPhiM,
0211 const float sinPhiM) const {
0212 float impactMax = m_config.impactMax;
0213
0214 constexpr bool isBottomCandidate =
0215 candidateType == SpacePointCandidateType::eBottom;
0216
0217 if constexpr (isBottomCandidate) {
0218 impactMax = -impactMax;
0219 }
0220
0221 outVec.clear();
0222 linCircleVec.clear();
0223
0224
0225 std::size_t nsp = 0;
0226 for (const auto& otherSPCol : otherSPsNeighbours) {
0227 nsp += grid.at(otherSPCol.index).size();
0228 }
0229
0230 linCircleVec.reserve(nsp);
0231 outVec.reserve(nsp);
0232
0233 const float rM = mediumSP.radius();
0234 const float xM = mediumSP.x();
0235 const float yM = mediumSP.y();
0236 const float zM = mediumSP.z();
0237 const float varianceRM = mediumSP.varianceR();
0238 const float varianceZM = mediumSP.varianceZ();
0239
0240 float vIPAbs = 0;
0241 if (m_config.interactionPointCut) {
0242
0243 vIPAbs = impactMax * uIP2;
0244 }
0245
0246 float deltaR = 0.;
0247 float deltaZ = 0.;
0248
0249 const auto outsideRangeCheck = [](const float value, const float min,
0250 const float max) -> bool {
0251
0252
0253 return static_cast<bool>(static_cast<int>(value < min) |
0254 static_cast<int>(value > max));
0255 };
0256
0257 for (auto& otherSPCol : otherSPsNeighbours) {
0258 const std::vector<const external_spacepoint_t*>& otherSPs =
0259 grid.at(otherSPCol.index);
0260 if (otherSPs.empty()) {
0261 continue;
0262 }
0263
0264
0265
0266 auto min_itr = otherSPCol.itr;
0267
0268
0269
0270 for (; min_itr != otherSPs.end(); ++min_itr) {
0271 const external_spacepoint_t* otherSP = *min_itr;
0272 if constexpr (candidateType == SpacePointCandidateType::eBottom) {
0273
0274 if ((rM - otherSP->radius()) <= deltaRMaxSP) {
0275 break;
0276 }
0277 } else {
0278
0279 if ((otherSP->radius() - rM) >= deltaRMinSP) {
0280 break;
0281 }
0282 }
0283 }
0284
0285
0286
0287 otherSPCol.itr = min_itr;
0288
0289 for (; min_itr != otherSPs.end(); ++min_itr) {
0290 const external_spacepoint_t* otherSP = *min_itr;
0291
0292 if constexpr (isBottomCandidate) {
0293 deltaR = (rM - otherSP->radius());
0294
0295
0296 if (deltaR < deltaRMinSP) {
0297 break;
0298 }
0299 } else {
0300 deltaR = (otherSP->radius() - rM);
0301
0302
0303 if (deltaR > deltaRMaxSP) {
0304 break;
0305 }
0306 }
0307
0308 if constexpr (isBottomCandidate) {
0309 deltaZ = (zM - otherSP->z());
0310 } else {
0311 deltaZ = (otherSP->z() - zM);
0312 }
0313
0314
0315
0316
0317
0318 const float zOriginTimesDeltaR = (zM * deltaR - rM * deltaZ);
0319
0320 if (outsideRangeCheck(zOriginTimesDeltaR,
0321 m_config.collisionRegionMin * deltaR,
0322 m_config.collisionRegionMax * deltaR)) {
0323 continue;
0324 }
0325
0326
0327
0328
0329
0330 if (!m_config.interactionPointCut) {
0331
0332
0333
0334 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0335 m_config.cotThetaMax * deltaR)) {
0336 continue;
0337 }
0338
0339 if (outsideRangeCheck(deltaZ, -m_config.deltaZMax,
0340 m_config.deltaZMax)) {
0341 continue;
0342 }
0343
0344
0345 const float deltaX = otherSP->x() - xM;
0346 const float deltaY = otherSP->y() - yM;
0347
0348 const float xNewFrame = deltaX * cosPhiM + deltaY * sinPhiM;
0349 const float yNewFrame = deltaY * cosPhiM - deltaX * sinPhiM;
0350
0351 const float deltaR2 = (deltaX * deltaX + deltaY * deltaY);
0352 const float iDeltaR2 = 1. / deltaR2;
0353
0354 const float uT = xNewFrame * iDeltaR2;
0355 const float vT = yNewFrame * iDeltaR2;
0356
0357 const float iDeltaR = std::sqrt(iDeltaR2);
0358 const float cotTheta = deltaZ * iDeltaR;
0359
0360 const float Er =
0361 ((varianceZM + otherSP->varianceZ()) +
0362 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0363 iDeltaR2;
0364
0365
0366 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0367 yNewFrame);
0368
0369 mutableData.setDeltaR(otherSP->index(),
0370 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0371 outVec.push_back(otherSP);
0372 continue;
0373 }
0374
0375
0376 const float deltaX = otherSP->x() - xM;
0377 const float deltaY = otherSP->y() - yM;
0378
0379 const float xNewFrame = deltaX * cosPhiM + deltaY * sinPhiM;
0380 const float yNewFrame = deltaY * cosPhiM - deltaX * sinPhiM;
0381
0382 const float deltaR2 = (deltaX * deltaX + deltaY * deltaY);
0383 const float iDeltaR2 = 1. / deltaR2;
0384
0385 const float uT = xNewFrame * iDeltaR2;
0386 const float vT = yNewFrame * iDeltaR2;
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 if (std::abs(rM * yNewFrame) <= impactMax * xNewFrame) {
0398
0399
0400
0401 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0402 m_config.cotThetaMax * deltaR)) {
0403 continue;
0404 }
0405
0406 const float iDeltaR = std::sqrt(iDeltaR2);
0407 const float cotTheta = deltaZ * iDeltaR;
0408
0409
0410
0411 if constexpr (isBottomCandidate) {
0412 if (!m_config.experimentCuts(otherSP->radius(), cotTheta)) {
0413 continue;
0414 }
0415 }
0416
0417 const float Er =
0418 ((varianceZM + otherSP->varianceZ()) +
0419 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0420 iDeltaR2;
0421
0422
0423 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0424 yNewFrame);
0425 mutableData.setDeltaR(otherSP->index(),
0426 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0427 outVec.emplace_back(otherSP);
0428 continue;
0429 }
0430
0431
0432
0433 const float vIP = (yNewFrame > 0.) ? -vIPAbs : vIPAbs;
0434
0435
0436
0437
0438 const float aCoef = (vT - vIP) / (uT - uIP);
0439 const float bCoef = vIP - aCoef * uIP;
0440
0441
0442
0443 if ((bCoef * bCoef) * options.minHelixDiameter2 > (1 + aCoef * aCoef)) {
0444 continue;
0445 }
0446
0447
0448
0449
0450 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0451 m_config.cotThetaMax * deltaR)) {
0452 continue;
0453 }
0454
0455 const float iDeltaR = std::sqrt(iDeltaR2);
0456 const float cotTheta = deltaZ * iDeltaR;
0457
0458
0459
0460 if constexpr (isBottomCandidate) {
0461 if (!m_config.experimentCuts(otherSP->radius(), cotTheta)) {
0462 continue;
0463 }
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_spacepoint_t, typename grid_t, typename platform_t>
0483 template <DetectorMeasurementInfo detailedMeasurement>
0484 inline void
0485 SeedFinder<external_spacepoint_t, grid_t, platform_t>::filterCandidates(
0486 const external_spacepoint_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.5 * (cotThetaB + cotThetaT);
0680 cotThetaAvg2 = averageCotTheta * averageCotTheta;
0681 } else if (cotThetaAvg2 <= 0) {
0682 continue;
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 if (!std::isinf(m_config.maxPtScattering)) {
0775
0776
0777
0778
0779 if (B2 == 0 || options.pTPerHelixRadius * std::sqrt(S2 / B2) >
0780 2. * m_config.maxPtScattering) {
0781 float pTscatterSigma =
0782 (m_config.highland / m_config.maxPtScattering) *
0783 m_config.sigmaScattering;
0784 p2scatterSigma = pTscatterSigma * pTscatterSigma * iSinTheta2;
0785 }
0786 }
0787
0788
0789 if (deltaCotTheta2 > (error2 + p2scatterSigma)) {
0790 if constexpr (detailedMeasurement ==
0791 DetectorMeasurementInfo::eDetailed) {
0792 continue;
0793 }
0794 if (cotThetaB - cotThetaT < 0) {
0795 break;
0796 }
0797 t0 = index_t;
0798 continue;
0799 }
0800
0801
0802
0803 float Im = 0;
0804 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0805 Im = std::abs((A - B * rMxy) * rMxy);
0806 } else {
0807 Im = std::abs((A - B * rM) * rM);
0808 }
0809
0810 if (Im > m_config.impactMax) {
0811 continue;
0812 }
0813
0814 state.topSpVec.push_back(state.compatTopSP[t]);
0815
0816
0817 state.curvatures.push_back(B / std::sqrt(S2));
0818 state.impactParameters.push_back(Im);
0819 }
0820
0821
0822 if (state.topSpVec.size() < minCompatibleTopSPs) {
0823 continue;
0824 }
0825
0826 seedFilterState.zOrigin = spM.z() - rM * lb.cotTheta;
0827
0828 m_config.seedFilter->filterSeeds_2SpFixed(
0829 state.spacePointMutableData, *state.compatBottomSP[b], spM,
0830 state.topSpVec, state.curvatures, state.impactParameters,
0831 seedFilterState, state.candidatesCollector);
0832 }
0833 }
0834
0835 template <typename external_spacepoint_t, typename grid_t, typename platform_t>
0836 std::pair<float, float> SeedFinder<external_spacepoint_t, grid_t, platform_t>::
0837 retrieveRadiusRangeForMiddle(const external_spacepoint_t& spM,
0838 const Range1D<float>& rMiddleSPRange) const {
0839 if (m_config.useVariableMiddleSPRange) {
0840 return {rMiddleSPRange.min(), rMiddleSPRange.max()};
0841 }
0842 if (!m_config.rRangeMiddleSP.empty()) {
0843
0844 auto pVal = std::lower_bound(m_config.zBinEdges.begin(),
0845 m_config.zBinEdges.end(), spM.z());
0846 int zBin = std::distance(m_config.zBinEdges.begin(), pVal);
0847
0848 zBin == 0 ? zBin : --zBin;
0849 return {m_config.rRangeMiddleSP[zBin][0], m_config.rRangeMiddleSP[zBin][1]};
0850 }
0851 return {m_config.rMinMiddle, m_config.rMaxMiddle};
0852 }
0853
0854 }