34 template <
typename traj_t>
68 template <
typename bethe_heitler_approx_t,
typename traj_t>
130 std::vector<MultiTrajectoryTraits::IndexType>
tips;
131 std::map<MultiTrajectoryTraits::IndexType, double>
weights;
143 template <
typename propagator_state_t,
typename stepper_t,
144 typename navigator_t>
151 if (not result.
result.ok()) {
157 auto setErrorOrAbort = [&](
auto error) {
171 if (not navigator.currentSurface(state.navigation)) {
175 const auto&
surface = *navigator.currentSurface(state.navigation);
180 [[maybe_unused]]
auto stepperComponents =
181 stepper.constComponentIterable(state.stepping);
183 stepperComponents, [](
const auto&
cmp) {
return cmp.weight(); }));
190 stepperComponents.begin(), stepperComponents.end(),
191 [](
const auto&
cmp) {
return cmp.status() == Status::onSurface; }));
207 const auto found_source_link =
209 const bool haveMaterial =
210 navigator.currentSurface(state.navigation)->surfaceMaterial() &&
212 const bool haveMeasurement =
215 ACTS_VERBOSE(std::boolalpha <<
"haveMaterial " << haveMaterial
216 <<
", haveMeasurement: " << haveMeasurement);
223 if (not haveMaterial && not haveMeasurement) {
232 for (
auto cmp : stepper.componentIterable(state.stepping)) {
233 auto singleState =
cmp.singleState(state);
234 cmp.singleStepper(stepper).transportCovarianceToBound(
235 singleState.stepping,
surface);
239 if (haveMeasurement) {
241 MaterialUpdateStage::PreUpdate);
244 MaterialUpdateStage::FullUpdate);
251 if (not haveMaterial) {
254 auto res =
kalmanUpdate(state, stepper, navigator, result, tmpStates,
255 found_source_link->second);
258 setErrorOrAbort(res.error());
271 if (haveMeasurement) {
272 res =
kalmanUpdate(state, stepper, navigator, result, tmpStates,
273 found_source_link->second);
280 setErrorOrAbort(res.error());
285 std::vector<ComponentCache>& componentCache = result.
componentCache;
286 componentCache.clear();
291 if (componentCache.empty()) {
293 "No components left after applying energy loss. "
294 "Is the weight cutoff "
296 ACTS_WARNING(
"Return to propagator without applying energy loss");
301 const auto finalCmpNumber =
std::min(
311 if (haveMaterial && haveMeasurement) {
313 MaterialUpdateStage::PostUpdate);
319 navigator.targetReached(state.navigation,
true);
323 template <
typename propagator_state_t,
typename stepper_t,
324 typename navigator_t>
328 std::vector<ComponentCache>& componentCache,
329 std::size_t& nInvalidBetheHeitler)
const {
330 auto cmps = stepper.componentIterable(state.stepping);
332 auto proxy = tmpStates.
traj.getTrackState(
idx);
335 proxy.filtered(), proxy.filteredCovariance(),
336 stepper.particleHypothesis(state.stepping));
339 componentCache, nInvalidBetheHeitler);
343 template <
typename propagator_state_t,
typename navigator_t>
347 const double old_weight,
348 std::vector<ComponentCache>& componentCaches,
349 std::size_t& nInvalidBetheHeitler)
const {
350 const auto&
surface = *navigator.currentSurface(state.navigation);
354 auto slab =
surface.surfaceMaterial()->materialSlab(
355 old_bound.
position(state.stepping.geoContext), state.options.direction,
356 MaterialUpdateStage::FullUpdate);
358 auto pathCorrection =
surface.pathCorrection(
359 state.stepping.geoContext,
361 slab.scaleThickness(pathCorrection);
365 ++nInvalidBetheHeitler;
367 "Bethe-Heitler approximation encountered invalid value for x/x0="
368 << slab.thicknessInX0() <<
" at surface " <<
surface.geometryId());
376 for (
const auto& gaussian : mixture) {
379 const auto new_weight = gaussian.weight * old_weight;
382 ACTS_VERBOSE(
"Skip component with weight " << new_weight);
386 if (gaussian.mean < 1.e-8) {
387 ACTS_WARNING(
"Skip component with gaussian " << gaussian.mean <<
" +- "
395 const auto delta_p = [&]() {
397 return p_prev * (gaussian.mean - 1.);
399 return p_prev * (1. / gaussian.mean - 1.);
403 assert(p_prev + delta_p > 0. &&
"new momentum must be > 0");
407 auto new_cov = old_bound.
covariance().value();
409 const auto varInvP = [&]() {
411 const auto f = 1. / (p_prev * gaussian.mean);
412 return f *
f * gaussian.var;
414 return gaussian.var / (p_prev * p_prev);
420 "new cov not finite");
423 componentCaches.push_back({new_weight, new_pars, new_cov});
432 auto proj = [](
auto&
cmp) ->
double& {
return cmp.weight; };
436 auto new_end = std::remove_if(cmps.begin(), cmps.end(), [&](
auto&
cmp) {
442 cmps = {*std::max_element(
443 cmps.begin(), cmps.end(),
445 cmps.front().weight = 1.0;
447 cmps.erase(new_end, cmps.end());
453 template <
typename propagator_state_t,
typename stepper_t>
456 auto cmps = stepper.componentIterable(state.stepping);
462 cmp.status() = Intersection3D::Status::missed;
466 auto proxy = tmpStates.
traj.getTrackState(
idx);
470 cmp.cov() = proxy.filteredCovariance();
474 stepper.removeMissedComponents(state.stepping);
479 [&](
auto cmp) ->
double& {
return cmp.weight(); });
483 template <
typename propagator_state_t,
typename stepper_t,
484 typename navigator_t>
487 const std::vector<ComponentCache>& componentCache)
const {
488 const auto&
surface = *navigator.currentSurface(state.navigation);
491 stepper.clearComponents(state.stepping);
494 for (
const auto& [weight,
pars,
cov] : componentCache) {
497 stepper.particleHypothesis(state.stepping));
499 auto res = stepper.addComponent(state.stepping,
std::move(bound), weight);
502 ACTS_ERROR(
"Error adding component to MultiStepper");
507 cmp.jacToGlobal() =
surface.boundToFreeJacobian(state.geoContext,
pars);
508 cmp.pathAccumulated() = state.stepping.pathAccumulated;
509 cmp.jacobian() = Acts::BoundMatrix::Identity();
510 cmp.derivative() = Acts::FreeVector::Zero();
511 cmp.jacTransport() = Acts::FreeMatrix::Identity();
517 template <
typename propagator_state_t,
typename stepper_t,
518 typename navigator_t>
523 const auto&
surface = *navigator.currentSurface(state.navigation);
529 bool is_valid_measurement =
false;
531 auto cmps = stepper.componentIterable(state.stepping);
532 for (
auto cmp : cmps) {
533 auto singleState =
cmp.singleState(state);
534 const auto& singleStepper =
cmp.singleStepper(stepper);
541 if (!trackStateProxyRes.ok()) {
542 return trackStateProxyRes.error();
545 const auto& trackStateProxy = *trackStateProxyRes;
549 if (trackStateProxy.typeFlags().test(
551 is_valid_measurement =
true;
554 tmpStates.
tips.push_back(trackStateProxy.index());
565 ++result.processedStates;
568 if (is_valid_measurement) {
569 ++result.measurementStates;
573 result.lastMeasurementTip = result.currentTip;
575 using FiltProjector =
577 FiltProjector
proj{tmpStates.traj, tmpStates.weights};
579 std::vector<std::tuple<double, BoundVector, BoundMatrix>>
v;
582 for (
const auto&
idx : tmpStates.tips) {
585 v.push_back({w,
p,
c});
591 result.lastMeasurementState = MultiComponentBoundTrackParameters(
599 template <
typename propagator_state_t,
typename stepper_t,
600 typename navigator_t>
606 bool doCovTransport)
const {
607 const auto&
surface = *navigator.currentSurface(state.navigation);
613 auto cmps = stepper.componentIterable(state.stepping);
614 for (
auto cmp : cmps) {
615 auto singleState =
cmp.singleState(state);
616 const auto& singleStepper =
cmp.singleStepper(stepper);
621 singleState, singleStepper,
surface, tmpStates.
traj,
624 if (!trackStateProxyRes.ok()) {
625 return trackStateProxyRes.error();
628 const auto& trackStateProxy = *trackStateProxyRes;
634 tmpStates.
tips.push_back(trackStateProxy.index());
651 template <
typename propagator_state_t,
typename stepper_t,
652 typename navigator_t>
657 MaterialUpdateStage::FullUpdate)
const {
658 const auto&
surface = *navigator.currentSurface(state.navigation);
660 for (
auto cmp : stepper.componentIterable(state.stepping)) {
661 auto singleState =
cmp.singleState(state);
662 const auto& singleStepper =
cmp.singleStepper(stepper);
675 <<
" at update stage: " << updateStage <<
" are :");
677 << interaction.
Eloss <<
", "
678 <<
"variancePhi = " << interaction.
variancePhi <<
", "
685 assert(singleState.stepping.cov.array().isFinite().all() &&
686 "covariance not finite after multi scattering");
699 const auto firstCmpProxy =
700 tmpStates.
traj.getTrackState(tmpStates.
tips.front());
701 const auto isMeasurement =
706 ? TrackStatePropMask::Calibrated | TrackStatePropMask::Predicted |
707 TrackStatePropMask::Filtered | TrackStatePropMask::Smoothed
708 : TrackStatePropMask::Calibrated | TrackStatePropMask::Predicted;
715 proxy.copyFrom(firstCmpProxy,
mask);
720 proxy.predicted() = prtMean;
721 proxy.predictedCovariance() = prtCov;
727 proxy.filtered() = fltMean;
728 proxy.filteredCovariance() = fltCov;
729 proxy.smoothed() = BoundVector::Constant(-2);
730 proxy.smoothedCovariance() = BoundSquareMatrix::Constant(-2);
732 proxy.shareFrom(TrackStatePropMask::Predicted,
733 TrackStatePropMask::Filtered);
740 result.fittedStates->applyBackwards(
741 result.currentTip, [&](
auto trackState) {
742 auto fSurface = &trackState.referenceSurface();
744 result.surfacesVisitedBwdAgain.push_back(&
surface);
746 if (trackState.hasSmoothed()) {
749 FltProjector{tmpStates.traj, tmpStates.weights});
751 trackState.smoothed() = smtMean;
752 trackState.smoothedCovariance() = smtCov;