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 
18 
19 #include <limits>
20 #include <map>
21 
22 namespace Acts {
23 
33 };
34 
46  public:
53 
55  CKFSourceLinkSelector() = default;
60  CKFSourceLinkSelector(Config cfg) : m_config(std::move(cfg)) {}
61 
77  template <typename calibrator_t, typename source_link_t>
79  const calibrator_t& calibrator,
80  const BoundTrackParameters& predictedParams,
81  const std::vector<source_link_t>& sourcelinks,
82  std::vector<std::pair<size_t, double>>& sourcelinkChi2,
83  std::vector<size_t>& sourcelinkCandidateIndices, bool& isOutlier,
84  LoggerWrapper logger) const {
85  ACTS_VERBOSE("Invoked CKFSourceLinkSelector");
86 
87  // Return error if no source link
88  if (sourcelinks.empty()) {
89  return CombinatorialKalmanFilterError::SourcelinkSelectionFailed;
90  }
91 
92  // Get geoID of this surface
93  auto surface = &predictedParams.referenceSurface();
94  auto geoID = surface->geometryId();
95 
96  // Find the appropriate cuts
97  auto cuts = m_config.find(geoID);
98  if (cuts == m_config.end()) {
99  // for now we consider missing cuts an unrecoverable error
100  // TODO consider other options e.g. do not add source links at all (not
101  // even as outliers)
102  return CombinatorialKalmanFilterError::SourcelinkSelectionFailed;
103  }
104  const auto chi2CutOff = cuts->chi2CutOff;
105  const auto numSourcelinksCutOff = cuts->numSourcelinksCutOff;
106  ACTS_VERBOSE("Allowed maximum chi2: " << chi2CutOff);
107  ACTS_VERBOSE(
108  "Allowed maximum number of source links: " << numSourcelinksCutOff);
109 
110  sourcelinkChi2.resize(sourcelinks.size());
111  double minChi2 = std::numeric_limits<double>::max();
112  size_t minIndex = 0;
113  size_t index = 0;
114  size_t nInitialCandidates = 0;
115  // Loop over all source links to select the compatible source links
116  for (const auto& sourcelink : sourcelinks) {
117  std::visit(
118  [&](const auto& calibrated) {
119  // The measurement surface should be the same as parameter surface
120  assert(&calibrated.referenceObject() == surface);
121 
122  // Take the projector (measurement mapping function)
123  const auto& H = calibrated.projector();
124  // Take the parameter covariance
125  const auto& predictedCovariance = *predictedParams.covariance();
126  // Get the residual
127  const auto& residual =
128  calibrated.residual(predictedParams.parameters());
129  // Get the chi2
130  double chi2 = (residual.transpose() *
131  ((calibrated.covariance() +
132  H * predictedCovariance * H.transpose()))
133  .inverse() *
134  residual)
135  .eval()(0, 0);
136 
137  ACTS_VERBOSE("Chi2: " << chi2);
138  // Push the source link index and chi2 if satisfying the criteria
139  if (chi2 < chi2CutOff) {
140  sourcelinkChi2.at(nInitialCandidates) = {index, chi2};
141  nInitialCandidates++;
142  }
143  // Search for the source link with the min chi2
144  if (chi2 < minChi2) {
145  minChi2 = chi2;
146  minIndex = index;
147  }
148  },
149  calibrator(sourcelink, predictedParams));
150  index++;
151  }
152 
153  // Get the number of source link candidates with provided constraint
154  // considered
155  size_t nFinalCandidates =
156  std::min(nInitialCandidates, numSourcelinksCutOff);
157 
158  // If there is no selected source link, return the source link with the best
159  // chi2 and tag it as an outlier
160  if (nFinalCandidates == 0) {
161  sourcelinkCandidateIndices.resize(1);
162  sourcelinkCandidateIndices.at(0) = minIndex;
163  ACTS_DEBUG("No measurement candidate. Return an outlier source link.");
164  isOutlier = true;
165  return Result<void>::success();
166  }
167 
168  ACTS_VERBOSE("Number of measurement candidates: " << nFinalCandidates);
169  sourcelinkCandidateIndices.resize(nFinalCandidates);
170  // Sort the initial source link candidates based on chi2 in ascending order
171  std::sort(sourcelinkChi2.begin(),
172  sourcelinkChi2.begin() + nInitialCandidates,
173  [](const std::pair<size_t, double>& lchi2,
174  const std::pair<size_t, double>& rchi2) {
175  return lchi2.second < rchi2.second;
176  });
177  // Get only allowed number of source link candidates, i.e. nFinalCandidates,
178  // from the front and reset the values in the container
179  size_t nRecorded = 0;
180  for (const auto& [id, chi2] : sourcelinkChi2) {
181  if (nRecorded >= nFinalCandidates) {
182  break;
183  }
184  sourcelinkCandidateIndices.at(nRecorded) = id;
185  nRecorded++;
186  }
187  isOutlier = false;
188  return Result<void>::success();
189  }
190 
193 };
194 
195 } // namespace Acts