ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CKFSourceLinkSelector.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CKFSourceLinkSelector.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 #include <limits>
11 
19 
20 namespace Acts {
21 
32  public:
39  struct Config {
40  // Criteria type down to detector volume
41  using VolumeChi2 = std::map<GeometryID::Value, double>;
42  using VolumeNumMeasurements = std::map<GeometryID::Value, size_t>;
43  // Criteria type down to detector layer
44  using LayerChi2 = std::map<GeometryID::Value, VolumeChi2>;
45  using LayerNumMeasurements =
46  std::map<GeometryID::Value, VolumeNumMeasurements>;
47 
48  // Global maximum chi2
50 
51  // Volume-level maximum chi2
53 
54  // Layer-level maximum chi2
56 
57  // Global maximum number of source links on surface (value 1 means selecting
58  // only the most compatible source link)
60 
61  // Volume-level maximum number of source links on surface
63 
64  // Layer-level maximum number of source links on surface
66  };
67 
69  CKFSourceLinkSelector() = default;
70 
76  Config cfg,
77  std::shared_ptr<const Logger> logger = std::shared_ptr<const Logger>(
78  getDefaultLogger("CKFSourceLinkSelector", Logging::INFO).release()))
79  : m_config(std::move(cfg)), m_logger(std::move(logger)) {}
80 
96  template <typename calibrator_t, typename source_link_t>
98  const calibrator_t& calibrator, const BoundParameters& predictedParams,
99  const std::vector<source_link_t>& sourcelinks,
100  std::vector<std::pair<size_t, double>>& sourcelinkChi2,
101  std::vector<size_t>& sourcelinkCandidateIndices, bool& isOutlier) const {
102  ACTS_VERBOSE("Invoked CKFSourceLinkSelector");
103 
104  using CovMatrix_t = typename BoundParameters::CovMatrix_t;
105 
106  // Return error if no source link
107  if (sourcelinks.empty()) {
108  return CombinatorialKalmanFilterError::SourcelinkSelectionFailed;
109  }
110 
111  auto surface = &predictedParams.referenceSurface();
112  // Get volume and layer ID
113  auto geoID = surface->geoID();
114  auto volumeID = geoID.volume();
115  auto layerID = geoID.layer();
116 
117  // First check if the layer-level criteria is configured.
118  // If not, check if the volume-level criteria is configured.
119  // Otherwise, use world criteria
120  double chi2Cutoff = std::numeric_limits<double>::max();
121  size_t numSourcelinksCutoff = std::numeric_limits<size_t>::max();
122  // Get the allowed maximum chi2 on this surface
123  while (true) {
124  // layer-level criteria
125  auto layerMaxChi2_volume_it = m_config.layerMaxChi2.find(volumeID);
126  if (layerMaxChi2_volume_it != m_config.layerMaxChi2.end()) {
127  auto layerMaxChi2_layer_it =
128  layerMaxChi2_volume_it->second.find(layerID);
129  if (layerMaxChi2_layer_it != layerMaxChi2_volume_it->second.end()) {
130  chi2Cutoff = layerMaxChi2_layer_it->second;
131  break;
132  }
133  }
134  // volume-level criteria
135  auto volumeMaxChi2_volume_it = m_config.volumeMaxChi2.find(volumeID);
136  if (volumeMaxChi2_volume_it != m_config.volumeMaxChi2.end()) {
137  chi2Cutoff = volumeMaxChi2_volume_it->second;
138  break;
139  }
140  // world-level criteria
141  chi2Cutoff = m_config.maxChi2;
142  break;
143  }
144  ACTS_VERBOSE("Allowed maximum chi2: " << chi2Cutoff);
145 
146  // Get the allowed maximum number of source link candidates on this surface
147  while (true) {
148  // layer-level criteria
149  auto layerMaxNumSourcelinks_volume_it =
151  if (layerMaxNumSourcelinks_volume_it !=
153  auto layerMaxNumSourcelinks_layer_it =
154  layerMaxNumSourcelinks_volume_it->second.find(layerID);
155  if (layerMaxNumSourcelinks_layer_it !=
156  layerMaxNumSourcelinks_volume_it->second.end()) {
157  numSourcelinksCutoff = layerMaxNumSourcelinks_layer_it->second;
158  break;
159  }
160  }
161  // volume-level criteria
162  auto volumeMaxNumSourcelinks_volume_it =
164  if (volumeMaxNumSourcelinks_volume_it !=
166  numSourcelinksCutoff = volumeMaxNumSourcelinks_volume_it->second;
167  break;
168  }
169  // world-level criteria
170  numSourcelinksCutoff = m_config.maxNumSourcelinksOnSurface;
171  break;
172  }
173  ACTS_VERBOSE(
174  "Allowed maximum number of source links: " << numSourcelinksCutoff);
175 
176  sourcelinkChi2.resize(sourcelinks.size());
177  double minChi2 = std::numeric_limits<double>::max();
178  size_t minIndex = 0;
179  size_t index = 0;
180  size_t nInitialCandidates = 0;
181  // Loop over all source links to select the compatible source links
182  for (const auto& sourcelink : sourcelinks) {
183  std::visit(
184  [&](const auto& calibrated) {
185  // The measurement surface should be the same as parameter surface
186  assert(&calibrated.referenceSurface() == surface);
187 
188  // type of measurement
189  using meas_t =
190  typename std::remove_const<typename std::remove_reference<
191  decltype(calibrated)>::type>::type;
192  // measurement (local) parameter vector
193  using meas_par_t = typename meas_t::ParVector_t;
194  // type of projection
195  using projection_t = typename meas_t::Projection_t;
196 
197  // Take the projector (measurement mapping function)
198  const projection_t& H = calibrated.projector();
199  // Take the parameter covariance
200  const CovMatrix_t& predicted_covariance =
201  *predictedParams.covariance();
202  // Get the residual
203  meas_par_t residual = calibrated.residual(predictedParams);
204  // Get the chi2
205  double chi2 = (residual.transpose() *
206  ((calibrated.covariance() +
207  H * predicted_covariance * H.transpose()))
208  .inverse() *
209  residual)
210  .eval()(0, 0);
211 
212  ACTS_VERBOSE("Chi2: " << chi2);
213  // Push the source link index and chi2 if satisfying the criteria
214  if (chi2 < chi2Cutoff) {
215  sourcelinkChi2.at(nInitialCandidates) = {index, chi2};
216  nInitialCandidates++;
217  }
218  // Search for the source link with the min chi2
219  if (chi2 < minChi2) {
220  minChi2 = chi2;
221  minIndex = index;
222  }
223  },
224  calibrator(sourcelink, predictedParams));
225  index++;
226  }
227 
228  // Get the number of source link candidates with provided constraint
229  // considered
230  size_t nFinalCandidates =
231  std::min(nInitialCandidates, numSourcelinksCutoff);
232 
233  // Size of sourcelinkCandidates
234  size_t containerSize = sourcelinkCandidateIndices.size();
235 
236  // If there is no selected source link, return the source link with the best
237  // chi2 and tag it as an outlier
238  if (nFinalCandidates == 0) {
239  sourcelinkCandidateIndices.resize(1);
240  sourcelinkCandidateIndices.at(0) = minIndex;
241  ACTS_DEBUG("No measurement candidate. Return an outlier source link.");
242  isOutlier = true;
243  return Result<void>::success();
244  }
245 
246  ACTS_VERBOSE("Number of measurement candidates: " << nFinalCandidates);
247  sourcelinkCandidateIndices.resize(nFinalCandidates);
248  // Sort the initial source link candidates based on chi2 in ascending order
249  std::sort(sourcelinkChi2.begin(),
250  sourcelinkChi2.begin() + nInitialCandidates,
251  [](const std::pair<size_t, double>& lchi2,
252  const std::pair<size_t, double>& rchi2) {
253  return lchi2.second < rchi2.second;
254  });
255  // Get only allowed number of source link candidates, i.e. nFinalCandidates,
256  // from the front and reset the values in the container
257  size_t nRecorded = 0;
258  for (const auto& [id, chi2] : sourcelinkChi2) {
259  if (nRecorded >= nFinalCandidates) {
260  break;
261  }
262  sourcelinkCandidateIndices.at(nRecorded) = id;
263  nRecorded++;
264  }
265  isOutlier = false;
266  return Result<void>::success();
267  }
268 
271 
273  std::shared_ptr<const Logger> m_logger{nullptr};
274 
276  const Logger& logger() const {
277  assert(m_logger);
278  return *m_logger;
279  }
280 };
281 
282 } // namespace Acts