File indexing completed on 2025-09-17 08:01:49
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 (!m_config.experimentCuts(mediumSP, *otherSP, cotTheta,
0412 isBottomCandidate)) {
0413 continue;
0414 }
0415
0416 const float Er =
0417 ((varianceZM + otherSP->varianceZ()) +
0418 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0419 iDeltaR2;
0420
0421
0422 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0423 yNewFrame);
0424 mutableData.setDeltaR(otherSP->index(),
0425 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0426 outVec.emplace_back(otherSP);
0427 continue;
0428 }
0429
0430
0431
0432 const float vIP = (yNewFrame > 0) ? -vIPAbs : vIPAbs;
0433
0434
0435
0436
0437 const float aCoef = (vT - vIP) / (uT - uIP);
0438 const float bCoef = vIP - aCoef * uIP;
0439
0440
0441
0442 if ((bCoef * bCoef) * options.minHelixDiameter2 > (1 + aCoef * aCoef)) {
0443 continue;
0444 }
0445
0446
0447
0448
0449 if (outsideRangeCheck(deltaZ, -m_config.cotThetaMax * deltaR,
0450 m_config.cotThetaMax * deltaR)) {
0451 continue;
0452 }
0453
0454 const float iDeltaR = std::sqrt(iDeltaR2);
0455 const float cotTheta = deltaZ * iDeltaR;
0456
0457
0458
0459 if (!m_config.experimentCuts(mediumSP, *otherSP, cotTheta,
0460 isBottomCandidate)) {
0461 continue;
0462 }
0463
0464 const float Er =
0465 ((varianceZM + otherSP->varianceZ()) +
0466 (cotTheta * cotTheta) * (varianceRM + otherSP->varianceR())) *
0467 iDeltaR2;
0468
0469
0470 linCircleVec.emplace_back(cotTheta, iDeltaR, Er, uT, vT, xNewFrame,
0471 yNewFrame);
0472
0473 mutableData.setDeltaR(otherSP->index(),
0474 std::sqrt(deltaR2 + (deltaZ * deltaZ)));
0475 outVec.emplace_back(otherSP);
0476 }
0477 }
0478 }
0479
0480 template <typename external_spacepoint_t, typename grid_t, typename platform_t>
0481 template <DetectorMeasurementInfo detailedMeasurement>
0482 inline void
0483 SeedFinder<external_spacepoint_t, grid_t, platform_t>::filterCandidates(
0484 const external_spacepoint_t& spM, const SeedFinderOptions& options,
0485 SeedFilterState& seedFilterState, SeedingState& state) const {
0486 const float rM = spM.radius();
0487 const float cosPhiM = spM.x() / rM;
0488 const float sinPhiM = spM.y() / rM;
0489 const float varianceRM = spM.varianceR();
0490 const float varianceZM = spM.varianceZ();
0491
0492 std::size_t numTopSp = state.compatTopSP.size();
0493
0494
0495 std::vector<std::uint32_t> sortedBottoms(state.compatBottomSP.size());
0496 for (std::uint32_t i = 0; i < sortedBottoms.size(); ++i) {
0497 sortedBottoms[i] = i;
0498 }
0499 std::vector<std::uint32_t> sortedTops(state.linCircleTop.size());
0500 for (std::uint32_t i = 0; i < sortedTops.size(); ++i) {
0501 sortedTops[i] = i;
0502 }
0503
0504 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDefault) {
0505 std::vector<float> cotThetaBottoms(state.compatBottomSP.size());
0506 for (std::uint32_t i = 0; i < sortedBottoms.size(); ++i) {
0507 cotThetaBottoms[i] = state.linCircleBottom[i].cotTheta;
0508 }
0509 std::ranges::sort(sortedBottoms, {}, [&](const std::uint32_t s) {
0510 return cotThetaBottoms[s];
0511 });
0512
0513 std::vector<float> cotThetaTops(state.linCircleTop.size());
0514 for (std::uint32_t i = 0; i < sortedTops.size(); ++i) {
0515 cotThetaTops[i] = state.linCircleTop[i].cotTheta;
0516 }
0517 std::ranges::sort(sortedTops, {},
0518 [&](const std::uint32_t s) { return cotThetaTops[s]; });
0519 }
0520
0521
0522 state.topSpVec.reserve(numTopSp);
0523 state.curvatures.reserve(numTopSp);
0524 state.impactParameters.reserve(numTopSp);
0525
0526 std::size_t t0 = 0;
0527
0528
0529 state.candidatesCollector.clear();
0530
0531 for (const std::size_t b : sortedBottoms) {
0532
0533 if (t0 == numTopSp) {
0534 break;
0535 }
0536
0537 auto lb = state.linCircleBottom[b];
0538 float cotThetaB = lb.cotTheta;
0539 float Vb = lb.V;
0540 float Ub = lb.U;
0541 float ErB = lb.Er;
0542 float iDeltaRB = lb.iDeltaR;
0543
0544
0545 float iSinTheta2 = 1 + cotThetaB * cotThetaB;
0546 float sigmaSquaredPtDependent = iSinTheta2 * options.sigmapT2perRadius;
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556 float scatteringInRegion2 = options.multipleScattering2 * iSinTheta2;
0557
0558 float sinTheta = 1 / std::sqrt(iSinTheta2);
0559 float cosTheta = cotThetaB * sinTheta;
0560
0561
0562 state.topSpVec.clear();
0563 state.curvatures.clear();
0564 state.impactParameters.clear();
0565
0566
0567
0568 float rotationTermsUVtoXY[2] = {0, 0};
0569 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0570 rotationTermsUVtoXY[0] = cosPhiM * sinTheta;
0571 rotationTermsUVtoXY[1] = sinPhiM * sinTheta;
0572 }
0573
0574
0575
0576
0577 std::size_t minCompatibleTopSPs = 2;
0578 if (!m_config.seedConfirmation ||
0579 state.compatBottomSP[b]->radius() > seedFilterState.rMaxSeedConf) {
0580 minCompatibleTopSPs = 1;
0581 }
0582 if (m_config.seedConfirmation &&
0583 state.candidatesCollector.nHighQualityCandidates()) {
0584 minCompatibleTopSPs++;
0585 }
0586
0587 for (std::size_t index_t = t0; index_t < numTopSp; index_t++) {
0588 const std::size_t t = sortedTops[index_t];
0589
0590 auto lt = state.linCircleTop[t];
0591
0592 float cotThetaT = lt.cotTheta;
0593 float rMxy = 0;
0594 float ub = 0;
0595 float vb = 0;
0596 float ut = 0;
0597 float vt = 0;
0598 double rMTransf[3];
0599 float xB = 0;
0600 float yB = 0;
0601 float xT = 0;
0602 float yT = 0;
0603 float iDeltaRB2 = 0;
0604 float iDeltaRT2 = 0;
0605
0606 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0607
0608 float dU = lt.U - Ub;
0609 if (dU == 0) {
0610 continue;
0611 }
0612
0613
0614 float A0 = (lt.V - Vb) / dU;
0615
0616 float zPositionMiddle = cosTheta * std::sqrt(1 + A0 * A0);
0617
0618
0619
0620 double positionMiddle[3] = {
0621 rotationTermsUVtoXY[0] - rotationTermsUVtoXY[1] * A0,
0622 rotationTermsUVtoXY[0] * A0 + rotationTermsUVtoXY[1],
0623 zPositionMiddle};
0624
0625 if (!xyzCoordinateCheck(m_config, spM, positionMiddle, rMTransf)) {
0626 continue;
0627 }
0628
0629
0630 float B0 = 2 * (Vb - A0 * Ub);
0631 float Cb = 1 - B0 * lb.y;
0632 float Sb = A0 + B0 * lb.x;
0633 double positionBottom[3] = {
0634 rotationTermsUVtoXY[0] * Cb - rotationTermsUVtoXY[1] * Sb,
0635 rotationTermsUVtoXY[0] * Sb + rotationTermsUVtoXY[1] * Cb,
0636 zPositionMiddle};
0637
0638 auto spB = state.compatBottomSP[b];
0639 double rBTransf[3];
0640 if (!xyzCoordinateCheck(m_config, *spB, positionBottom, rBTransf)) {
0641 continue;
0642 }
0643
0644
0645 float Ct = 1 - B0 * lt.y;
0646 float St = A0 + B0 * lt.x;
0647 double positionTop[3] = {
0648 rotationTermsUVtoXY[0] * Ct - rotationTermsUVtoXY[1] * St,
0649 rotationTermsUVtoXY[0] * St + rotationTermsUVtoXY[1] * Ct,
0650 zPositionMiddle};
0651
0652 auto spT = state.compatTopSP[t];
0653 double rTTransf[3];
0654 if (!xyzCoordinateCheck(m_config, *spT, positionTop, rTTransf)) {
0655 continue;
0656 }
0657
0658
0659 xB = rBTransf[0] - rMTransf[0];
0660 yB = rBTransf[1] - rMTransf[1];
0661 float zB = rBTransf[2] - rMTransf[2];
0662 xT = rTTransf[0] - rMTransf[0];
0663 yT = rTTransf[1] - rMTransf[1];
0664 float zT = rTTransf[2] - rMTransf[2];
0665
0666 iDeltaRB2 = 1 / (xB * xB + yB * yB);
0667 iDeltaRT2 = 1 / (xT * xT + yT * yT);
0668
0669 cotThetaB = -zB * std::sqrt(iDeltaRB2);
0670 cotThetaT = zT * std::sqrt(iDeltaRT2);
0671 }
0672
0673
0674 float cotThetaAvg2 = cotThetaB * cotThetaT;
0675 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0676
0677 float averageCotTheta = 0.5f * (cotThetaB + cotThetaT);
0678 cotThetaAvg2 = averageCotTheta * averageCotTheta;
0679 }
0680
0681
0682
0683 float error2 =
0684 lt.Er + ErB +
0685 2 * (cotThetaAvg2 * varianceRM + varianceZM) * iDeltaRB * lt.iDeltaR;
0686
0687 float deltaCotTheta = cotThetaB - cotThetaT;
0688 float deltaCotTheta2 = deltaCotTheta * deltaCotTheta;
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700 if (deltaCotTheta2 > error2 + scatteringInRegion2) {
0701
0702 if constexpr (detailedMeasurement ==
0703 DetectorMeasurementInfo::eDetailed) {
0704 continue;
0705 }
0706
0707
0708 if (cotThetaB - cotThetaT < 0) {
0709 break;
0710 }
0711 t0 = index_t + 1;
0712 continue;
0713 }
0714
0715 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0716 rMxy = std::sqrt(rMTransf[0] * rMTransf[0] + rMTransf[1] * rMTransf[1]);
0717 float irMxy = 1 / rMxy;
0718 float Ax = rMTransf[0] * irMxy;
0719 float Ay = rMTransf[1] * irMxy;
0720
0721 ub = (xB * Ax + yB * Ay) * iDeltaRB2;
0722 vb = (yB * Ax - xB * Ay) * iDeltaRB2;
0723 ut = (xT * Ax + yT * Ay) * iDeltaRT2;
0724 vt = (yT * Ax - xT * Ay) * iDeltaRT2;
0725 }
0726
0727 float dU = 0;
0728 float A = 0;
0729 float S2 = 0;
0730 float B = 0;
0731 float B2 = 0;
0732
0733 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0734 dU = ut - ub;
0735
0736 if (dU == 0) {
0737 continue;
0738 }
0739 A = (vt - vb) / dU;
0740 S2 = 1 + A * A;
0741 B = vb - A * ub;
0742 B2 = B * B;
0743 } else {
0744 dU = lt.U - Ub;
0745
0746 if (dU == 0) {
0747 continue;
0748 }
0749
0750
0751 A = (lt.V - Vb) / dU;
0752 S2 = 1 + A * A;
0753 B = Vb - A * Ub;
0754 B2 = B * B;
0755 }
0756
0757
0758
0759 if (S2 < B2 * options.minHelixDiameter2) {
0760 continue;
0761 }
0762
0763
0764
0765
0766 float iHelixDiameter2 = B2 / S2;
0767
0768
0769 float p2scatterSigma = iHelixDiameter2 * sigmaSquaredPtDependent;
0770
0771 if (deltaCotTheta2 > error2 + p2scatterSigma) {
0772 if constexpr (detailedMeasurement ==
0773 DetectorMeasurementInfo::eDetailed) {
0774 continue;
0775 }
0776 if (cotThetaB - cotThetaT < 0) {
0777 break;
0778 }
0779 t0 = index_t;
0780 continue;
0781 }
0782
0783
0784
0785 float Im = 0;
0786 if constexpr (detailedMeasurement == DetectorMeasurementInfo::eDetailed) {
0787 Im = std::abs((A - B * rMxy) * rMxy);
0788 } else {
0789 Im = std::abs((A - B * rM) * rM);
0790 }
0791
0792 if (Im > m_config.impactMax) {
0793 continue;
0794 }
0795
0796 state.topSpVec.push_back(state.compatTopSP[t]);
0797
0798
0799 state.curvatures.push_back(B / std::sqrt(S2));
0800 state.impactParameters.push_back(Im);
0801 }
0802
0803
0804 if (state.topSpVec.size() < minCompatibleTopSPs) {
0805 continue;
0806 }
0807
0808 seedFilterState.zOrigin = spM.z() - rM * lb.cotTheta;
0809
0810 m_config.seedFilter->filterSeeds_2SpFixed(
0811 state.spacePointMutableData, *state.compatBottomSP[b], spM,
0812 state.topSpVec, state.curvatures, state.impactParameters,
0813 seedFilterState, state.candidatesCollector);
0814 }
0815 }
0816
0817 template <typename external_spacepoint_t, typename grid_t, typename platform_t>
0818 std::pair<float, float> SeedFinder<external_spacepoint_t, grid_t, platform_t>::
0819 retrieveRadiusRangeForMiddle(const external_spacepoint_t& spM,
0820 const Range1D<float>& rMiddleSPRange) const {
0821 if (m_config.useVariableMiddleSPRange) {
0822 return {rMiddleSPRange.min(), rMiddleSPRange.max()};
0823 }
0824 if (!m_config.rRangeMiddleSP.empty()) {
0825
0826 auto pVal = std::lower_bound(m_config.zBinEdges.begin(),
0827 m_config.zBinEdges.end(), spM.z());
0828 int zBin = std::distance(m_config.zBinEdges.begin(), pVal);
0829
0830 zBin == 0 ? zBin : --zBin;
0831 return {m_config.rRangeMiddleSP[zBin][0], m_config.rRangeMiddleSP[zBin][1]};
0832 }
0833 return {m_config.rMinMiddle, m_config.rMaxMiddle};
0834 }
0835
0836 }