![]() |
|
|||
File indexing completed on 2025-08-06 08:10:09
0001 // This file is part of the Acts project. 0002 // 0003 // Copyright (C) 2022 CERN for the benefit of the Acts project 0004 // 0005 // This Source Code Form is subject to the terms of the Mozilla Public 0006 // License, v. 2.0. If a copy of the MPL was not distributed with this 0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 0008 0009 /// This file implements the tools for a hough transform. 0010 0011 #pragma once 0012 #include "Acts/Utilities/Delegate.hpp" 0013 #include "Acts/Utilities/Logger.hpp" 0014 #include "Acts/Utilities/Result.hpp" 0015 0016 #include <algorithm> 0017 #include <array> 0018 #include <map> 0019 #include <optional> 0020 #include <set> 0021 #include <unordered_set> 0022 0023 #include "HoughVectors.hpp" 0024 0025 namespace Acts::HoughTransformUtils { 0026 0027 /// this type is responsible for encoding the parameters of our hough space 0028 using CoordType = double; 0029 0030 // this type is used to encode hit counts. 0031 // Floating point to allow hit weights to be applied 0032 using YieldType = float; 0033 0034 /// @brief this function represents a mapping of a coordinate point in detector space to a line in 0035 /// hough space. Given the value of the first hough coordinate, it shall return 0036 /// the corresponding second coordinate according to the line parametrisation. 0037 /// Should be implemented by the user. 0038 /// @tparam PointType: The class representing a point in detector space (can differ between implementations) 0039 template <class PointType> 0040 using LineParametrisation = 0041 std::function<CoordType(CoordType, const PointType&)>; 0042 0043 /// @brief struct to define the ranges of the hough histogram. 0044 /// Used to move between parameter and bin index coordinates. 0045 /// Disconnected from the hough plane binning to be able to re-use 0046 /// a plane with a given binning for several parameter ranges 0047 struct HoughAxisRanges { 0048 CoordType xMin = 0.0f; // minimum value of the first coordinate 0049 CoordType xMax = 0.0f; // maximum value of the first coordinate 0050 CoordType yMin = 0.0f; // minimum value of the second coordinate 0051 CoordType yMax = 0.0f; // maximum value of the second coordinate 0052 }; 0053 0054 /// convenience functions to link bin indices to axis coordinates 0055 0056 /// @brief find the bin index corresponding to a certain abscissa 0057 /// of the coordinate axis, based on the axis limits and binning. 0058 /// @param min: Start of axis range 0059 /// @param max: End of axis range 0060 /// @param nSteps: Number of bins in axis 0061 /// @param val: value to find the corresponding bin for 0062 /// @return the bin number. 0063 /// No special logic to prevent over-/underflow, checking these is 0064 /// left to the caller 0065 inline int binIndex(double min, double max, unsigned nSteps, double val) { 0066 return static_cast<int>((val - min) / (max - min) * nSteps); 0067 } 0068 // Returns the lower bound of the bin specified by step 0069 /// @param min: Start of axis range 0070 /// @param max: End of axis range 0071 /// @param nSteps: Number of bins in axis 0072 /// @param binIndex: The index of the bin 0073 /// @return the parameter value at the lower bin edge. 0074 /// No special logic to prevent over-/underflow, checking these is 0075 /// left to the caller 0076 inline double lowerBinEdge(double min, double max, unsigned nSteps, 0077 std::size_t binIndex) { 0078 return min + (max - min) * binIndex / nSteps; 0079 } 0080 // Returns the lower bound of the bin specified by step 0081 /// @param min: Start of axis range 0082 /// @param max: End of axis range 0083 /// @param nSteps: Number of bins in axis 0084 /// @param binIndex: The index of the bin 0085 /// @return the parameter value at the bin center. 0086 /// No special logic to prevent over-/underflow, checking these is 0087 /// left to the caller 0088 inline double binCenter(double min, double max, unsigned nSteps, 0089 std::size_t binIndex) { 0090 return min + (max - min) * 0.5 * (2 * binIndex + 1) / nSteps; 0091 } 0092 0093 /// @brief data class for the information to store for each 0094 /// cell of the hough histogram. 0095 /// @tparam identifier_t: Type of the identifier to associate to the hits 0096 /// Should be sortable. Used to uniquely identify each 0097 /// hit and to eventually return the list of hits per cell 0098 template <class identifier_t> 0099 class HoughCell { 0100 public: 0101 /// @brief construct the cell as empty 0102 HoughCell() = default; 0103 /// @brief add an entry to this cell 0104 /// @param identifier: Identifier of the hit (used to distinguish hits from another) 0105 /// @param layer: Layer of the hit (used when counting layers) 0106 /// @param weight: Optional weight to assign to the hit 0107 void fill(const identifier_t& identifier, unsigned int layer, 0108 YieldType weight = 1.); 0109 /// @brief access the number of layers with hits compatible with this cell 0110 YieldType nLayers() const { return m_nLayers; } 0111 /// @brief access the number of unique hits compatible with this cell 0112 YieldType nHits() const { return m_nHits; } 0113 /// @brief access the set of layers compatible with this cell 0114 const std::unordered_set<unsigned>& layers() const { return m_layers; } 0115 /// @brief access the set of unique hits compatible with this cell 0116 const std::unordered_set<identifier_t>& hits() const { return m_hits; } 0117 /// @brief reset this cell, removing any existing content. 0118 void reset(); 0119 0120 private: 0121 /// data members 0122 0123 YieldType m_nLayers = 0124 0; // (weighted) number of layers with hits on this cell 0125 YieldType m_nHits = 0; // (weighted) number of unique hits on this cell 0126 std::unordered_set<unsigned> m_layers = 0127 {}; // set of layers with hits on this cell 0128 std::unordered_set<identifier_t> m_hits = 0129 {}; // set of unique hits on this cell 0130 }; 0131 0132 /// @brief Configuration - number of bins in each axis. 0133 /// The Hough plane is agnostic of how the bins map to 0134 /// coordinates, allowing to re-use a plane for several 0135 /// (sub) detectors of different dimensions if the bin number 0136 /// remains applicable 0137 struct HoughPlaneConfig { 0138 std::size_t nBinsX = 0; // number of bins in the first coordinate 0139 std::size_t nBinsY = 0; // number of bins in the second coordinate 0140 }; 0141 0142 /// @brief Representation of the hough plane - the histogram used 0143 /// for the hough transform with methods to fill and evaluate 0144 /// the histogram. Templated to a class used as identifier for the hits 0145 template <class identifier_t> 0146 class HoughPlane { 0147 public: 0148 /// @brief hough histogram representation as a 2D-indexable vector of hough cells 0149 using HoughHist = MultiIndexedVector2D<HoughCell<identifier_t>>; 0150 0151 /// @brief instantiate the (empty) hough plane 0152 /// @param cfg: configuration 0153 HoughPlane(const HoughPlaneConfig& cfg); 0154 0155 /// fill and reset methods to modify the grid content 0156 0157 /// @brief add one measurement to the hough plane 0158 /// @tparam PointType: Type of the objects to use when adding measurements (e.g. experiment EDM object) 0159 /// @param measurement: The measurement to add 0160 /// @param axisRanges: Ranges of the hough axes, used to map the bin numbers to parameter values 0161 /// @param linePar: The function y(x) parametrising the hough space line for a given measurement 0162 /// @param widthPar: The function dy(x) parametrising the width of the y(x) curve 0163 /// for a given measurement 0164 /// @param identifier: The unique identifier for the given hit 0165 /// @param layer: A layer index for this hit 0166 /// @param weight: An optional weight to assign to this hit 0167 template <class PointType> 0168 void fill(const PointType& measurement, const HoughAxisRanges& axisRanges, 0169 LineParametrisation<PointType> linePar, 0170 LineParametrisation<PointType> widthPar, 0171 const identifier_t& identifier, unsigned layer = 0, 0172 YieldType weight = 1.0f); 0173 /// @brief resets the contents of the grid. Can be used to avoid reallocating the histogram 0174 /// when switching regions / (sub)detectors 0175 void reset(); 0176 0177 //// user-facing accessors 0178 0179 /// @brief get the layers with hits in one cell of the histogram 0180 /// @param xBin: bin index in the first coordinate 0181 /// @param yBin: bin index in the second coordinate 0182 /// @return the set of layer indices that have hits for this cell 0183 const std::unordered_set<unsigned>& layers(std::size_t xBin, 0184 std::size_t yBin) const { 0185 return m_houghHist(xBin, yBin).layers(); 0186 } 0187 0188 /// @brief get the (weighted) number of layers with hits in one cell of the histogram 0189 /// @param xBin: bin index in the first coordinate 0190 /// @param yBin: bin index in the second coordinate 0191 /// @return the (weighed) number of layers that have hits for this cell 0192 YieldType nLayers(std::size_t xBin, std::size_t yBin) const { 0193 return m_houghHist(xBin, yBin).nLayers(); 0194 } 0195 0196 /// @brief get the identifiers of all hits in one cell of the histogram 0197 /// @param xBin: bin index in the first coordinate 0198 /// @param yBin: bin index in the second coordinate 0199 /// @return the set of identifiers of the hits for this cell 0200 const std::unordered_set<identifier_t>& hitIds(std::size_t xBin, 0201 std::size_t yBin) const { 0202 return m_houghHist(xBin, yBin).hits(); 0203 } 0204 /// @brief get the (weighted) number of hits in one cell of the histogram 0205 /// @param xBin: bin index in the first coordinate 0206 /// @param yBin: bin index in the second coordinate 0207 /// @return the (weighted) number of hits for this cell 0208 YieldType nHits(std::size_t xBin, std::size_t yBin) const { 0209 return m_houghHist(xBin, yBin).nHits(); 0210 } 0211 0212 /// @brief get the number of bins on the first coordinate 0213 std::size_t nBinsX() const { return m_cfg.nBinsX; } 0214 /// @brief get the number of bins on the second coordinate 0215 std::size_t nBinsY() const { return m_cfg.nBinsY; } 0216 0217 /// @brief get the maximum number of (weighted) hits seen in a single 0218 /// cell across the entire histrogram. 0219 YieldType maxHits() const { return m_maxHits; } 0220 0221 /// @brief get the list of cells with non-zero content. 0222 /// Useful for peak-finders in sparse data 0223 /// to avoid looping over all cells 0224 const std::set<std::pair<std::size_t, std::size_t>>& getNonEmptyBins() const { 0225 return m_touchedBins; 0226 } 0227 0228 /// @brief get the bin indices of the cell containing the largest number 0229 /// of (weighted) hits across the entire histogram 0230 std::pair<std::size_t, std::size_t> locMaxHits() const { 0231 return m_maxLocHits; 0232 } 0233 0234 /// @brief get the maximum number of (weighted) layers with hits seen 0235 /// in a single cell across the entire histrogram. 0236 YieldType maxLayers() const { return m_maxLayers; } 0237 0238 /// @brief get the bin indices of the cell containing the largest number 0239 /// of (weighted) layers with hits across the entire histogram 0240 std::pair<std::size_t, std::size_t> locMaxLayers() const { 0241 return m_maxLocLayers; 0242 } 0243 0244 private: 0245 /// @brief Helper method to fill a bin of the hough histogram. 0246 /// Updates the internal helper data structures (maximum tracker etc). 0247 /// @param binX: bin number along x 0248 /// @param binY: bin number along y 0249 /// @param identifier: hit identifier 0250 /// @param layer: layer index 0251 /// @param w: optional hit weight 0252 void fillBin(std::size_t binX, std::size_t binY, 0253 const identifier_t& identifier, unsigned layer, double w = 1.0f); 0254 0255 YieldType m_maxHits = 0.0f; // track the maximum number of hits seen 0256 YieldType m_maxLayers = 0.0f; // track the maximum number of layers seen 0257 std::pair<std::size_t, std::size_t> m_maxLocHits = { 0258 0, 0}; // track the location of the maximum in hits 0259 std::pair<std::size_t, std::size_t> m_maxLocLayers = { 0260 0, 0}; // track the location of the maximum in layers 0261 std::set<std::pair<std::size_t, std::size_t>> m_touchedBins = 0262 {}; // track the bins with non-trivial content 0263 HoughPlaneConfig m_cfg; // the configuration object 0264 HoughHist m_houghHist; // the histogram data object 0265 }; 0266 0267 /// example peak finders. 0268 namespace PeakFinders { 0269 /// configuration for the LayerGuidedCombinatoric peak finder 0270 struct LayerGuidedCombinatoricConfig { 0271 YieldType threshold = 3.0f; // min number of layers to obtain a maximum 0272 int localMaxWindowSize = 0; // Only create candidates from a local maximum 0273 }; 0274 0275 /// @brief Peak finder inspired by ATLAS ITk event filter developments. 0276 /// Builds peaks based on layer counts and allows for subsequent resolution 0277 /// of the combinatorics by building multiple candidates per peak if needed. 0278 /// In flat regions, peak positions are moved towards smaller values of the 0279 /// second and first coordinate. 0280 /// @tparam identifier_t: The identifier type to use. Should match the one used in the hough plane. 0281 template <class identifier_t> 0282 class LayerGuidedCombinatoric { 0283 public: 0284 /// @brief data class representing the found maxima. 0285 /// Here, we just have a list of cluster identifiers 0286 struct Maximum { 0287 std::unordered_set<identifier_t> hitIdentifiers = 0288 {}; // identifiers of contributing hits 0289 }; 0290 /// @brief constructor 0291 /// @param cfg: Configuration object 0292 LayerGuidedCombinatoric(const LayerGuidedCombinatoricConfig& cfg); 0293 0294 /// @brief main peak finder method. 0295 /// @param plane: Filled hough plane to search 0296 /// @return vector of found maxima 0297 std::vector<Maximum> findPeaks(const HoughPlane<identifier_t>& plane) const; 0298 0299 private: 0300 /// @brief check if a given bin is a local maximum. 0301 /// @param plane: The filled hough plane 0302 /// @param xBin: x bin index 0303 /// @param yBin: y bin index 0304 /// @return true if a maximum, false otherwise 0305 bool passThreshold(const HoughPlane<identifier_t>& plane, std::size_t xBin, 0306 std::size_t yBin) const; // did we pass extensions? 0307 0308 LayerGuidedCombinatoricConfig m_cfg; // configuration data object 0309 }; 0310 /// @brief Configuration for the IslandsAroundMax peak finder 0311 struct IslandsAroundMaxConfig { 0312 YieldType threshold = 0313 3.0f; // min number of weigted hits required in a maximum 0314 YieldType fractionCutoff = 0315 0; // Fraction of the global maximum at which to cut off maxima 0316 std::pair<CoordType, CoordType> minSpacingBetweenPeaks = { 0317 0.0f, 0.0f}; // minimum distance of a new peak from existing peaks in 0318 // parameter space 0319 }; 0320 /// @brief Peak finder inspired by ATLAS muon reconstruction. 0321 /// Looks for regions above a given fraction of the global maximum 0322 /// hit count and connects them into islands comprising adjacent bins 0323 /// above the threshold. Peak positions are averaged across cells in the island, 0324 /// weighted by hit counts 0325 /// @tparam identifier_t: The identifier type to use. Should match the one used in the hough plane. 0326 template <class identifier_t> 0327 class IslandsAroundMax { 0328 public: 0329 /// @brief data struct representing a local maximum. 0330 /// Comes with a position estimate and a list of hits within the island 0331 struct Maximum { 0332 CoordType x = 0; // x value of the maximum 0333 CoordType y = 0; // y value of the maximum 0334 CoordType wx = 0; // x width of the maximum 0335 CoordType wy = 0; // y width of the maximum 0336 std::unordered_set<identifier_t> hitIdentifiers = 0337 {}; // identifiers of contributing hits 0338 }; 0339 /// @brief constructor. 0340 /// @param cfg: configuration object 0341 IslandsAroundMax(const IslandsAroundMaxConfig& cfg); 0342 0343 /// @brief main peak finder method. 0344 /// @param plane: The filled hough plane to search 0345 /// @param ranges: The axis ranges used for mapping between parameter space and bins. 0346 /// @return List of the found maxima 0347 std::vector<Maximum> findPeaks(const HoughPlane<identifier_t>& plane, 0348 const HoughAxisRanges& ranges); 0349 0350 private: 0351 /// @brief method to incrementally grow an island by adding adjacent cells 0352 /// Performs a breadth-first search for neighbours above threshold and adds 0353 /// them to candidate. Stops when no suitable neighbours are left. 0354 /// @param inMaximum: List of cells found in the island. Incrementally populated by calls to the method 0355 /// @param toExplore: List of neighbour cell candidates left to explore. Method will not do anything once this is empty 0356 /// @param threshold: the threshold to apply to check if a cell should be added to an island 0357 /// @param yieldMap: A map of the hit content of above-threshold cells. Used cells will be set to empty content to avoid re-use by subsequent calls 0358 void extendMaximum( 0359 std::vector<std::pair<std::size_t, std::size_t>>& inMaximum, 0360 std::vector<std::pair<std::size_t, std::size_t>>& toExplore, 0361 YieldType threshold, 0362 std::map<std::pair<std::size_t, std::size_t>, YieldType>& yieldMap); 0363 0364 IslandsAroundMaxConfig m_cfg; // configuration data object 0365 0366 /// @brief array of steps to consider when exploring neighbouring cells. 0367 const std::array<std::pair<int, int>, 8> m_stepDirections{ 0368 std::make_pair(-1, -1), std::make_pair(0, -1), std::make_pair(1, -1), 0369 std::make_pair(-1, 0), std::make_pair(1, 0), std::make_pair(-1, 1), 0370 std::make_pair(0, 1), std::make_pair(1, 1)}; 0371 }; 0372 } // namespace PeakFinders 0373 } // namespace Acts::HoughTransformUtils 0374 0375 #include "HoughTransformUtils.ipp"
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |