ATLAS Offline Software
GaussianSumFitter.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <type_traits>
6 /*
7  * Actual Implementation method for StepForwardFit.
8  * Templated on MeasurementBase or PrepRawData.
9  *
10  * Using std Kalman notation and omitting Covariances
11  * 1. We extrapolate our current best prediction x_{k-1|k−1}
12  * to a surface
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.
17  * In which case
18  * - We add a TSOS containing the "predictedState" x_{k|k−1} to the
19  * forwardTrajectory
20  * - The "updatedState" x_{k|k} is ready for the next step.
21  */
22 template <typename T>
23 bool
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 {
31 
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
36  if (!inMeasurement) {
37  ATH_MSG_WARNING("No measurement passed to StepForwardFit!");
38  return false;
39  }
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,
44  extrapolatorCache,
45  updatedState,
46  surface,
47  Trk::alongMomentum,
48  false);
49  if (predictedState.empty()) {
50  return false;
51  }
52 
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());
58  } else {
59  // Create a new MeasurementBase object from PrepRawData
60  std::unique_ptr<Trk::TrackParameters> combinedState =
61  MultiComponentStateCombiner::combineToSingle(predictedState);
62  if (!combinedState) {
63  ATH_MSG_WARNING("State combination failed... exiting");
64  return false;
65  }
66  measurement.reset(
67  m_rioOnTrackCreator->correct(*inMeasurement, *combinedState, ctx));
68  if (!measurement) {
69  ATH_MSG_WARNING("stepForwardFit no measurement to update with");
70  return false;
71  }
72  }
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),
78  *measurement,
79  fitQuality);
80 
81  if (updatedState.empty()) {
82  return false;
83  }
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);
98  return true;
99  }
100  forwardTrajectory.emplace_back(fitQuality, std::move(measurement), nullptr,
101  std::move(predictedState));
102  return true;
103 }
104 
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,
111  const T& inputSet,
112  const Trk::TrackParameters& estimatedTrackParametersNearOrigin) const {
113 
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{};
120  }
121 
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],
128  par[Trk::loc2],
129  par[Trk::phi],
130  par[Trk::theta],
131  par[Trk::qOverP],
132  std::nullopt /*no errors*/),
133  1.};
134  Trk::MultiComponentState multiComponentStateNearOrigin{};
135  multiComponentStateNearOrigin.push_back(std::move(componentParametersNearOrigin));
136  GSFTrajectory forwardTrajectory{};
137  forwardTrajectory.reserve(inputSet.size());
138 
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);
146  if (!stepIsValid) {
147  return GSFTrajectory{};
148  }
149  }
150  }
151  else{
152  // Extract PrepRawDataSet into new local object and check that the
153  // PrepRawData is associated with a detector element
154  T prepRawDataSet;
155  for (const auto* rawData : inputSet) {
156  if (!(rawData->detectorElement())) {
157  ATH_MSG_WARNING("PrepRawData has no Element link... disregard it");
158  } else {
159  prepRawDataSet.push_back(rawData);
160  }
161  }
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);
168 
169  if (!stepIsValid) {
170  return GSFTrajectory{};
171  }
172  }
173  }//end of if constexpr
174  return forwardTrajectory;
175 }
176