2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
7 * Actual Implementation method for StepForwardFit.
8 * Templated on MeasurementBase or PrepRawData.
10 * Using std Kalman notation and omitting Covariances
11 * 1. We extrapolate our current best prediction x_{k-1|k−1}
13 * 2. We obtain a "predictedState" x_{k|k−1} = Fx_{k-1|k−1} + w_k
14 * 3. We perform the update with the measurement.
15 * x_{k|k} = x_{k|k−1} + K_k m_k− H_k x_{k|k−1}
16 * 4. Return true if the step was succesful.
18 * - We add a TSOS containing the "predictedState" x_{k|k−1} to the
20 * - The "updatedState" x_{k|k} is ready for the next step.
24 Trk::GaussianSumFitter::stepForwardFit(
25 const EventContext& ctx,
26 Trk::IMultiStateExtrapolator::Cache& extrapolatorCache,
27 GSFTrajectory& forwardTrajectory,
28 const T* inMeasurement,
29 const Trk::Surface& surface,
30 Trk::MultiComponentState& updatedState) const {
32 static_assert(std::is_same_v<T, Trk::MeasurementBase> ||
33 std::is_same_v<T, Trk::PrepRawData>,
34 "input should be Trk::MeasurementBase or Trk::PrepRawData");
35 // Protect against undefined Measurement or PrepRawData
37 ATH_MSG_WARNING("No measurement passed to StepForwardFit!");
40 // Propagate the multi-component state to the next measurement surface
41 // accounting for the material effects. This gives us the prediction at that surface.
42 Trk::MultiComponentState predictedState =
43 m_extrapolator->extrapolate(ctx,
49 if (predictedState.empty()) {
53 std::unique_ptr<Trk::MeasurementBase> measurement = nullptr;
54 //We need different treatment for the different inputs
55 if constexpr (std::is_same_v<T, Trk::MeasurementBase>){
56 // clone original MeasurementBase object
57 measurement.reset(inMeasurement->clone());
59 // Create a new MeasurementBase object from PrepRawData
60 std::unique_ptr<Trk::TrackParameters> combinedState =
61 MultiComponentStateCombiner::combineToSingle(predictedState);
63 ATH_MSG_WARNING("State combination failed... exiting");
67 m_rioOnTrackCreator->correct(*inMeasurement, *combinedState, ctx));
69 ATH_MSG_WARNING("stepForwardFit no measurement to update with");
73 // Perform measurement update
74 auto fitQuality = Trk::FitQualityOnSurface{};
75 // We need to keep the extrapolatedState so clone
76 updatedState = Trk::GsfMeasurementUpdator::update(
77 MultiComponentStateHelpers::clone(predictedState),
81 if (updatedState.empty()) {
84 // Hits with excessive chi2 are outliers.
85 // We ingore the update, reset back to the extrapolated
86 // state before the update
87 if (fitQuality.chiSquared() >
88 m_cutChiSquaredPerNumberDOF * fitQuality.numberDoF()) {
89 fitQuality = FitQualityOnSurface(1, 1);
90 std::bitset<TrackStateOnSurface::NumberOfTrackStateOnSurfaceTypes> type(0);
91 type.set(TrackStateOnSurface::Outlier);
92 forwardTrajectory.emplace_back(
93 fitQuality, std::move(measurement), nullptr,
94 Trk::MultiComponentStateHelpers::clone(predictedState), type);
95 // reset the updated state to the predicted state
96 // before the measurement update
97 updatedState = std::move(predictedState);
100 forwardTrajectory.emplace_back(fitQuality, std::move(measurement), nullptr,
101 std::move(predictedState));
105 /* @ Forward fit on a set of MeasurementBase or PrepRawData */
106 template <typename T>
107 Trk::GaussianSumFitter::GSFTrajectory
108 Trk::GaussianSumFitter::forwardFit(
109 const EventContext& ctx,
110 Trk::IMultiStateExtrapolator::Cache& extrapolatorCache,
112 const Trk::TrackParameters& estimatedTrackParametersNearOrigin) const {
114 static_assert(std::is_same_v<T, Trk::MeasurementSet> ||
115 std::is_same_v<T, Trk::PrepRawDataSet>,
116 "input should be Trk::MeasurementSet or Trk::PrepRawDataSe");
117 if (inputSet.empty()) {
118 ATH_MSG_ERROR("forwardFit: Input Set is empty!");
119 return GSFTrajectory{};
122 // For starting guess a multicompoment state
123 // that has single component with weight 1
124 const AmgVector(5)& par = estimatedTrackParametersNearOrigin.parameters();
125 Trk::ComponentParameters componentParametersNearOrigin = {
126 estimatedTrackParametersNearOrigin.associatedSurface()
127 .createUniqueTrackParameters(par[Trk::loc1],
132 std::nullopt /*no errors*/),
134 Trk::MultiComponentState multiComponentStateNearOrigin{};
135 multiComponentStateNearOrigin.push_back(std::move(componentParametersNearOrigin));
136 GSFTrajectory forwardTrajectory{};
137 forwardTrajectory.reserve(inputSet.size());
139 if constexpr (std::is_same_v<T, Trk::MeasurementSet>){
140 for (const auto* measurement : inputSet) {
141 // Every step the ForwardTrajectory is updated
142 const bool stepIsValid =
143 stepForwardFit(ctx, extrapolatorCache, forwardTrajectory,
144 measurement, measurement->associatedSurface(),
145 multiComponentStateNearOrigin);
147 return GSFTrajectory{};
152 // Extract PrepRawDataSet into new local object and check that the
153 // PrepRawData is associated with a detector element
155 for (const auto* rawData : inputSet) {
156 if (!(rawData->detectorElement())) {
157 ATH_MSG_WARNING("PrepRawData has no Element link... disregard it");
159 prepRawDataSet.push_back(rawData);
162 for (const auto* prepRawData : prepRawDataSet) {
163 // Every step the ForwardTrajectory is updated
164 const bool stepIsValid = stepForwardFit(
165 ctx, extrapolatorCache, forwardTrajectory, prepRawData,
166 prepRawData->detectorElement()->surface(prepRawData->identify()),
167 multiComponentStateNearOrigin);
170 return GSFTrajectory{};
173 }//end of if constexpr
174 return forwardTrajectory;