Warning, file /include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "Acts/Utilities/detail/ReferenceWrapperAnyCompat.hpp"
0013
0014 #include "Acts/Definitions/Common.hpp"
0015 #include "Acts/EventData/MultiTrajectory.hpp"
0016 #include "Acts/EventData/MultiTrajectoryHelpers.hpp"
0017 #include "Acts/EventData/TrackParameters.hpp"
0018 #include "Acts/EventData/TrackStatePropMask.hpp"
0019 #include "Acts/EventData/Types.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0022 #include "Acts/Propagator/ActorList.hpp"
0023 #include "Acts/Propagator/ConstrainedStep.hpp"
0024 #include "Acts/Propagator/PropagatorState.hpp"
0025 #include "Acts/Propagator/StandardAborters.hpp"
0026 #include "Acts/Propagator/detail/LoopProtection.hpp"
0027 #include "Acts/Propagator/detail/PointwiseMaterialInteraction.hpp"
0028 #include "Acts/TrackFinding/CombinatorialKalmanFilterError.hpp"
0029 #include "Acts/TrackFinding/CombinatorialKalmanFilterExtensions.hpp"
0030 #include "Acts/Utilities/CalibrationContext.hpp"
0031 #include "Acts/Utilities/Logger.hpp"
0032 #include "Acts/Utilities/Result.hpp"
0033
0034 #include <functional>
0035 #include <limits>
0036 #include <memory>
0037 #include <type_traits>
0038
0039 namespace Acts {
0040
0041
0042
0043
0044
0045 template <typename track_container_t>
0046 struct CombinatorialKalmanFilterOptions {
0047 using TrackStateContainerBackend =
0048 typename track_container_t::TrackStateContainerBackend;
0049 using TrackStateProxy = typename track_container_t::TrackStateProxy;
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 CombinatorialKalmanFilterOptions(
0061 const GeometryContext& gctx, const MagneticFieldContext& mctx,
0062 std::reference_wrapper<const CalibrationContext> cctx,
0063 CombinatorialKalmanFilterExtensions<track_container_t> extensions_,
0064 const PropagatorPlainOptions& pOptions, bool mScattering = true,
0065 bool eLoss = true)
0066 : geoContext(gctx),
0067 magFieldContext(mctx),
0068 calibrationContext(cctx),
0069 extensions(extensions_),
0070 propagatorPlainOptions(pOptions),
0071 multipleScattering(mScattering),
0072 energyLoss(eLoss) {}
0073
0074
0075 CombinatorialKalmanFilterOptions() = delete;
0076
0077
0078 std::reference_wrapper<const GeometryContext> geoContext;
0079
0080 std::reference_wrapper<const MagneticFieldContext> magFieldContext;
0081
0082 std::reference_wrapper<const CalibrationContext> calibrationContext;
0083
0084
0085 CombinatorialKalmanFilterExtensions<track_container_t> extensions;
0086
0087
0088 PropagatorPlainOptions propagatorPlainOptions;
0089
0090
0091
0092
0093 const Surface* targetSurface = nullptr;
0094
0095
0096 bool multipleScattering = true;
0097
0098
0099 bool energyLoss = true;
0100
0101
0102
0103 bool skipPrePropagationUpdate = false;
0104 };
0105
0106 template <typename track_container_t>
0107 struct CombinatorialKalmanFilterResult {
0108 using TrackStateContainerBackend =
0109 typename track_container_t::TrackStateContainerBackend;
0110 using TrackProxy = typename track_container_t::TrackProxy;
0111 using TrackStateProxy = typename track_container_t::TrackStateProxy;
0112
0113
0114 track_container_t* tracks{nullptr};
0115
0116
0117 TrackStateContainerBackend* trackStates{nullptr};
0118
0119
0120 std::vector<TrackProxy> activeBranches;
0121
0122
0123 std::vector<TrackProxy> collectedTracks;
0124
0125
0126 std::vector<TrackStateProxy> trackStateCandidates;
0127
0128
0129 bool finished = false;
0130
0131
0132 Result<void> lastError{Result<void>::success()};
0133
0134
0135 PathLimitReached pathLimitReached;
0136 };
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 template <typename propagator_t, typename track_container_t>
0158 class CombinatorialKalmanFilter {
0159 public:
0160
0161 CombinatorialKalmanFilter() = delete;
0162
0163 CombinatorialKalmanFilter(propagator_t pPropagator,
0164 std::unique_ptr<const Logger> _logger =
0165 getDefaultLogger("CKF", Logging::INFO))
0166 : m_propagator(std::move(pPropagator)),
0167 m_logger(std::move(_logger)),
0168 m_actorLogger{m_logger->cloneWithSuffix("Actor")},
0169 m_updaterLogger{m_logger->cloneWithSuffix("Updater")} {}
0170
0171 private:
0172 using BoundState = std::tuple<BoundTrackParameters, BoundMatrix, double>;
0173 using TrackStateContainerBackend =
0174 typename track_container_t::TrackStateContainerBackend;
0175 using TrackProxy = typename track_container_t::TrackProxy;
0176 using TrackStateProxy = typename track_container_t::TrackStateProxy;
0177
0178
0179 propagator_t m_propagator;
0180
0181 std::unique_ptr<const Logger> m_logger;
0182 std::shared_ptr<const Logger> m_actorLogger;
0183 std::shared_ptr<const Logger> m_updaterLogger;
0184
0185 const Logger& logger() const { return *m_logger; }
0186
0187
0188
0189
0190
0191
0192
0193 template <typename parameters_t>
0194 class Actor {
0195 public:
0196 using BoundState = std::tuple<parameters_t, BoundMatrix, double>;
0197 using CurvilinearState =
0198 std::tuple<CurvilinearTrackParameters, BoundMatrix, double>;
0199
0200 using result_type = CombinatorialKalmanFilterResult<track_container_t>;
0201
0202 using BranchStopperResult = CombinatorialKalmanFilterBranchStopperResult;
0203
0204
0205 SurfaceReached targetReached{std::numeric_limits<double>::lowest()};
0206
0207
0208 bool multipleScattering = true;
0209
0210
0211 bool energyLoss = true;
0212
0213
0214 bool skipPrePropagationUpdate = false;
0215
0216
0217 const CalibrationContext* calibrationContextPtr{nullptr};
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228 template <typename propagator_state_t, typename stepper_t,
0229 typename navigator_t>
0230 void act(propagator_state_t& state, const stepper_t& stepper,
0231 const navigator_t& navigator, result_type& result,
0232 const Logger& ) const {
0233 assert(result.trackStates && "No MultiTrajectory set");
0234
0235 if (result.finished) {
0236 return;
0237 }
0238
0239 if (state.stage == PropagatorStage::prePropagation &&
0240 skipPrePropagationUpdate) {
0241 ACTS_VERBOSE("Skip pre-propagation update (first surface)");
0242 return;
0243 }
0244
0245 ACTS_VERBOSE("CombinatorialKalmanFilter step");
0246
0247 assert(!result.activeBranches.empty() && "No active branches");
0248
0249
0250 if (result.pathLimitReached.internalLimit ==
0251 std::numeric_limits<double>::max()) {
0252 detail::setupLoopProtection(state, stepper, result.pathLimitReached,
0253 true, logger());
0254 }
0255
0256
0257
0258 if (auto surface = navigator.currentSurface(state.navigation);
0259 surface != nullptr) {
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 ACTS_VERBOSE("Perform filter step");
0275 auto res = filter(surface, state, stepper, navigator, result);
0276 if (!res.ok()) {
0277 ACTS_ERROR("Error in filter: " << res.error());
0278 result.lastError = res.error();
0279 }
0280
0281 if (result.finished) {
0282 return;
0283 }
0284 }
0285
0286 assert(!result.activeBranches.empty() && "No active branches");
0287
0288 const bool isEndOfWorldReached =
0289 endOfWorldReached.checkAbort(state, stepper, navigator, logger());
0290 const bool isVolumeConstraintReached = volumeConstraintAborter.checkAbort(
0291 state, stepper, navigator, logger());
0292 const bool isPathLimitReached = result.pathLimitReached.checkAbort(
0293 state, stepper, navigator, logger());
0294 const bool isTargetReached =
0295 targetReached.checkAbort(state, stepper, navigator, logger());
0296 if (isEndOfWorldReached || isVolumeConstraintReached ||
0297 isPathLimitReached || isTargetReached) {
0298 if (isEndOfWorldReached) {
0299 ACTS_VERBOSE("End of world reached");
0300 } else if (isVolumeConstraintReached) {
0301 ACTS_VERBOSE("Volume constraint reached");
0302 } else if (isPathLimitReached) {
0303 ACTS_VERBOSE("Path limit reached");
0304 } else if (isTargetReached) {
0305 ACTS_VERBOSE("Target surface reached");
0306
0307
0308 auto res = stepper.boundState(state.stepping, *targetReached.surface);
0309 if (!res.ok()) {
0310 ACTS_ERROR("Error while acquiring bound state for target surface: "
0311 << res.error() << " " << res.error().message());
0312 result.lastError = res.error();
0313 } else {
0314 const auto& [boundParams, jacobian, pathLength] = *res;
0315 auto currentBranch = result.activeBranches.back();
0316
0317 currentBranch.parameters() = boundParams.parameters();
0318 currentBranch.covariance() = *boundParams.covariance();
0319 currentBranch.setReferenceSurface(
0320 boundParams.referenceSurface().getSharedPtr());
0321 }
0322
0323 stepper.releaseStepSize(state.stepping,
0324 ConstrainedStep::Type::Navigator);
0325 }
0326
0327
0328 storeLastActiveBranch(result);
0329 result.activeBranches.pop_back();
0330
0331
0332 reset(state, stepper, navigator, result);
0333 }
0334 }
0335
0336 template <typename propagator_state_t, typename stepper_t,
0337 typename navigator_t>
0338 bool checkAbort(propagator_state_t& , const stepper_t& ,
0339 const navigator_t& , const result_type& result,
0340 const Logger& ) const {
0341 return !result.lastError.ok() || result.finished;
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 template <typename propagator_state_t, typename stepper_t,
0355 typename navigator_t>
0356 void reset(propagator_state_t& state, const stepper_t& stepper,
0357 const navigator_t& navigator, result_type& result) const {
0358 if (result.activeBranches.empty()) {
0359 ACTS_VERBOSE("Stop CKF with " << result.collectedTracks.size()
0360 << " found tracks");
0361 result.finished = true;
0362
0363 return;
0364 }
0365
0366 auto currentBranch = result.activeBranches.back();
0367 auto currentState = currentBranch.outermostTrackState();
0368
0369 ACTS_VERBOSE("Propagation jumps to branch with tip = "
0370 << currentBranch.tipIndex());
0371
0372
0373 stepper.initialize(state.stepping, currentState.filtered(),
0374 currentState.filteredCovariance(),
0375 stepper.particleHypothesis(state.stepping),
0376 currentState.referenceSurface());
0377
0378
0379
0380 state.navigation.options.startSurface = ¤tState.referenceSurface();
0381 state.navigation.options.targetSurface = nullptr;
0382 auto navInitRes = navigator.initialize(
0383 state.navigation, stepper.position(state.stepping),
0384 stepper.direction(state.stepping), state.options.direction);
0385 if (!navInitRes.ok()) {
0386 ACTS_ERROR("Navigation initialization failed: " << navInitRes.error());
0387 result.lastError = navInitRes.error();
0388 }
0389
0390
0391
0392 materialInteractor(navigator.currentSurface(state.navigation), state,
0393 stepper, navigator, MaterialUpdateStage::PostUpdate);
0394
0395
0396 detail::setupLoopProtection(state, stepper, result.pathLimitReached, true,
0397 logger());
0398
0399
0400 targetReached.checkAbort(state, stepper, navigator, logger());
0401 }
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 template <typename propagator_state_t, typename stepper_t,
0418 typename navigator_t>
0419 Result<void> filter(const Surface* surface, propagator_state_t& state,
0420 const stepper_t& stepper, const navigator_t& navigator,
0421 result_type& result) const {
0422 using PM = TrackStatePropMask;
0423
0424 bool isSensitive = surface->associatedDetectorElement() != nullptr;
0425 bool hasMaterial = surface->surfaceMaterial() != nullptr;
0426 bool isMaterialOnly = hasMaterial && !isSensitive;
0427 bool expectMeasurements = isSensitive;
0428
0429 if (isSensitive) {
0430 ACTS_VERBOSE("Measurement surface " << surface->geometryId()
0431 << " detected.");
0432 } else if (isMaterialOnly) {
0433 ACTS_VERBOSE("Material surface " << surface->geometryId()
0434 << " detected.");
0435 } else {
0436 ACTS_VERBOSE("Passive surface " << surface->geometryId()
0437 << " detected.");
0438 return Result<void>::success();
0439 }
0440
0441
0442 if (isMaterialOnly) {
0443 stepper.transportCovarianceToCurvilinear(state.stepping);
0444 } else {
0445 stepper.transportCovarianceToBound(state.stepping, *surface);
0446 }
0447
0448
0449 materialInteractor(surface, state, stepper, navigator,
0450 MaterialUpdateStage::PreUpdate);
0451
0452
0453 auto boundStateRes = stepper.boundState(state.stepping, *surface, false);
0454 if (!boundStateRes.ok()) {
0455 return boundStateRes.error();
0456 }
0457 auto& boundState = *boundStateRes;
0458 auto& [boundParams, jacobian, pathLength] = boundState;
0459 boundParams.covariance() = state.stepping.cov;
0460
0461 auto currentBranch = result.activeBranches.back();
0462 TrackIndexType prevTip = currentBranch.tipIndex();
0463
0464 using TrackStatesResult =
0465 Acts::Result<CkfTypes::BranchVector<TrackIndexType>>;
0466 TrackStatesResult tsRes = TrackStatesResult::success({});
0467 if (isSensitive) {
0468
0469
0470
0471 tsRes = m_extensions.createTrackStates(
0472 state.geoContext, *calibrationContextPtr, *surface, boundState,
0473 prevTip, result.trackStateCandidates, *result.trackStates,
0474 logger());
0475 if (!tsRes.ok()) {
0476 ACTS_ERROR("Track state creation failed on surface "
0477 << surface->geometryId() << ": " << tsRes.error());
0478 return tsRes.error();
0479 }
0480 }
0481 const CkfTypes::BranchVector<TrackIndexType>& newTrackStateList = *tsRes;
0482
0483 if (!newTrackStateList.empty()) {
0484 Result<unsigned int> procRes =
0485 processNewTrackStates(state.geoContext, newTrackStateList, result);
0486 if (!procRes.ok()) {
0487 ACTS_ERROR("Processing of selected track states failed: "
0488 << procRes.error());
0489 return procRes.error();
0490 }
0491 unsigned int nBranchesOnSurface = *procRes;
0492
0493 if (nBranchesOnSurface == 0) {
0494 ACTS_VERBOSE("All branches on surface " << surface->geometryId()
0495 << " have been stopped");
0496
0497 reset(state, stepper, navigator, result);
0498
0499 return Result<void>::success();
0500 }
0501
0502
0503 currentBranch = result.activeBranches.back();
0504 prevTip = currentBranch.tipIndex();
0505 } else {
0506 if (expectMeasurements) {
0507 ACTS_VERBOSE("Detected hole after measurement selection on surface "
0508 << surface->geometryId());
0509 }
0510
0511 auto stateMask = PM::Predicted | PM::Jacobian;
0512
0513
0514 TrackIndexType currentTip = addNonSourcelinkState(
0515 stateMask, boundState, result, expectMeasurements, prevTip);
0516 currentBranch.tipIndex() = currentTip;
0517 auto currentState = currentBranch.outermostTrackState();
0518 if (expectMeasurements) {
0519 currentBranch.nHoles()++;
0520 }
0521
0522 BranchStopperResult branchStopperResult =
0523 m_extensions.branchStopper(currentBranch, currentState);
0524
0525
0526 if (branchStopperResult == BranchStopperResult::Continue) {
0527
0528 } else {
0529
0530 if (branchStopperResult == BranchStopperResult::StopAndKeep) {
0531 storeLastActiveBranch(result);
0532 }
0533
0534 result.activeBranches.pop_back();
0535
0536
0537 ACTS_VERBOSE("Branch on surface " << surface->geometryId()
0538 << " has been stopped");
0539
0540 reset(state, stepper, navigator, result);
0541
0542 return Result<void>::success();
0543 }
0544 }
0545
0546 auto currentState = currentBranch.outermostTrackState();
0547
0548 if (currentState.typeFlags().test(TrackStateFlag::OutlierFlag)) {
0549
0550 ACTS_VERBOSE("Outlier state detected on surface "
0551 << surface->geometryId());
0552 } else if (currentState.typeFlags().test(
0553 TrackStateFlag::MeasurementFlag)) {
0554
0555
0556
0557 stepper.update(state.stepping,
0558 MultiTrajectoryHelpers::freeFiltered(
0559 state.options.geoContext, currentState),
0560 currentState.filtered(),
0561 currentState.filteredCovariance(), *surface);
0562 ACTS_VERBOSE("Stepping state is updated with filtered parameter:");
0563 ACTS_VERBOSE("-> " << currentState.filtered().transpose()
0564 << " of track state with tip = "
0565 << currentState.index());
0566 }
0567
0568
0569 materialInteractor(surface, state, stepper, navigator,
0570 MaterialUpdateStage::PostUpdate);
0571
0572 return Result<void>::success();
0573 }
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585 Result<unsigned int> processNewTrackStates(
0586 const Acts::GeometryContext& gctx,
0587 const CkfTypes::BranchVector<TrackIndexType>& newTrackStateList,
0588 result_type& result) const {
0589 using PM = TrackStatePropMask;
0590
0591 unsigned int nBranchesOnSurface = 0;
0592
0593 auto rootBranch = result.activeBranches.back();
0594
0595
0596
0597 CkfTypes::BranchVector<TrackProxy> newBranches;
0598 for (auto it = newTrackStateList.rbegin(); it != newTrackStateList.rend();
0599 ++it) {
0600
0601
0602 auto newBranch = (it == newTrackStateList.rbegin())
0603 ? rootBranch
0604 : rootBranch.shallowCopy();
0605 newBranch.tipIndex() = *it;
0606 newBranches.push_back(newBranch);
0607 }
0608
0609
0610 result.activeBranches.pop_back();
0611
0612
0613 for (TrackProxy newBranch : newBranches) {
0614 auto trackState = newBranch.outermostTrackState();
0615 TrackStateType typeFlags = trackState.typeFlags();
0616
0617 if (typeFlags.test(TrackStateFlag::OutlierFlag)) {
0618
0619
0620
0621 trackState.shareFrom(PM::Predicted, PM::Filtered);
0622
0623 newBranch.nOutliers()++;
0624 } else if (typeFlags.test(TrackStateFlag::MeasurementFlag)) {
0625
0626 auto updateRes =
0627 m_extensions.updater(gctx, trackState, *updaterLogger);
0628 if (!updateRes.ok()) {
0629 ACTS_ERROR("Update step failed: " << updateRes.error());
0630 return updateRes.error();
0631 }
0632 ACTS_VERBOSE("Appended measurement track state with tip = "
0633 << newBranch.tipIndex());
0634
0635 typeFlags.set(TrackStateFlag::MeasurementFlag);
0636
0637 newBranch.nMeasurements()++;
0638 newBranch.nDoF() += trackState.calibratedSize();
0639 newBranch.chi2() += trackState.chi2();
0640 } else {
0641 ACTS_WARNING("Cannot handle this track state flags");
0642 continue;
0643 }
0644
0645 result.activeBranches.push_back(newBranch);
0646
0647 BranchStopperResult branchStopperResult =
0648 m_extensions.branchStopper(newBranch, trackState);
0649
0650
0651 if (branchStopperResult == BranchStopperResult::Continue) {
0652
0653 nBranchesOnSurface++;
0654 } else {
0655
0656 if (branchStopperResult == BranchStopperResult::StopAndKeep) {
0657 storeLastActiveBranch(result);
0658 }
0659
0660 result.activeBranches.pop_back();
0661 }
0662 }
0663
0664 return nBranchesOnSurface;
0665 }
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676 TrackIndexType addNonSourcelinkState(TrackStatePropMask stateMask,
0677 const BoundState& boundState,
0678 result_type& result, bool isSensitive,
0679 TrackIndexType prevTip) const {
0680 using PM = TrackStatePropMask;
0681
0682
0683 auto trackStateProxy =
0684 result.trackStates->makeTrackState(stateMask, prevTip);
0685 ACTS_VERBOSE("Create " << (isSensitive ? "Hole" : "Material")
0686 << " output track state #"
0687 << trackStateProxy.index()
0688 << " with mask: " << stateMask);
0689
0690 const auto& [boundParams, jacobian, pathLength] = boundState;
0691
0692 trackStateProxy.predicted() = boundParams.parameters();
0693 trackStateProxy.predictedCovariance() = boundParams.covariance().value();
0694 trackStateProxy.jacobian() = jacobian;
0695 trackStateProxy.pathLength() = pathLength;
0696
0697 trackStateProxy.setReferenceSurface(
0698 boundParams.referenceSurface().getSharedPtr());
0699
0700
0701 auto typeFlags = trackStateProxy.typeFlags();
0702 if (trackStateProxy.referenceSurface().surfaceMaterial() != nullptr) {
0703 typeFlags.set(TrackStateFlag::MaterialFlag);
0704 }
0705 typeFlags.set(TrackStateFlag::ParameterFlag);
0706 if (isSensitive) {
0707 typeFlags.set(TrackStateFlag::HoleFlag);
0708 }
0709
0710
0711
0712 trackStateProxy.shareFrom(PM::Predicted, PM::Filtered);
0713
0714 return trackStateProxy.index();
0715 }
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728 template <typename propagator_state_t, typename stepper_t,
0729 typename navigator_t>
0730 void materialInteractor(const Surface* surface, propagator_state_t& state,
0731 const stepper_t& stepper,
0732 const navigator_t& navigator,
0733 const MaterialUpdateStage& updateStage) const {
0734 if (surface == nullptr) {
0735 return;
0736 }
0737
0738
0739 bool hasMaterial = false;
0740
0741 if (surface->surfaceMaterial() != nullptr) {
0742
0743 detail::PointwiseMaterialInteraction interaction(surface, state,
0744 stepper);
0745
0746 if (interaction.evaluateMaterialSlab(state, navigator, updateStage)) {
0747
0748 hasMaterial = true;
0749
0750
0751 interaction.evaluatePointwiseMaterialInteraction(multipleScattering,
0752 energyLoss);
0753
0754
0755 ACTS_VERBOSE("Material effects on surface: "
0756 << surface->geometryId()
0757 << " at update stage: " << updateStage << " are :");
0758 ACTS_VERBOSE("eLoss = "
0759 << interaction.Eloss * interaction.navDir << ", "
0760 << "variancePhi = " << interaction.variancePhi << ", "
0761 << "varianceTheta = " << interaction.varianceTheta
0762 << ", "
0763 << "varianceQoverP = " << interaction.varianceQoverP);
0764
0765
0766 interaction.updateState(state, stepper, addNoise);
0767 }
0768 }
0769
0770 if (!hasMaterial) {
0771
0772 ACTS_VERBOSE("No material effects on surface: " << surface->geometryId()
0773 << " at update stage: "
0774 << updateStage);
0775 }
0776 }
0777
0778 void storeLastActiveBranch(result_type& result) const {
0779 auto currentBranch = result.activeBranches.back();
0780 TrackIndexType currentTip = currentBranch.tipIndex();
0781
0782 ACTS_VERBOSE("Storing track "
0783 << currentBranch.index() << " with tip index " << currentTip
0784 << ". nMeasurements = " << currentBranch.nMeasurements()
0785 << ", nOutliers = " << currentBranch.nOutliers()
0786 << ", nHoles = " << currentBranch.nHoles());
0787
0788 result.collectedTracks.push_back(currentBranch);
0789 }
0790
0791 CombinatorialKalmanFilterExtensions<track_container_t> m_extensions;
0792
0793
0794 EndOfWorldReached endOfWorldReached;
0795
0796
0797 VolumeConstraintAborter volumeConstraintAborter;
0798
0799
0800 const Logger* actorLogger{nullptr};
0801
0802 const Logger* updaterLogger{nullptr};
0803
0804 const Logger& logger() const { return *actorLogger; }
0805 };
0806
0807
0808
0809 struct StubPathLimitReached {
0810 double internalLimit{};
0811
0812 template <typename propagator_state_t, typename stepper_t,
0813 typename navigator_t>
0814 bool checkAbort(propagator_state_t& , const stepper_t& ,
0815 const navigator_t& ,
0816 const Logger& ) const {
0817 return false;
0818 }
0819 };
0820
0821 public:
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839 template <typename start_parameters_t,
0840 typename parameters_t = BoundTrackParameters>
0841 auto findTracks(
0842 const start_parameters_t& initialParameters,
0843 const CombinatorialKalmanFilterOptions<track_container_t>& tfOptions,
0844 track_container_t& trackContainer,
0845 typename track_container_t::TrackProxy rootBranch) const
0846 -> Result<std::vector<
0847 typename std::decay_t<decltype(trackContainer)>::TrackProxy>> {
0848
0849 using CombinatorialKalmanFilterActor = Actor<parameters_t>;
0850 using Actors = ActorList<CombinatorialKalmanFilterActor>;
0851
0852
0853 using PropagatorOptions = typename propagator_t::template Options<Actors>;
0854 PropagatorOptions propOptions(tfOptions.geoContext,
0855 tfOptions.magFieldContext);
0856
0857
0858 propOptions.setPlainOptions(tfOptions.propagatorPlainOptions);
0859
0860
0861 auto& combKalmanActor =
0862 propOptions.actorList.template get<CombinatorialKalmanFilterActor>();
0863 combKalmanActor.targetReached.surface = tfOptions.targetSurface;
0864 combKalmanActor.multipleScattering = tfOptions.multipleScattering;
0865 combKalmanActor.energyLoss = tfOptions.energyLoss;
0866 combKalmanActor.skipPrePropagationUpdate =
0867 tfOptions.skipPrePropagationUpdate;
0868 combKalmanActor.actorLogger = m_actorLogger.get();
0869 combKalmanActor.updaterLogger = m_updaterLogger.get();
0870 combKalmanActor.calibrationContextPtr = &tfOptions.calibrationContext.get();
0871
0872
0873 combKalmanActor.m_extensions = tfOptions.extensions;
0874
0875 auto propState =
0876 m_propagator
0877 .template makeState<PropagatorOptions, StubPathLimitReached>(
0878 propOptions);
0879
0880 auto initResult = m_propagator.template initialize<
0881 decltype(propState), start_parameters_t, StubPathLimitReached>(
0882 propState, initialParameters);
0883 if (!initResult.ok()) {
0884 ACTS_ERROR("Propagation initialization failed: " << initResult.error());
0885 return initResult.error();
0886 }
0887
0888 auto& r =
0889 propState
0890 .template get<CombinatorialKalmanFilterResult<track_container_t>>();
0891 r.tracks = &trackContainer;
0892 r.trackStates = &trackContainer.trackStateContainer();
0893
0894 r.activeBranches.push_back(rootBranch);
0895
0896 auto propagationResult = m_propagator.propagate(propState);
0897
0898 auto result = m_propagator.makeResult(
0899 std::move(propState), propagationResult, propOptions, false);
0900
0901 if (!result.ok()) {
0902 ACTS_ERROR("Propagation failed: " << result.error() << " "
0903 << result.error().message()
0904 << " with the initial parameters: \n"
0905 << initialParameters.parameters());
0906 return result.error();
0907 }
0908
0909 auto& propRes = *result;
0910
0911
0912 auto combKalmanResult =
0913 std::move(propRes.template get<
0914 CombinatorialKalmanFilterResult<track_container_t>>());
0915
0916 Result<void> error = combKalmanResult.lastError;
0917 if (error.ok() && !combKalmanResult.finished) {
0918 error = Result<void>(
0919 CombinatorialKalmanFilterError::PropagationReachesMaxSteps);
0920 }
0921 if (!error.ok()) {
0922 ACTS_ERROR("CombinatorialKalmanFilter failed: "
0923 << combKalmanResult.lastError.error() << " "
0924 << combKalmanResult.lastError.error().message()
0925 << " with the initial parameters: "
0926 << initialParameters.parameters().transpose());
0927 return error.error();
0928 }
0929
0930 return std::move(combKalmanResult.collectedTracks);
0931 }
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948 template <typename start_parameters_t,
0949 typename parameters_t = BoundTrackParameters>
0950 auto findTracks(
0951 const start_parameters_t& initialParameters,
0952 const CombinatorialKalmanFilterOptions<track_container_t>& tfOptions,
0953 track_container_t& trackContainer) const
0954 -> Result<std::vector<
0955 typename std::decay_t<decltype(trackContainer)>::TrackProxy>> {
0956 auto rootBranch = trackContainer.makeTrack();
0957 return findTracks(initialParameters, tfOptions, trackContainer, rootBranch);
0958 }
0959 };
0960
0961 }