Belle II Software development
BoxDivisionHoughTree.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#pragma once
9#include <tracking/trackFindingCDC/hough/trees/WeightedFastHoughTree.h>
10#include <tracking/trackFindingCDC/hough/baseelements/SectoredLinearDivision.h>
11
12#include <tracking/trackingUtilities/numerics/LookupTable.h>
13
14#include <tracking/trackingUtilities/utilities/TupleGenerate.h>
15
16#include <type_traits>
17#include <utility>
18#include <tuple>
19#include <array>
20#include <memory>
21
22namespace Belle2 {
27 namespace TrackFindingCDC {
28
33 template <class AItemPtr, class AHoughBox, size_t ... divisions>
35
36 public:
38 using HoughBox = AHoughBox;
39
42
45
47 template <size_t I>
48 using Type = typename HoughBox::template Type<I>;
49
51 template <class T>
52 using HasType = typename HoughBox::template HasType<T>;
53
55 template <class T>
56 using TypeIndex = typename HoughBox::template TypeIndex<T>;
57
59 template <size_t I>
60 using Width = typename HoughBox::template Width<I>;
61
63 using Node = typename HoughTree::Node;
64
65 public:
67 explicit BoxDivisionHoughTree(int maxLevel, int sectorLevelSkip = 0)
68 : m_maxLevel(maxLevel)
69 , m_sectorLevelSkip(sectorLevelSkip)
70 // cppcheck-suppress nullPointer ; false positive on the variadic pack expansion
71 , m_overlaps((divisions * 0)...)
72 {
73 }
74
75 private:
77 template <size_t I>
78 using Array = typename Type<I>::Array;
79
81 using Arrays = TrackingUtilities::TupleGenerateN<Array, sizeof...(divisions)>;
82
83 public:
85 size_t getDivision(size_t i) const
86 {
87 return m_divisions[i];
88 }
89
104 template <size_t I>
105 void constructArray(double lowerBound,
106 double upperBound,
107 Width<I> nBinOverlap = 0,
108 Width<I> nBinWidth = 0)
109 {
110 static_assert(std::is_integral<Width<I> >::value, "Method only applicable to discrete axes");
111 const size_t division = getDivision(I);
112 const int granularityLevel = m_maxLevel + m_sectorLevelSkip;
113 const size_t nBins = std::pow(division, granularityLevel);
114
115 if (nBinWidth == 0) {
116 nBinWidth = nBinOverlap + 1;
117 }
118
119 B2ASSERT("Width " << nBinWidth << "is not bigger than overlap " << nBinOverlap,
120 nBinOverlap < nBinWidth);
121
122 const auto nPositions = (nBinWidth - nBinOverlap) * nBins + nBinOverlap + 1;
123 std::get<I>(m_arrays) = TrackingUtilities::linspace<float>(lowerBound, upperBound, nPositions);
124 std::get<I>(m_overlaps) = nBinOverlap;
125 }
126
128 template <size_t I>
129 void assignArray(Array<I> array, Width<I> overlap = 0)
130 {
131 std::get<I>(m_arrays) = std::move(array);
132 std::get<I>(m_overlaps) = overlap;
133
134 // In case of a discrete axes, check whether the size of the array is sensible
135 // such that the bin width at the highest granularity level is a whole number given the overlap.
136 if (std::is_integral<Width<I> >::value) {
137 const int division = getDivision(I);
138 const int granularityLevel = m_maxLevel + m_sectorLevelSkip;
139 const long int nBins = std::pow(division, granularityLevel);
140 const long int nPositions = std::get<I>(m_arrays).size();
141 const long int nWidthTimeNBins = nPositions - 1 + (nBins - 1) * overlap;
142
143 B2ASSERT("Not enough positions in array to cover all bins.\n"
144 "Expected: positions = " << nBins - (nBins - 1) * overlap + 1 << " at least.\n"
145 "Actual: positions = " << nPositions << " (overlap = " << overlap << ", bins = " << nBins << ")\n",
146 nWidthTimeNBins >= nBins);
147
148 B2ASSERT("Number of positions in array introduces inhomogeneous width at the highest granularity level.\n"
149 "Expected: positions = 'width * bins - (bins - 1) * overlap + 1'\n"
150 "Actual: positions = " << nPositions << " (overlap = " << overlap << ", bins = " << nBins << ")\n",
151 nWidthTimeNBins % nBins == 0);
152 }
153 }
154
156 template <class T>
157 std::enable_if_t< HasType<T>::value, void>
159 {
160 assignArray<TypeIndex<T>::value>(std::move(array), overlap);
161 }
162
163 public:
166 {
167 // Compose the hough space
168 HoughBox houghPlane = constructHoughPlane();
170 m_houghTree.reset(new HoughTree(std::move(houghPlane), std::move(boxDivision)));
171 }
172
174 template <class AItemPtrs>
175 void seed(const AItemPtrs& items)
176 {
177 if (not m_houghTree) initialize();
178 m_houghTree->seed(items);
179 }
180
182 void fell()
183 {
184 HoughTree* const tree = this->m_houghTree.get();
185 if (tree != nullptr) {
186 tree->fell();
187 }
188 }
189
191 void raze()
192 {
193 HoughTree* const tree = this->m_houghTree.get();
194 if (tree != nullptr) {
195 tree->raze();
196 }
197 }
198
199 public:
202 {
203 return m_houghTree.get();
204 }
205
207 int getMaxLevel() const
208 {
209 return m_maxLevel;
210 }
211
213 void setMaxLevel(int maxLevel)
214 {
215 m_maxLevel = maxLevel;
216 }
217
220 {
221 return m_sectorLevelSkip;
222 }
223
225 void setSectorLevelSkip(int sectorLevelSkip)
226 {
227 m_sectorLevelSkip = sectorLevelSkip;
228 }
229
231 template <size_t I>
232 const Array<I>& getArray() const
233 {
234 return std::get<I>(m_arrays);
235 }
236
237 private:
239 template <size_t... Is>
240 HoughBox constructHoughPlaneImpl(const std::index_sequence<Is...>& is __attribute__((unused)))
241 {
242 return HoughBox(Type<Is>::getRange(std::get<Is>(m_arrays))...);
243 }
244
247 {
248 return constructHoughPlaneImpl(std::make_index_sequence<sizeof...(divisions)>());
249 }
250
251 private:
253 const std::array<size_t, sizeof ...(divisions)> m_divisions = {{divisions ...}};
254
256 std::unique_ptr<HoughTree> m_houghTree = nullptr;
257
260
263
265 typename HoughBox::Delta m_overlaps;
266
269 };
270 }
272}
void fell()
Terminates the processing by striping all hit information from the tree.
void initialize()
Initialise the algorithm by constructing the hough tree from the parameters.
void raze()
Release all memory that the tree acquired during the runs.
void setSectorLevelSkip(int sectorLevelSkip)
Setter for number of levels to skip in first level to form a finer sectored hough space.
HoughBox constructHoughPlaneImpl(const std::index_sequence< Is... > &is)
Construct the box of the top node of the tree. Implementation unroling the indices.
void setMaxLevel(int maxLevel)
Setter maximal level of the hough tree.
size_t getDivision(size_t i) const
Getter the number of divisions at each level for coordinate index I.
const Array< I > & getArray() const
Getter for the array of discrete value for coordinate I.
void seed(const AItemPtrs &items)
Prepare the leave finding by filling the top node with given hits.
HoughBox constructHoughPlane()
Construct the box of the top node of the tree.
int getSectorLevelSkip() const
Getter for number of levels to skip in first level to form a finer sectored hough space.
void assignArray(Array< I > array, Width< I > overlap=0)
Provide an externally constructed array by coordinate index.
std::enable_if_t< HasType< T >::value, void > assignArray(Array< TypeIndex< T >::value > array, Width< TypeIndex< T >::value > overlap=0)
Provide an externally constructed array by coordinate type.
int getMaxLevel() const
Getter for the currently set maximal level.
BoxDivisionHoughTree(int maxLevel, int sectorLevelSkip=0)
Constructor using the given maximal level.
void constructArray(double lowerBound, double upperBound, Width< I > nBinOverlap=0, Width< I > nBinWidth=0)
Construct the discrete value array at coordinate index I.
HoughTree * getTree() const
Getter for the tree used in the search in the hough plane.
Factory object that constructs sub boxes from a given box with optional overlaps.
Dynamic tree structure with weighted items in each node which are markable through out the tree.
Abstract base class for different kinds of events.