Warning, file /include/Acts/Seeding/HoughTransformUtils.ipp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <algorithm>
0010
0011 template <class identifier_t>
0012 template <class PointType>
0013 void Acts::HoughTransformUtils::HoughPlane<identifier_t>::fill(
0014 const PointType& measurement, const HoughAxisRanges& axisRanges,
0015 LineParametrisation<PointType> linePar,
0016 LineParametrisation<PointType> widthPar, const identifier_t& identifier,
0017 unsigned layer, YieldType weight) {
0018
0019 for (std::size_t xBin = 0; xBin < m_cfg.nBinsX; xBin++) {
0020
0021 auto x = binCenter(axisRanges.xMin, axisRanges.xMax, m_cfg.nBinsX, xBin);
0022
0023 CoordType y = linePar(x, measurement);
0024 CoordType dy = widthPar(x, measurement);
0025
0026 int yBinDown =
0027 binIndex(axisRanges.yMin, axisRanges.yMax, m_cfg.nBinsY, y - dy);
0028 int yBinUp =
0029 binIndex(axisRanges.yMin, axisRanges.yMax, m_cfg.nBinsY, y + dy);
0030
0031 for (int yBin = yBinDown; yBin <= yBinUp; ++yBin) {
0032
0033 if (yBin >= static_cast<int>(m_cfg.nBinsY) || yBin < 0) {
0034 continue;
0035 }
0036 fillBin(xBin, yBin, identifier, layer, weight);
0037 }
0038 }
0039 }
0040
0041 template <class identifier_t>
0042 void Acts::HoughTransformUtils::HoughCell<identifier_t>::fill(
0043 const identifier_t& identifier, unsigned layer, YieldType weight) {
0044
0045 if (m_hits.insert(identifier).second) {
0046
0047 m_nHits += weight;
0048 }
0049
0050 if (m_layers.insert(layer).second) {
0051 m_nLayers += weight;
0052 }
0053 }
0054 template <class identifier_t>
0055 void Acts::HoughTransformUtils::HoughCell<identifier_t>::reset() {
0056
0057 if (m_nLayers > 0) {
0058 m_layers.clear();
0059 }
0060 if (m_nHits > 0) {
0061 m_hits.clear();
0062 }
0063 m_nHits = 0;
0064 m_nLayers = 0;
0065 }
0066
0067 template <class identifier_t>
0068 Acts::HoughTransformUtils::HoughPlane<identifier_t>::HoughPlane(
0069 const HoughPlaneConfig& cfg)
0070 : m_cfg(cfg) {
0071
0072 m_houghHist = HoughHist(m_cfg.nBinsX, m_cfg.nBinsY);
0073 }
0074 template <class identifier_t>
0075 void Acts::HoughTransformUtils::HoughPlane<identifier_t>::fillBin(
0076 std::size_t binX, std::size_t binY, const identifier_t& identifier,
0077 unsigned layer, double w) {
0078
0079 m_touchedBins.insert({binX, binY});
0080
0081 m_houghHist(binX, binY).fill(identifier, layer, w);
0082
0083 YieldType nLayers = m_houghHist(binX, binY).nLayers();
0084 YieldType nHits = m_houghHist(binX, binY).nHits();
0085 if (nLayers > m_maxLayers) {
0086 m_maxLayers = nLayers;
0087 m_maxLocLayers = {binX, binY};
0088 }
0089 if (nHits > m_maxHits) {
0090 m_maxHits = nHits;
0091 m_maxLocHits = {binX, binY};
0092 }
0093 }
0094
0095 template <class identifier_t>
0096 void Acts::HoughTransformUtils::HoughPlane<identifier_t>::reset() {
0097
0098
0099 for (auto bin : m_touchedBins) {
0100 m_houghHist(bin).reset();
0101 }
0102
0103 m_maxHits = 0.;
0104 m_maxLayers = 0.;
0105
0106 m_touchedBins.clear();
0107 }
0108
0109 template <class identifier_t>
0110 Acts::HoughTransformUtils::PeakFinders::LayerGuidedCombinatoric<identifier_t>::
0111 LayerGuidedCombinatoric(const LayerGuidedCombinatoricConfig& cfg)
0112 : m_cfg(cfg) {}
0113
0114 template <class identifier_t>
0115 std::vector<typename Acts::HoughTransformUtils::PeakFinders::
0116 LayerGuidedCombinatoric<identifier_t>::Maximum>
0117 Acts::HoughTransformUtils::PeakFinders::LayerGuidedCombinatoric<
0118 identifier_t>::findPeaks(const HoughPlane<identifier_t>& plane) const {
0119
0120 std::vector<PeakFinders::LayerGuidedCombinatoric<identifier_t>::Maximum>
0121 maxima;
0122
0123 for (auto [x, y] : plane.getNonEmptyBins()) {
0124
0125 if (passThreshold(plane, x, y)) {
0126
0127 Maximum max;
0128 max.hitIdentifiers = plane.hitIds(x, y);
0129 maxima.push_back(max);
0130 }
0131 }
0132 return maxima;
0133 }
0134
0135 template <class identifier_t>
0136 bool Acts::HoughTransformUtils::PeakFinders::LayerGuidedCombinatoric<
0137 identifier_t>::passThreshold(const HoughPlane<identifier_t>& plane,
0138 std::size_t xBin, std::size_t yBin) const {
0139
0140 if (plane.nLayers(xBin, yBin) < m_cfg.threshold) {
0141 return false;
0142 }
0143
0144 if (m_cfg.localMaxWindowSize == 0) {
0145 return true;
0146 }
0147
0148
0149
0150 for (int dXbin = -m_cfg.localMaxWindowSize; dXbin <= m_cfg.localMaxWindowSize;
0151 dXbin++) {
0152 for (int dYbin = -m_cfg.localMaxWindowSize;
0153 dYbin <= m_cfg.localMaxWindowSize; dYbin++) {
0154
0155 if (dYbin == 0 && dXbin == 0) {
0156 continue;
0157 }
0158
0159 if (static_cast<int>(xBin) + dXbin < 0 ||
0160 static_cast<int>(yBin) + dYbin < 0) {
0161 continue;
0162 }
0163 if (xBin + dXbin >= plane.nBinsX() || yBin + dYbin >= plane.nBinsY()) {
0164 continue;
0165 }
0166
0167 if (plane.nLayers(xBin + dXbin, yBin + dYbin) >
0168 plane.nLayers(xBin, yBin)) {
0169 return false;
0170 }
0171
0172 if (plane.nLayers(xBin + dXbin, yBin + dYbin) <
0173 plane.nLayers(xBin, yBin)) {
0174 continue;
0175 }
0176
0177
0178
0179
0180
0181 if (plane.nHits(xBin + dXbin, yBin + dYbin) > plane.nHits(xBin, yBin)) {
0182 return false;
0183 }
0184
0185
0186 if (plane.nHits(xBin + dXbin, yBin + dYbin) == plane.nHits(xBin, yBin) &&
0187 (dYbin < 0 || (dYbin == 0 && dXbin < 0))) {
0188 return false;
0189 }
0190 }
0191 }
0192 return true;
0193 }
0194 template <class identifier_t>
0195 Acts::HoughTransformUtils::PeakFinders::IslandsAroundMax<
0196 identifier_t>::IslandsAroundMax(const IslandsAroundMaxConfig& cfg)
0197 : m_cfg(cfg) {}
0198
0199 template <class identifier_t>
0200 std::vector<typename Acts::HoughTransformUtils::PeakFinders::IslandsAroundMax<
0201 identifier_t>::Maximum>
0202 Acts::HoughTransformUtils::PeakFinders::IslandsAroundMax<
0203 identifier_t>::findPeaks(const HoughPlane<identifier_t>& plane,
0204 const HoughAxisRanges& ranges) {
0205
0206 YieldType max = plane.maxHits();
0207
0208 YieldType min = std::max(m_cfg.threshold, m_cfg.fractionCutoff * max);
0209
0210 std::vector<std::pair<std::size_t, std::size_t>> candidates;
0211 std::vector<Maximum> maxima;
0212
0213 std::map<std::pair<std::size_t, std::size_t>, YieldType> yieldMap;
0214
0215
0216 for (auto [x, y] : plane.getNonEmptyBins()) {
0217
0218
0219
0220 if (plane.nHits(x, y) > min) {
0221 candidates.push_back({x, y});
0222 yieldMap[{x, y}] = plane.nHits(x, y);
0223 }
0224 }
0225
0226 std::sort(candidates.begin(), candidates.end(),
0227 [&plane](const std::pair<std::size_t, std::size_t>& bin1,
0228 const std::pair<std::size_t, std::size_t>& bin2) {
0229 return (plane.nHits(bin1.first, bin1.second) >
0230 plane.nHits(bin2.first, bin2.second));
0231 });
0232
0233
0234
0235 std::vector<std::pair<std::size_t, std::size_t>> toExplore;
0236 std::vector<std::pair<std::size_t, std::size_t>> solution;
0237
0238
0239 for (auto& cand : candidates) {
0240
0241
0242 if (yieldMap[cand] < min) {
0243 continue;
0244 }
0245
0246 CoordType xCand =
0247 binCenter(ranges.xMin, ranges.xMax, plane.nBinsX(), cand.first);
0248 CoordType yCand =
0249 binCenter(ranges.yMin, ranges.yMax, plane.nBinsY(), cand.second);
0250
0251 bool goodSpacing = true;
0252 for (auto& found : maxima) {
0253 if (std::abs(xCand - found.x) < m_cfg.minSpacingBetweenPeaks.first ||
0254 std::abs(yCand - found.y) < m_cfg.minSpacingBetweenPeaks.second) {
0255 goodSpacing = false;
0256 break;
0257 }
0258 }
0259 if (!goodSpacing) {
0260 continue;
0261 }
0262
0263 toExplore.clear();
0264 solution.clear();
0265
0266
0267 toExplore.push_back(cand);
0268
0269 while (!toExplore.empty()) {
0270 extendMaximum(solution, toExplore, min, yieldMap);
0271 }
0272
0273 if (solution.empty()) {
0274 continue;
0275 }
0276
0277 Maximum maximum;
0278 CoordType max_x = 0;
0279 CoordType max_y = 0;
0280 CoordType pos_den = 0;
0281 CoordType ymax = -std::numeric_limits<CoordType>::max();
0282 CoordType ymin = std::numeric_limits<CoordType>::max();
0283 CoordType xmax = -std::numeric_limits<CoordType>::max();
0284 CoordType xmin = std::numeric_limits<CoordType>::max();
0285
0286
0287
0288 for (auto& [xBin, yBin] : solution) {
0289 const auto& hidIds = plane.hitIds(xBin, yBin);
0290 maximum.hitIdentifiers.insert(hidIds.cbegin(), hidIds.cend());
0291 CoordType xHit =
0292 binCenter(ranges.xMin, ranges.xMax, plane.nBinsX(), xBin);
0293 CoordType yHit =
0294 binCenter(ranges.yMin, ranges.yMax, plane.nBinsY(), yBin);
0295 YieldType nHits = plane.nHits(xBin, yBin);
0296 max_x += xHit * nHits;
0297 max_y += yHit * nHits;
0298 pos_den += nHits;
0299 if (xHit > xmax) {
0300 xmax = xHit;
0301 }
0302 if (yHit > ymax) {
0303 ymax = yHit;
0304 }
0305 if (xHit < xmin) {
0306 xmin = xHit;
0307 }
0308 if (yHit < ymin) {
0309 ymin = yHit;
0310 }
0311 }
0312
0313 maximum.x = max_x / pos_den;
0314 maximum.y = max_y / pos_den;
0315
0316 maximum.wx = 0.5 * (xmax - xmin);
0317 maximum.wy = 0.5 * (ymax - ymin);
0318 maxima.push_back(maximum);
0319 }
0320 return maxima;
0321 }
0322
0323 template <class identifier_t>
0324 void Acts::HoughTransformUtils::PeakFinders::IslandsAroundMax<identifier_t>::
0325 extendMaximum(
0326 std::vector<std::pair<std::size_t, std::size_t>>& inMaximum,
0327 std::vector<std::pair<std::size_t, std::size_t>>& toExplore,
0328 YieldType threshold,
0329 std::map<std::pair<std::size_t, std::size_t>, YieldType>& yieldMap) {
0330
0331
0332 auto nextCand = toExplore.back();
0333 toExplore.pop_back();
0334
0335 if (yieldMap[nextCand] < threshold) {
0336 return;
0337 }
0338
0339
0340
0341 inMaximum.push_back(nextCand);
0342
0343 yieldMap[nextCand] = -1.0f;
0344
0345
0346
0347 for (auto step : m_stepDirections) {
0348 auto newCand = std::make_pair(nextCand.first + step.first,
0349 nextCand.second + step.second);
0350
0351
0352
0353
0354
0355 if (yieldMap[newCand] > threshold) {
0356 toExplore.push_back(newCand);
0357 }
0358 }
0359 }