44 using LayerChi2 = std::map<GeometryID::Value, VolumeChi2>;
46 std::map<GeometryID::Value, VolumeNumMeasurements>;
77 std::shared_ptr<const Logger>
logger = std::shared_ptr<const Logger>(
96 template <
typename calibrator_t,
typename source_link_t>
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 {
107 if (sourcelinks.empty()) {
108 return CombinatorialKalmanFilterError::SourcelinkSelectionFailed;
114 auto volumeID = geoID.volume();
115 auto layerID = geoID.layer();
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;
137 chi2Cutoff = volumeMaxChi2_volume_it->second;
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;
162 auto volumeMaxNumSourcelinks_volume_it =
164 if (volumeMaxNumSourcelinks_volume_it !=
166 numSourcelinksCutoff = volumeMaxNumSourcelinks_volume_it->second;
174 "Allowed maximum number of source links: " << numSourcelinksCutoff);
176 sourcelinkChi2.resize(sourcelinks.size());
180 size_t nInitialCandidates = 0;
182 for (
const auto& sourcelink : sourcelinks) {
184 [&](
const auto& calibrated) {
186 assert(&calibrated.referenceSurface() ==
surface);
190 typename std::remove_const<
typename std::remove_reference<
191 decltype(calibrated)>::type>::type;
193 using meas_par_t =
typename meas_t::ParVector_t;
195 using projection_t =
typename meas_t::Projection_t;
198 const projection_t&
H = calibrated.projector();
200 const CovMatrix_t& predicted_covariance =
203 meas_par_t residual = calibrated.residual(predictedParams);
205 double chi2 = (residual.transpose() *
206 ((calibrated.covariance() +
207 H * predicted_covariance * H.transpose()))
214 if (chi2 < chi2Cutoff) {
215 sourcelinkChi2.at(nInitialCandidates) = {index, chi2};
216 nInitialCandidates++;
219 if (chi2 < minChi2) {
224 calibrator(sourcelink, predictedParams));
230 size_t nFinalCandidates =
231 std::min(nInitialCandidates, numSourcelinksCutoff);
234 size_t containerSize = sourcelinkCandidateIndices.size();
238 if (nFinalCandidates == 0) {
239 sourcelinkCandidateIndices.resize(1);
240 sourcelinkCandidateIndices.at(0) = minIndex;
241 ACTS_DEBUG(
"No measurement candidate. Return an outlier source link.");
246 ACTS_VERBOSE(
"Number of measurement candidates: " << nFinalCandidates);
247 sourcelinkCandidateIndices.resize(nFinalCandidates);
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;
257 size_t nRecorded = 0;
258 for (
const auto& [
id, chi2] : sourcelinkChi2) {
259 if (nRecorded >= nFinalCandidates) {
262 sourcelinkCandidateIndices.at(nRecorded) = id;