File indexing completed on 2025-01-18 09:27:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/EventData/MultiTrajectoryHelpers.hpp"
0013 #include "Acts/EventData/TrackParameters.hpp"
0014 #include "Acts/EventData/TrackStateType.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/Propagator/StandardAborters.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/TrackFitting/GainMatrixSmoother.hpp"
0019 #include "Acts/Utilities/Logger.hpp"
0020 #include "Acts/Utilities/Result.hpp"
0021
0022 #include <utility>
0023
0024 namespace Acts {
0025
0026 enum class TrackExtrapolationStrategy {
0027
0028 first,
0029
0030 last,
0031
0032
0033 firstOrLast,
0034 };
0035
0036 enum class TrackExtrapolationError {
0037 CompatibleTrackStateNotFound = 1,
0038 ReferenceSurfaceUnreachable = 2,
0039 };
0040
0041 std::error_code make_error_code(TrackExtrapolationError e);
0042
0043 template <typename track_proxy_t>
0044 Result<typename track_proxy_t::ConstTrackStateProxy> findFirstMeasurementState(
0045 const track_proxy_t &track) {
0046 using TrackStateProxy = typename track_proxy_t::ConstTrackStateProxy;
0047
0048
0049
0050 auto result = Result<TrackStateProxy>::failure(
0051 TrackExtrapolationError::CompatibleTrackStateNotFound);
0052
0053 for (const auto &trackState : track.trackStatesReversed()) {
0054 bool isMeasurement =
0055 trackState.typeFlags().test(TrackStateFlag::MeasurementFlag);
0056 bool isOutlier = trackState.typeFlags().test(TrackStateFlag::OutlierFlag);
0057
0058 if (isMeasurement && !isOutlier) {
0059 result = trackState;
0060 }
0061 }
0062
0063 return result;
0064 }
0065
0066 template <typename track_proxy_t>
0067 Result<typename track_proxy_t::ConstTrackStateProxy> findLastMeasurementState(
0068 const track_proxy_t &track) {
0069 using TrackStateProxy = typename track_proxy_t::ConstTrackStateProxy;
0070
0071 for (const auto &trackState : track.trackStatesReversed()) {
0072 bool isMeasurement =
0073 trackState.typeFlags().test(TrackStateFlag::MeasurementFlag);
0074 bool isOutlier = trackState.typeFlags().test(TrackStateFlag::OutlierFlag);
0075
0076 if (isMeasurement && !isOutlier) {
0077 return trackState;
0078 }
0079 }
0080
0081 return Result<TrackStateProxy>::failure(
0082 TrackExtrapolationError::CompatibleTrackStateNotFound);
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 template <typename track_proxy_t>
0095 Result<void> smoothTrack(
0096 const GeometryContext &geoContext, track_proxy_t &track,
0097 const Logger &logger = *getDefaultLogger("TrackSmoother", Logging::INFO)) {
0098 Acts::GainMatrixSmoother smoother;
0099
0100 auto &trackContainer = track.container();
0101 auto &trackStateContainer = trackContainer.trackStateContainer();
0102
0103 auto last = findLastMeasurementState(track);
0104 if (!last.ok()) {
0105 ACTS_ERROR("no last track state found");
0106 return last.error();
0107 }
0108
0109 auto smoothingResult =
0110 smoother(geoContext, trackStateContainer, last->index(), logger);
0111
0112 if (!smoothingResult.ok()) {
0113 ACTS_ERROR("Smoothing track " << track.index() << " failed with error "
0114 << smoothingResult.error());
0115 return smoothingResult.error();
0116 }
0117
0118 return Result<void>::success();
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 template <typename track_container_t>
0131 Result<void> smoothTracks(
0132 const GeometryContext &geoContext, const track_container_t &trackContainer,
0133 const Logger &logger = *getDefaultLogger("TrackSmoother", Logging::INFO)) {
0134 Result<void> result = Result<void>::success();
0135
0136 for (const auto &track : trackContainer) {
0137 auto smoothingResult = smoothTrack(geoContext, track, logger);
0138
0139
0140 if (!smoothingResult.ok() && result.ok()) {
0141 result = smoothingResult.error();
0142 }
0143 }
0144
0145 return result;
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 template <typename track_proxy_t>
0161 Result<std::pair<typename track_proxy_t::ConstTrackStateProxy, double>>
0162 findTrackStateForExtrapolation(
0163 const GeometryContext &geoContext, const track_proxy_t &track,
0164 const Surface &referenceSurface, TrackExtrapolationStrategy strategy,
0165 const Logger &logger = *getDefaultLogger("TrackExtrapolation",
0166 Logging::INFO)) {
0167 using TrackStateProxy = typename track_proxy_t::ConstTrackStateProxy;
0168
0169 auto intersect = [&](const TrackStateProxy &state) -> SurfaceIntersection {
0170 assert(state.hasSmoothed() || state.hasFiltered());
0171
0172 FreeVector freeVector;
0173 if (state.hasSmoothed()) {
0174 freeVector = MultiTrajectoryHelpers::freeSmoothed(geoContext, state);
0175 } else {
0176 freeVector = MultiTrajectoryHelpers::freeFiltered(geoContext, state);
0177 }
0178
0179 return referenceSurface
0180 .intersect(geoContext, freeVector.template segment<3>(eFreePos0),
0181 freeVector.template segment<3>(eFreeDir0),
0182 BoundaryCheck(true), s_onSurfaceTolerance)
0183 .closest();
0184 };
0185
0186 switch (strategy) {
0187 case TrackExtrapolationStrategy::first: {
0188 ACTS_VERBOSE("looking for first track state");
0189
0190 auto first = findFirstMeasurementState(track);
0191 if (!first.ok()) {
0192 ACTS_ERROR("no first track state found");
0193 return first.error();
0194 }
0195
0196 SurfaceIntersection intersection = intersect(*first);
0197 if (!intersection) {
0198 ACTS_ERROR("no intersection found");
0199 return Result<std::pair<TrackStateProxy, double>>::failure(
0200 TrackExtrapolationError::ReferenceSurfaceUnreachable);
0201 }
0202
0203 ACTS_VERBOSE("found intersection at " << intersection.pathLength());
0204 return std::make_pair(*first, intersection.pathLength());
0205 }
0206
0207 case TrackExtrapolationStrategy::last: {
0208 ACTS_VERBOSE("looking for last track state");
0209
0210 auto last = findLastMeasurementState(track);
0211 if (!last.ok()) {
0212 ACTS_ERROR("no last track state found");
0213 return last.error();
0214 }
0215
0216 SurfaceIntersection intersection = intersect(*last);
0217 if (!intersection) {
0218 ACTS_ERROR("no intersection found");
0219 return Result<std::pair<TrackStateProxy, double>>::failure(
0220 TrackExtrapolationError::ReferenceSurfaceUnreachable);
0221 }
0222
0223 ACTS_VERBOSE("found intersection at " << intersection.pathLength());
0224 return std::make_pair(*last, intersection.pathLength());
0225 }
0226
0227 case TrackExtrapolationStrategy::firstOrLast: {
0228 ACTS_VERBOSE("looking for first or last track state");
0229
0230 auto first = findFirstMeasurementState(track);
0231 if (!first.ok()) {
0232 ACTS_ERROR("no first track state found");
0233 return first.error();
0234 }
0235
0236 auto last = findLastMeasurementState(track);
0237 if (!last.ok()) {
0238 ACTS_ERROR("no last track state found");
0239 return last.error();
0240 }
0241
0242 SurfaceIntersection intersectionFirst = intersect(*first);
0243 SurfaceIntersection intersectionLast = intersect(*last);
0244
0245 double absDistanceFirst = std::abs(intersectionFirst.pathLength());
0246 double absDistanceLast = std::abs(intersectionLast.pathLength());
0247
0248 if (intersectionFirst && absDistanceFirst <= absDistanceLast) {
0249 ACTS_VERBOSE("using first track state with intersection at "
0250 << intersectionFirst.pathLength());
0251 return std::make_pair(*first, intersectionFirst.pathLength());
0252 }
0253
0254 if (intersectionLast && absDistanceLast <= absDistanceFirst) {
0255 ACTS_VERBOSE("using last track state with intersection at "
0256 << intersectionLast.pathLength());
0257 return std::make_pair(*last, intersectionLast.pathLength());
0258 }
0259
0260 ACTS_ERROR("no intersection found");
0261 return Result<std::pair<TrackStateProxy, double>>::failure(
0262 TrackExtrapolationError::ReferenceSurfaceUnreachable);
0263 }
0264 }
0265
0266
0267 return Result<std::pair<TrackStateProxy, double>>::failure(
0268 TrackExtrapolationError::CompatibleTrackStateNotFound);
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 template <typename track_proxy_t, typename propagator_t,
0286 typename propagator_options_t>
0287 Result<void> extrapolateTrackToReferenceSurface(
0288 track_proxy_t &track, const Surface &referenceSurface,
0289 const propagator_t &propagator, propagator_options_t options,
0290 TrackExtrapolationStrategy strategy,
0291 const Logger &logger = *getDefaultLogger("TrackExtrapolation",
0292 Logging::INFO)) {
0293 auto findResult = findTrackStateForExtrapolation(
0294 options.geoContext, track, referenceSurface, strategy, logger);
0295
0296 if (!findResult.ok()) {
0297 ACTS_ERROR("failed to find track state for extrapolation");
0298 return findResult.error();
0299 }
0300
0301 auto &[trackState, distance] = *findResult;
0302
0303 options.direction = Direction::fromScalarZeroAsPositive(distance);
0304
0305 BoundTrackParameters parameters = track.createParametersFromState(trackState);
0306 ACTS_VERBOSE("extrapolating track to reference surface at distance "
0307 << distance << " with direction " << options.direction
0308 << " with starting parameters " << parameters);
0309
0310 auto propagateResult =
0311 propagator.template propagate<BoundTrackParameters, propagator_options_t,
0312 ForcedSurfaceReached>(
0313 parameters, referenceSurface, options);
0314
0315 if (!propagateResult.ok()) {
0316 ACTS_ERROR("failed to extrapolate track: " << propagateResult.error());
0317 return propagateResult.error();
0318 }
0319
0320 track.setReferenceSurface(referenceSurface.getSharedPtr());
0321 track.parameters() = propagateResult->endParameters.value().parameters();
0322 track.covariance() =
0323 propagateResult->endParameters.value().covariance().value();
0324
0325 return Result<void>::success();
0326 }
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342 template <typename track_container_t, typename propagator_t,
0343 typename propagator_options_t>
0344 Result<void> extrapolateTracksToReferenceSurface(
0345 const track_container_t &trackContainer, const Surface &referenceSurface,
0346 const propagator_t &propagator, propagator_options_t options,
0347 TrackExtrapolationStrategy strategy,
0348 const Logger &logger = *getDefaultLogger("TrackExtrapolation",
0349 Logging::INFO)) {
0350 Result<void> result = Result<void>::success();
0351
0352 for (const auto &track : trackContainer) {
0353 auto extrapolateResult = extrapolateTrackToReferenceSurface(
0354 track, referenceSurface, propagator, options, strategy, logger);
0355
0356
0357 if (!extrapolateResult.ok() && result.ok()) {
0358 result = extrapolateResult.error();
0359 }
0360 }
0361
0362 return result;
0363 }
0364
0365 }
0366
0367 namespace std {
0368
0369 template <>
0370 struct is_error_code_enum<Acts::TrackExtrapolationError> : std::true_type {};
0371 }