File indexing completed on 2025-10-13 08:16:38
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/SpacePointFormation2/StripSpacePointBuilder.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/SpacePointFormation2/PixelSpacePointBuilder.hpp"
0013 #include "Acts/SpacePointFormation2/SpacePointFormationError.hpp"
0014 #include "Acts/Utilities/MathHelpers.hpp"
0015 #include "Acts/Utilities/VectorHelpers.hpp"
0016
0017 namespace Acts {
0018
0019 Result<double> StripSpacePointBuilder::computeClusterPairDistance(
0020 const Vector3& globalCluster1, const Vector3& globalCluster2,
0021 const ClusterPairingOptions& options) {
0022
0023 if ((globalCluster1 - globalCluster2).norm() > options.maxDistance) {
0024 return Result<double>::failure(
0025 SpacePointFormationError::ClusterPairDistanceExceeded);
0026 }
0027
0028 const Vector3 vertexToCluster1 = globalCluster1 - options.vertex;
0029 const Vector3 vertexToCluster2 = globalCluster2 - options.vertex;
0030
0031
0032 const double phi1 = VectorHelpers::phi(vertexToCluster1);
0033 const double theta1 = VectorHelpers::theta(vertexToCluster1);
0034 const double phi2 = VectorHelpers::phi(vertexToCluster2);
0035 const double theta2 = VectorHelpers::theta(vertexToCluster2);
0036
0037
0038 const double diffTheta = std::abs(theta1 - theta2);
0039 if (diffTheta > options.maxAngleTheta) {
0040 return Result<double>::failure(
0041 SpacePointFormationError::ClusterPairThetaDistanceExceeded);
0042 }
0043
0044
0045 const double diffPhi = std::abs(phi1 - phi2);
0046 if (diffPhi > options.maxAnglePhi) {
0047 return Result<double>::failure(
0048 SpacePointFormationError::ClusterPairPhiDistanceExceeded);
0049 }
0050
0051
0052 const double distance2 = square(diffTheta) + square(diffPhi);
0053 return Result<double>::success(distance2);
0054 }
0055
0056 Result<Vector3> StripSpacePointBuilder::computeCosmicSpacePoint(
0057 const StripEnds& stripEnds1, const StripEnds& stripEnds2,
0058 const CosmicOptions& options) {
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 const Vector3 firstBtmToTop = stripEnds1.top - stripEnds1.bottom;
0070 const Vector3 secondBtmToTop = stripEnds2.top - stripEnds2.bottom;
0071
0072 const Vector3 ac = stripEnds2.top - stripEnds1.top;
0073 const double qr = firstBtmToTop.dot(secondBtmToTop);
0074 const double denom = firstBtmToTop.dot(firstBtmToTop) - qr * qr;
0075
0076 if (std::abs(denom) < options.tolerance) {
0077 return Result<Vector3>::failure(
0078 SpacePointFormationError::CosmicToleranceNotMet);
0079 }
0080
0081 const double lambda0 =
0082 (ac.dot(secondBtmToTop) * qr -
0083 ac.dot(firstBtmToTop) * secondBtmToTop.dot(secondBtmToTop)) /
0084 denom;
0085 const Vector3 spacePoint = stripEnds1.top + lambda0 * firstBtmToTop;
0086 return Result<Vector3>::success(spacePoint);
0087 }
0088
0089 namespace {
0090
0091
0092 struct FormationState {
0093
0094 Vector3 firstBtmToTop = Vector3::Zero();
0095
0096 Vector3 secondBtmToTop = Vector3::Zero();
0097
0098 Vector3 vtxToFirstMid2 = Vector3::Zero();
0099
0100 Vector3 vtxToSecondMid2 = Vector3::Zero();
0101
0102 Vector3 firstBtmToTopXvtxToFirstMid2 = Vector3::Zero();
0103
0104 Vector3 secondBtmToTopXvtxToSecondMid2 = Vector3::Zero();
0105
0106 double m = 0;
0107
0108 double n = 0;
0109
0110 double limit = 1;
0111 };
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 Result<void> computeConstrainedFormationState(
0124 const StripSpacePointBuilder::StripEnds& stripEnds1,
0125 const StripSpacePointBuilder::StripEnds& stripEnds2, const Vector3& vertex,
0126 FormationState& state, const double stripLengthTolerance) {
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 state.firstBtmToTop = stripEnds1.top - stripEnds1.bottom;
0149 state.secondBtmToTop = stripEnds2.top - stripEnds2.bottom;
0150 state.vtxToFirstMid2 = stripEnds1.top + stripEnds1.bottom - 2 * vertex;
0151 state.vtxToSecondMid2 = stripEnds2.top + stripEnds2.bottom - 2 * vertex;
0152 state.firstBtmToTopXvtxToFirstMid2 =
0153 state.firstBtmToTop.cross(state.vtxToFirstMid2);
0154 state.secondBtmToTopXvtxToSecondMid2 =
0155 state.secondBtmToTop.cross(state.vtxToSecondMid2);
0156 state.m = -state.vtxToFirstMid2.dot(state.secondBtmToTopXvtxToSecondMid2) /
0157 state.firstBtmToTop.dot(state.secondBtmToTopXvtxToSecondMid2);
0158 state.n = -state.vtxToSecondMid2.dot(state.firstBtmToTopXvtxToFirstMid2) /
0159 state.secondBtmToTop.dot(state.firstBtmToTopXvtxToFirstMid2);
0160
0161
0162 state.limit = 1 + stripLengthTolerance;
0163
0164
0165 if (std::abs(state.m) > state.limit || std::abs(state.n) > state.limit) {
0166 return Result<void>::failure(SpacePointFormationError::OutsideLimits);
0167 }
0168 return Result<void>::success();
0169 }
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 Result<void> recoverConstrainedFormationState(
0180 FormationState& state, const double stripLengthGapTolerance) {
0181 const double magFirstBtmToTop = state.firstBtmToTop.norm();
0182
0183
0184 const double relaxedLimit =
0185 state.limit + stripLengthGapTolerance / magFirstBtmToTop;
0186
0187
0188 if (std::abs(state.m) > relaxedLimit) {
0189 return Result<void>::failure(
0190 SpacePointFormationError::OutsideRelaxedLimits);
0191 }
0192
0193 if (state.n == 0) {
0194 state.n = -state.vtxToSecondMid2.dot(state.firstBtmToTopXvtxToFirstMid2) /
0195 state.secondBtmToTop.dot(state.firstBtmToTopXvtxToFirstMid2);
0196 }
0197
0198 if (std::abs(state.n) > relaxedLimit) {
0199 return Result<void>::failure(
0200 SpacePointFormationError::OutsideRelaxedLimits);
0201 }
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 const double secOnFirstScale =
0224 state.firstBtmToTop.dot(state.secondBtmToTop) / square(magFirstBtmToTop);
0225
0226
0227 if (state.m > 1 && state.n > 1) {
0228
0229 const double mOvershoot = state.m - 1;
0230
0231 const double nOvershoot = (state.n - 1) * secOnFirstScale;
0232
0233 const double biggerOvershoot = std::max(mOvershoot, nOvershoot);
0234
0235 state.m -= biggerOvershoot;
0236 state.n -= (biggerOvershoot / secOnFirstScale);
0237
0238 if (std::abs(state.m) > state.limit || std::abs(state.n) > state.limit) {
0239 return Result<void>::failure(SpacePointFormationError::OutsideLimits);
0240 }
0241 return Result<void>::success();
0242 }
0243
0244
0245 if (state.m < -1 && state.n < -1) {
0246
0247 const double mOvershoot = -(state.m + 1);
0248
0249 const double nOvershoot = -(state.n + 1) * secOnFirstScale;
0250
0251 const double biggerOvershoot = std::max(mOvershoot, nOvershoot);
0252
0253 state.m += biggerOvershoot;
0254 state.n += (biggerOvershoot / secOnFirstScale);
0255
0256 if (std::abs(state.m) > state.limit || std::abs(state.n) > state.limit) {
0257 return Result<void>::failure(SpacePointFormationError::OutsideLimits);
0258 }
0259 return Result<void>::success();
0260 }
0261
0262
0263 return Result<void>::failure(SpacePointFormationError::NoSolutionFound);
0264 }
0265
0266 }
0267
0268 Result<Vector3> StripSpacePointBuilder::computeConstrainedSpacePoint(
0269 const StripEnds& stripEnds1, const StripEnds& stripEnds2,
0270 const ConstrainedOptions& options) {
0271 FormationState state;
0272
0273 Result<void> result =
0274 computeConstrainedFormationState(stripEnds1, stripEnds2, options.vertex,
0275 state, options.stripLengthTolerance);
0276
0277 if (!result.ok()) {
0278 result = recoverConstrainedFormationState(state,
0279 options.stripLengthGapTolerance);
0280 }
0281
0282 if (!result.ok()) {
0283 return Result<Vector3>::failure(result.error());
0284 }
0285
0286 const Vector3 spacePoint = 0.5 * (stripEnds1.top + stripEnds1.bottom +
0287 state.m * state.firstBtmToTop);
0288 return Result<Vector3>::success(spacePoint);
0289 }
0290
0291 Vector2 StripSpacePointBuilder::computeVarianceZR(const GeometryContext& gctx,
0292 const Surface& surface1,
0293 const Vector3& spacePoint,
0294 const double localCov1,
0295 const double localCov2,
0296 const double theta) {
0297 const double sinThetaHalf = std::sin(0.5 * theta);
0298 const double cosThetaHalf = std::cos(0.5 * theta);
0299
0300
0301 const double var = fastHypot(localCov1, localCov2);
0302 const double varX = var / (2 * sinThetaHalf);
0303 const double varY = var / (2 * cosThetaHalf);
0304
0305
0306 const double varX1 = varX * cosThetaHalf + varY * sinThetaHalf;
0307 const double varY1 = varY * cosThetaHalf + varX * sinThetaHalf;
0308 const SquareMatrix2 localCov = Vector2(varX1, varY1).asDiagonal();
0309
0310 return PixelSpacePointBuilder::computeVarianceZR(gctx, surface1, spacePoint,
0311 localCov);
0312 }
0313
0314 }