File indexing completed on 2025-01-18 09:27:52
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 CombinatorialKalmanFilterError::MeasurementSelectionFailed;
0027 }
0028
0029
0030 auto geoID = candidates.front().referenceSurface().geometryId();
0031
0032 auto cuts = m_config.find(geoID);
0033 if (cuts == m_config.end()) {
0034
0035
0036
0037 return CombinatorialKalmanFilterError::MeasurementSelectionFailed;
0038 }
0039
0040 assert(!cuts->chi2CutOff.empty());
0041 const std::vector<double>& chi2CutOff = cuts->chi2CutOff;
0042 const double maxChi2Cut =
0043 std::min(*std::max_element(chi2CutOff.begin(), chi2CutOff.end()),
0044 getCut<traj_t>(candidates.front(), cuts, chi2CutOff, logger));
0045 const std::size_t numMeasurementsCut = getCut<traj_t>(
0046 candidates.front(), cuts, cuts->numMeasurementsCutOff, logger);
0047
0048 if (numMeasurementsCut == 0ul) {
0049 return CombinatorialKalmanFilterError::MeasurementSelectionFailed;
0050 }
0051
0052 double minChi2 = std::numeric_limits<double>::max();
0053 std::size_t minIndex = std::numeric_limits<std::size_t>::max();
0054
0055 isOutlier = false;
0056
0057
0058
0059
0060
0061 std::size_t passedCandidates = 0ul;
0062 for (std::size_t i(0ul); i < candidates.size(); ++i) {
0063 auto& trackState = candidates[i];
0064
0065
0066
0067
0068 double chi2 = calculateChi2(
0069 trackState
0070 .template calibrated<MultiTrajectoryTraits::MeasurementSizeMax>()
0071 .data(),
0072 trackState
0073 .template calibratedCovariance<
0074 MultiTrajectoryTraits::MeasurementSizeMax>()
0075 .data(),
0076 trackState.predicted(), trackState.predictedCovariance(),
0077 trackState.projector(), trackState.calibratedSize());
0078 trackState.chi2() = chi2;
0079
0080 if (chi2 < minChi2) {
0081 minChi2 = chi2;
0082 minIndex = i;
0083 }
0084
0085
0086 if (chi2 >= maxChi2Cut) {
0087 continue;
0088 }
0089
0090 if (passedCandidates != i) {
0091 std::swap(candidates[passedCandidates], candidates[i]);
0092 if (minIndex == i) {
0093 minIndex = passedCandidates;
0094 }
0095 }
0096 ++passedCandidates;
0097 }
0098
0099
0100
0101 if (passedCandidates == 0ul) {
0102 ACTS_VERBOSE("No measurement candidate. Return an outlier measurement chi2="
0103 << minChi2);
0104 isOutlier = true;
0105 }
0106
0107 if (passedCandidates <= 1ul || numMeasurementsCut == 1ul) {
0108
0109 ACTS_VERBOSE("Returning only 1 element");
0110 return Result::success(std::make_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 if (passedCandidates <= numMeasurementsCut) {
0119 ACTS_VERBOSE("Number of selected measurements: "
0120 << passedCandidates << ", max: " << numMeasurementsCut);
0121 return Result::success(std::make_pair(
0122 candidates.begin(), candidates.begin() + passedCandidates));
0123 }
0124
0125 ACTS_VERBOSE("Number of selected measurements: "
0126 << numMeasurementsCut << ", max: " << numMeasurementsCut);
0127
0128 return Result::success(std::make_pair(
0129 candidates.begin(), candidates.begin() + numMeasurementsCut));
0130 }
0131
0132 template <typename traj_t, typename cut_value_t>
0133 cut_value_t MeasurementSelector::getCut(
0134 const typename traj_t::TrackStateProxy& trackState,
0135 const Acts::MeasurementSelector::Config::Iterator selector,
0136 const std::vector<cut_value_t>& cuts, const Logger& logger) {
0137 const auto& etaBins = selector->etaBins;
0138 if (etaBins.empty()) {
0139 return cuts[0];
0140 }
0141 const auto eta = std::atanh(std::cos(trackState.predicted()[eBoundTheta]));
0142 const auto abseta = std::abs(eta);
0143 std::size_t bin = 0;
0144 for (auto etaBin : etaBins) {
0145 if (etaBin >= abseta) {
0146 break;
0147 }
0148 bin++;
0149 }
0150 if (bin >= cuts.size()) {
0151 bin = cuts.size() - 1;
0152 }
0153 ACTS_VERBOSE("Get cut for eta=" << eta << ": " << cuts[bin]);
0154 return cuts[bin];
0155 }
0156
0157 }