File indexing completed on 2025-06-30 07:51:55
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/TrackFinding/MeasurementSelector.hpp"
0012
0013 namespace Acts {
0014
0015 template <typename traj_t>
0016 Result<
0017 std::pair<typename std::vector<typename traj_t::TrackStateProxy>::iterator,
0018 typename std::vector<typename traj_t::TrackStateProxy>::iterator>>
0019 MeasurementSelector::select(
0020 std::vector<typename traj_t::TrackStateProxy>& candidates, bool& isOutlier,
0021 const Logger& logger) const {
0022 using Result = Result<std::pair<
0023 typename std::vector<typename traj_t::TrackStateProxy>::iterator,
0024 typename std::vector<typename traj_t::TrackStateProxy>::iterator>>;
0025
0026 ACTS_VERBOSE("Invoked MeasurementSelector");
0027
0028
0029 if (candidates.empty()) {
0030 return Result::success(std::pair(candidates.begin(), candidates.end()));
0031 }
0032
0033
0034 GeometryIdentifier geoID = candidates.front().referenceSurface().geometryId();
0035
0036 const double theta = candidates.front().predicted()[eBoundTheta];
0037
0038 const auto cutsResult = getCuts(geoID, theta);
0039 if (!cutsResult.ok()) {
0040 return cutsResult.error();
0041 }
0042 const Cuts& cuts = *cutsResult;
0043
0044 if (cuts.numMeasurements == 0ul) {
0045 return CombinatorialKalmanFilterError::MeasurementSelectionFailed;
0046 }
0047
0048 double minChi2 = std::numeric_limits<double>::max();
0049 std::size_t minIndex = std::numeric_limits<std::size_t>::max();
0050
0051 isOutlier = false;
0052
0053
0054
0055
0056
0057 std::size_t passedCandidates = 0ul;
0058 for (std::size_t i(0ul); i < candidates.size(); ++i) {
0059 auto& trackState = candidates[i];
0060
0061
0062
0063
0064
0065
0066 double chi2 = calculateChi2(
0067 trackState.effectiveCalibrated().data(),
0068 trackState.effectiveCalibratedCovariance().data(),
0069 trackState.predicted(), trackState.predictedCovariance(),
0070 trackState.projectorSubspaceIndices(), trackState.calibratedSize());
0071 trackState.chi2() = chi2;
0072
0073 if (chi2 < minChi2) {
0074 minChi2 = chi2;
0075 minIndex = i;
0076 }
0077
0078
0079 if (chi2 >= cuts.chi2Measurement) {
0080 continue;
0081 }
0082
0083 if (passedCandidates != i) {
0084 std::swap(candidates[passedCandidates], candidates[i]);
0085 if (minIndex == i) {
0086 minIndex = passedCandidates;
0087 }
0088 }
0089 ++passedCandidates;
0090 }
0091
0092
0093 if (passedCandidates == 0ul) {
0094 if (minChi2 < cuts.chi2Outlier) {
0095 ACTS_VERBOSE(
0096 "No measurement candidate. Return an outlier measurement chi2="
0097 << minChi2);
0098 isOutlier = true;
0099 return Result::success(std::pair(candidates.begin() + minIndex,
0100 candidates.begin() + minIndex + 1));
0101 } else {
0102 ACTS_VERBOSE("No measurement candidate. Return empty chi2=" << minChi2);
0103 return Result::success(std::pair(candidates.begin(), candidates.begin()));
0104 }
0105 }
0106
0107 if (passedCandidates <= 1ul) {
0108
0109 ACTS_VERBOSE("Returning only 1 element chi2=" << minChi2);
0110 return Result::success(std::pair(candidates.begin() + minIndex,
0111 candidates.begin() + minIndex + 1));
0112 }
0113
0114 std::sort(
0115 candidates.begin(), candidates.begin() + passedCandidates,
0116 [](const auto& tsa, const auto& tsb) { return tsa.chi2() < tsb.chi2(); });
0117
0118 ACTS_VERBOSE("Number of selected measurements: "
0119 << passedCandidates << ", max: " << cuts.numMeasurements);
0120
0121 return Result::success(std::pair(
0122 candidates.begin(),
0123 candidates.begin() + std::min(cuts.numMeasurements, passedCandidates)));
0124 }
0125
0126 }