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