File indexing completed on 2025-07-13 07:50:40
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Seeding2/DoubletSeedFinder.hpp"
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/EventData/SpacePointContainer2.hpp"
0013 #include "Acts/Utilities/MathHelpers.hpp"
0014
0015 #include <stdexcept>
0016
0017 namespace Acts::Experimental {
0018
0019 namespace {
0020
0021 enum class SpacePointCandidateType { Bottom, Top };
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <SpacePointCandidateType candidateType, bool interactionPointCut,
0039 bool sortedInR>
0040 void createDoubletsImpl(
0041 const DoubletSeedFinder::DerivedConfig& config,
0042 const SpacePointContainer2& spacePoints,
0043 const ConstSpacePointProxy2& middleSp,
0044 const DoubletSeedFinder::MiddleSpInfo& middleSpInfo,
0045 std::span<const SpacePointIndex2> candidateSps,
0046 std::size_t& candidateOffset,
0047 DoubletSeedFinder::DoubletsForMiddleSp& compatibleDoublets) {
0048 constexpr bool isBottomCandidate =
0049 candidateType == SpacePointCandidateType::Bottom;
0050
0051 const float impactMax =
0052 isBottomCandidate ? -config.impactMax : config.impactMax;
0053
0054 const float xM = middleSp.x();
0055 const float yM = middleSp.y();
0056 const float zM = middleSp.z();
0057 const float rM = middleSp.r();
0058 const float varianceZM = middleSp.varianceZ();
0059 const float varianceRM = middleSp.varianceR();
0060
0061
0062 const float vIPAbs = impactMax * middleSpInfo.uIP2;
0063
0064 float deltaR = 0.;
0065 float deltaZ = 0.;
0066
0067 const auto outsideRangeCheck = [](const float value, const float min,
0068 const float max) {
0069
0070
0071 return static_cast<bool>(static_cast<int>(value < min) |
0072 static_cast<int>(value > max));
0073 };
0074
0075 const auto calculateError = [&](const ConstSpacePointProxy2& otherSp,
0076 float iDeltaR2, float cotTheta) {
0077 const float varianceZO = otherSp.varianceZ();
0078 const float varianceRO = otherSp.varianceR();
0079
0080 return iDeltaR2 * ((varianceZM + varianceZO) +
0081 (cotTheta * cotTheta) * (varianceRM + varianceRO));
0082 };
0083
0084 if constexpr (sortedInR) {
0085
0086
0087 for (; candidateOffset < candidateSps.size(); ++candidateOffset) {
0088 ConstSpacePointProxy2 otherSp =
0089 spacePoints[candidateSps[candidateOffset]];
0090
0091 if constexpr (isBottomCandidate) {
0092
0093 if (rM - otherSp.r() <= config.deltaRMax) {
0094 break;
0095 }
0096 } else {
0097
0098 if (otherSp.r() - rM >= config.deltaRMin) {
0099 break;
0100 }
0101 }
0102 }
0103 }
0104
0105 for (SpacePointIndex2 otherSpIndex : candidateSps.subspan(candidateOffset)) {
0106 ConstSpacePointProxy2 otherSp = spacePoints[otherSpIndex];
0107
0108 const float xO = otherSp.x();
0109 const float yO = otherSp.y();
0110 const float zO = otherSp.z();
0111 const float rO = otherSp.r();
0112
0113 if constexpr (isBottomCandidate) {
0114 deltaR = rM - rO;
0115
0116 if constexpr (sortedInR) {
0117
0118 if (deltaR < config.deltaRMin) {
0119 break;
0120 }
0121 }
0122 } else {
0123 deltaR = rO - rM;
0124
0125 if constexpr (sortedInR) {
0126
0127 if (deltaR > config.deltaRMax) {
0128 break;
0129 }
0130 }
0131 }
0132
0133 if constexpr (!sortedInR) {
0134 if (outsideRangeCheck(deltaR, config.deltaRMin, config.deltaRMax)) {
0135 continue;
0136 }
0137 }
0138
0139 if constexpr (isBottomCandidate) {
0140 deltaZ = zM - zO;
0141 } else {
0142 deltaZ = zO - zM;
0143 }
0144
0145 if (outsideRangeCheck(deltaZ, config.deltaZMin, config.deltaZMax)) {
0146 continue;
0147 }
0148
0149
0150
0151
0152
0153 const float zOriginTimesDeltaR = zM * deltaR - rM * deltaZ;
0154
0155 if (outsideRangeCheck(zOriginTimesDeltaR,
0156 config.collisionRegionMin * deltaR,
0157 config.collisionRegionMax * deltaR)) {
0158 continue;
0159 }
0160
0161
0162
0163
0164
0165 if constexpr (!interactionPointCut) {
0166
0167
0168
0169 if (outsideRangeCheck(deltaZ, -config.cotThetaMax * deltaR,
0170 config.cotThetaMax * deltaR)) {
0171 continue;
0172 }
0173
0174
0175 const float deltaX = xO - xM;
0176 const float deltaY = yO - yM;
0177
0178 const float xNewFrame =
0179 deltaX * middleSpInfo.cosPhiM + deltaY * middleSpInfo.sinPhiM;
0180 const float yNewFrame =
0181 deltaY * middleSpInfo.cosPhiM - deltaX * middleSpInfo.sinPhiM;
0182
0183 const float deltaR2 = deltaX * deltaX + deltaY * deltaY;
0184 const float iDeltaR2 = 1 / deltaR2;
0185
0186 const float uT = xNewFrame * iDeltaR2;
0187 const float vT = yNewFrame * iDeltaR2;
0188
0189 const float iDeltaR = std::sqrt(iDeltaR2);
0190 const float cotTheta = deltaZ * iDeltaR;
0191
0192 const float er = calculateError(otherSp, iDeltaR2, cotTheta);
0193
0194
0195 compatibleDoublets.emplace_back(
0196 otherSp.index(),
0197 {cotTheta, iDeltaR, er, uT, vT, xNewFrame, yNewFrame});
0198 continue;
0199 }
0200
0201
0202 const float deltaX = xO - xM;
0203 const float deltaY = yO - yM;
0204
0205 const float xNewFrame =
0206 deltaX * middleSpInfo.cosPhiM + deltaY * middleSpInfo.sinPhiM;
0207 const float yNewFrame =
0208 deltaY * middleSpInfo.cosPhiM - deltaX * middleSpInfo.sinPhiM;
0209
0210 const float deltaR2 = deltaX * deltaX + deltaY * deltaY;
0211 const float iDeltaR2 = 1 / deltaR2;
0212
0213 const float uT = xNewFrame * iDeltaR2;
0214 const float vT = yNewFrame * iDeltaR2;
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 if (std::abs(rM * yNewFrame) <= impactMax * xNewFrame) {
0226
0227
0228
0229 if (outsideRangeCheck(deltaZ, -config.cotThetaMax * deltaR,
0230 config.cotThetaMax * deltaR)) {
0231 continue;
0232 }
0233
0234 const float iDeltaR = std::sqrt(iDeltaR2);
0235 const float cotTheta = deltaZ * iDeltaR;
0236
0237
0238
0239 if constexpr (isBottomCandidate) {
0240 if (config.experimentCuts.connected() &&
0241 !config.experimentCuts(rO, cotTheta)) {
0242 continue;
0243 }
0244 }
0245
0246 const float er = calculateError(otherSp, iDeltaR2, cotTheta);
0247
0248
0249 compatibleDoublets.emplace_back(
0250 otherSp.index(),
0251 {cotTheta, iDeltaR, er, uT, vT, xNewFrame, yNewFrame});
0252 continue;
0253 }
0254
0255
0256
0257 const float vIP = (yNewFrame > 0) ? -vIPAbs : vIPAbs;
0258
0259
0260
0261
0262 const float aCoef = (vT - vIP) / (uT - middleSpInfo.uIP);
0263 const float bCoef = vIP - aCoef * middleSpInfo.uIP;
0264
0265
0266
0267 if ((bCoef * bCoef) * config.minHelixDiameter2 > 1 + aCoef * aCoef) {
0268 continue;
0269 }
0270
0271
0272
0273
0274 if (outsideRangeCheck(deltaZ, -config.cotThetaMax * deltaR,
0275 config.cotThetaMax * deltaR)) {
0276 continue;
0277 }
0278
0279 const float iDeltaR = std::sqrt(iDeltaR2);
0280 const float cotTheta = deltaZ * iDeltaR;
0281
0282
0283
0284 if constexpr (isBottomCandidate) {
0285 if (config.experimentCuts.connected() &&
0286 !config.experimentCuts(rO, cotTheta)) {
0287 continue;
0288 }
0289 }
0290
0291 const float er = calculateError(otherSp, iDeltaR2, cotTheta);
0292
0293
0294 compatibleDoublets.emplace_back(
0295 otherSp.index(), {cotTheta, iDeltaR, er, uT, vT, xNewFrame, yNewFrame});
0296 }
0297 }
0298
0299 }
0300
0301 DoubletSeedFinder::DerivedConfig::DerivedConfig(const Config& cfg,
0302 float bFieldInZ_)
0303 : Config(cfg), bFieldInZ(bFieldInZ_) {
0304
0305 const float pTPerHelixRadius = bFieldInZ;
0306 minHelixDiameter2 = square(minPt * 2 / pTPerHelixRadius) * helixCutTolerance;
0307 }
0308
0309 DoubletSeedFinder::MiddleSpInfo DoubletSeedFinder::computeMiddleSpInfo(
0310 const ConstSpacePointProxy2& spM) {
0311 const float rM = spM.r();
0312 const float uIP = -1 / rM;
0313 const float cosPhiM = -spM.x() * uIP;
0314 const float sinPhiM = -spM.y() * uIP;
0315 const float uIP2 = uIP * uIP;
0316
0317 return {uIP, uIP2, cosPhiM, sinPhiM};
0318 }
0319
0320 DoubletSeedFinder::DoubletSeedFinder(const DerivedConfig& cfg) : m_cfg(cfg) {}
0321
0322 void DoubletSeedFinder::createDoublets(
0323 const SpacePointContainer2& spacePoints,
0324 const ConstSpacePointProxy2& middleSp, const MiddleSpInfo& middleSpInfo,
0325 std::span<const SpacePointIndex2> candidateSps,
0326 DoubletsForMiddleSp& compatibleDoublets) const {
0327 std::size_t candidateOffset = 0;
0328
0329 if (m_cfg.candidateDirection == Direction::Backward() &&
0330 m_cfg.interactionPointCut) {
0331 return createDoubletsImpl<SpacePointCandidateType::Bottom, true, false>(
0332 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0333 candidateOffset, compatibleDoublets);
0334 }
0335
0336 if (m_cfg.candidateDirection == Direction::Backward() &&
0337 !m_cfg.interactionPointCut) {
0338 return createDoubletsImpl<SpacePointCandidateType::Bottom, false, false>(
0339 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0340 candidateOffset, compatibleDoublets);
0341 }
0342
0343 if (m_cfg.candidateDirection == Direction::Forward() &&
0344 m_cfg.interactionPointCut) {
0345 return createDoubletsImpl<SpacePointCandidateType::Top, true, false>(
0346 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0347 candidateOffset, compatibleDoublets);
0348 }
0349
0350 if (m_cfg.candidateDirection == Direction::Forward() &&
0351 !m_cfg.interactionPointCut) {
0352 return createDoubletsImpl<SpacePointCandidateType::Top, false, false>(
0353 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0354 candidateOffset, compatibleDoublets);
0355 }
0356
0357 throw std::logic_error("DoubletSeedFinder: unhandled configuration");
0358 }
0359
0360 void DoubletSeedFinder::createSortedDoublets(
0361 const SpacePointContainer2& spacePoints,
0362 const ConstSpacePointProxy2& middleSp, const MiddleSpInfo& middleSpInfo,
0363 std::span<const SpacePointIndex2> candidateSps,
0364 std::size_t& candidateOffset,
0365 DoubletsForMiddleSp& compatibleDoublets) const {
0366 if (m_cfg.candidateDirection == Direction::Backward() &&
0367 m_cfg.interactionPointCut) {
0368 return createDoubletsImpl<SpacePointCandidateType::Bottom, true, true>(
0369 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0370 candidateOffset, compatibleDoublets);
0371 }
0372
0373 if (m_cfg.candidateDirection == Direction::Backward() &&
0374 !m_cfg.interactionPointCut) {
0375 return createDoubletsImpl<SpacePointCandidateType::Bottom, false, true>(
0376 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0377 candidateOffset, compatibleDoublets);
0378 }
0379
0380 if (m_cfg.candidateDirection == Direction::Forward() &&
0381 m_cfg.interactionPointCut) {
0382 return createDoubletsImpl<SpacePointCandidateType::Top, true, true>(
0383 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0384 candidateOffset, compatibleDoublets);
0385 }
0386
0387 if (m_cfg.candidateDirection == Direction::Forward() &&
0388 !m_cfg.interactionPointCut) {
0389 return createDoubletsImpl<SpacePointCandidateType::Top, false, true>(
0390 config(), spacePoints, middleSp, middleSpInfo, candidateSps,
0391 candidateOffset, compatibleDoublets);
0392 }
0393
0394 throw std::logic_error("DoubletSeedFinder: unhandled configuration");
0395 }
0396
0397 }