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