Belle II Software  release-08-01-10
SingleHoughSpaceFastInterceptFinder.cc
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 #include <tracking/vxdHoughTracking/findlets/SingleHoughSpaceFastInterceptFinder.h>
9 #include <tracking/vxdHoughTracking/entities/VXDHoughState.h>
10 #include <tracking/spacePointCreation/SpacePoint.h>
11 #include <tracking/spacePointCreation/SpacePointTrackCand.h>
12 #include <tracking/trackFindingCDC/utilities/StringManipulation.h>
13 #include <tracking/trackFindingCDC/utilities/Algorithms.h>
14 #include <vxd/dataobjects/VxdID.h>
15 #include <framework/core/ModuleParamList.h>
16 #include <framework/core/ModuleParamList.templateDetails.h>
17 
18 using namespace Belle2;
19 using namespace TrackFindingCDC;
20 using namespace vxdHoughTracking;
21 
22 SingleHoughSpaceFastInterceptFinder::SingleHoughSpaceFastInterceptFinder() : Super()
23 {
24 }
25 
26 void SingleHoughSpaceFastInterceptFinder::exposeParameters(ModuleParamList* moduleParamList, const std::string& prefix)
27 {
28  Super::exposeParameters(moduleParamList, prefix);
29 
30  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumRecursionLevel"), m_maxRecursionLevel,
31  "Maximum recursion level for the fast Hough trafo algorithm.", m_maxRecursionLevel);
32 
33  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "nAngleSectors"), m_nAngleSectors,
34  "Number of angle sectors (= x-axis) dividing the Hough space.", m_nAngleSectors);
35 
36  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "nVerticalSectors"), m_nVerticalSectors,
37  "Number of vertical sectors (= y-axis) dividing the Hough space.", m_nVerticalSectors);
38 
39  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "verticalHoughSpaceSize"), m_verticalHoughSpaceSize,
40  "Vertical size of the Hough space.", m_verticalHoughSpaceSize);
41 
42  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "HoughSpaceMinimumX"), m_minimumX,
43  "Minimum x value of the Hough space.", m_minimumX);
44 
45  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "HoughSpaceMaximumX"), m_maximumX,
46  "Maximum x value of the Hough space.", m_maximumX);
47 
48  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "minimumHSClusterSize"), m_MinimumHSClusterSize,
49  "Maximum x value of the Hough space.", m_MinimumHSClusterSize);
50 
51  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumHSClusterSize"), m_MaximumHSClusterSize,
52  "Maximum x value of the Hough space.", m_MaximumHSClusterSize);
53 
54  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumHSClusterSizeX"), m_MaximumHSClusterSizeX,
55  "Maximum x value of the Hough space.", m_MaximumHSClusterSizeX);
56 
57  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumHSClusterSizeY"), m_MaximumHSClusterSizeY,
58  "Maximum x value of the Hough space.", m_MaximumHSClusterSizeY);
59 
60 }
61 
63 {
65 
66  m_maxRecursionLevel = ceil(log2(std::max(m_nAngleSectors, m_nVerticalSectors))) - 1;
67  if (m_maxRecursionLevel > 14) {
68  B2ERROR("The maximum number of recursions (maximumRecursionLevel) must not be larger than 14, but it is " <<
70  ", please choose a smaller value for maximumRecursionLevel, and / or for nAngleSectors and / or nVerticalSectors.");
71  }
73  for (uint i = 0; i < m_nAngleSectors; i++) {
74  double x = m_minimumX + m_unitX * (double)i;
75  double xc = x + 0.5 * m_unitX;
76 
77  m_HSXLUT[i] = x;
78  m_HSSinValuesLUT[i] = sin(x);
79  m_HSCosValuesLUT[i] = cos(x);
80  m_HSCenterSinValuesLUT[i] = sin(xc);
81  m_HSCenterCosValuesLUT[i] = cos(xc);
82  m_HSXCenterLUT[i] = xc;
83  }
87 
89  for (uint i = 0; i <= m_nVerticalSectors; i++) {
92  }
93  B2DEBUG(29, "HS size x: " << (m_maximumX - m_minimumX) << " HS size y: " << m_verticalHoughSpaceSize <<
94  " unitX: " << m_unitX << " unitY: " << m_unitY);
95 }
96 
97 
98 void SingleHoughSpaceFastInterceptFinder::apply(std::vector<VXDHoughState>& hits,
99  std::vector<std::vector<VXDHoughState*>>& rawTrackCandidates)
100 {
101  m_trackCandidates.clear();
102  m_activeSectors.clear();
103 
104  const std::vector<VXDHoughState*> currentEventHitList = TrackFindingCDC::as_pointers<VXDHoughState>(hits);
105 
106  fastInterceptFinder2d(currentEventHitList, 0, m_nAngleSectors, 0, m_nVerticalSectors, 0);
107 
109 
110  for (auto& trackCand : m_trackCandidates) {
111  // sort for layer, and 2D radius in case of same layer before storing as SpacePointTrackCand
112  // outer hit goes first, as later on tracks are build from outside to inside
113  std::sort(trackCand.begin(), trackCand.end(),
114  [](const VXDHoughState * a, const VXDHoughState * b) {
115  return
116  (a->getDataCache().layer > b->getDataCache().layer) or
117  (a->getDataCache().layer == b->getDataCache().layer
118  and a->getHit()->getPosition().Perp() > b->getHit()->getPosition().Perp());
119  });
120 
121  rawTrackCandidates.emplace_back(trackCand);
122  }
123 
124  B2DEBUG(29, "m_trackCandidates.size: " << m_trackCandidates.size());
125 
126 }
127 
128 
129 void SingleHoughSpaceFastInterceptFinder::fastInterceptFinder2d(const std::vector<VXDHoughState*>& hits, uint xmin, uint xmax,
130  uint ymin,
131  uint ymax, uint currentRecursion)
132 {
133  std::vector<VXDHoughState*> containedHits;
134  containedHits.reserve(hits.size());
135  std::bitset<8> layerHits; /* For layer filter */
136 
137  if (currentRecursion == m_maxRecursionLevel + 1) return;
138 
139  // these int-divisions can cause {min, center} or {center, max} to be the same, which is a desired behaviour
140  const uint centerx = xmin + (uint)((xmax - xmin) / 2);
141  const uint centery = ymin + (uint)((ymax - ymin) / 2);
142  const uint xIndexCache[3] = {xmin, centerx, xmax};
143  const uint yIndexCache[3] = {ymin, centery, ymax};
144 
145  for (int i = 0; i < 2 ; ++i) {
146  const uint left = xIndexCache[i];
147  const uint right = xIndexCache[i + 1];
148  const uint localIndexX = left;
149 
150  if (left == right) continue;
151 
152  const double& sinLeft = m_HSSinValuesLUT[left];
153  const double& cosLeft = m_HSCosValuesLUT[left];
154  const double& sinRight = m_HSSinValuesLUT[right];
155  const double& cosRight = m_HSCosValuesLUT[right];
156 
157  // the sin and cos of the current center can't be stored in a LUT, as the number of possible centers
158  // is quite large and the logic would become rather complex
159  const double sinCenter = m_HSCenterSinValuesLUT[(left + right) / 2];
160  const double cosCenter = m_HSCenterCosValuesLUT[(left + right) / 2];
161 
162  for (int j = 0; j < 2; ++j) {
163  const uint lowerIndex = yIndexCache[j];
164  const uint upperIndex = yIndexCache[j + 1];
165 
166  if (lowerIndex == upperIndex) continue;
167 
168  const uint localIndexY = lowerIndex;
169  const double& localUpperCoordinate = m_HSYLUT[lowerIndex];
170  const double& localLowerCoordinate = m_HSYLUT[upperIndex];
171 
172  // reset layerHits and containedHits
173  layerHits = 0;
174  containedHits.clear();
175  for (VXDHoughState* hit : hits) {
176 
177  const VXDHoughState::DataCache& hitData = hit->getDataCache();
178  const double& m = hitData.xConformal;
179  const double& a = hitData.yConformal;
180 
181  const double derivativeyLeft = m * -sinLeft + a * cosLeft;
182  const double derivativeyRight = m * -sinRight + a * cosRight;
183  const double derivativeyCenter = m * -sinCenter + a * cosCenter;
184 
185  // Only interested in the rising arm of the sinosoidal curves.
186  // Thus if derivative on both sides of the cell is negative, ignore and continue.
187  if (derivativeyLeft < 0 and derivativeyRight < 0 and derivativeyCenter < 0) continue;
188 
189  const double yLeft = m * cosLeft + a * sinLeft;
190  const double yRight = m * cosRight + a * sinRight;
191  const double yCenter = m * cosCenter + a * sinCenter;
192 
193  /* Check if HS-parameter curve is inside (or outside) actual sub-HS */
194  if ((yLeft <= localUpperCoordinate and yRight >= localLowerCoordinate) or
195  (yCenter <= localUpperCoordinate and yLeft >= localLowerCoordinate and yRight >= localLowerCoordinate) or
196  (yCenter >= localLowerCoordinate and yLeft <= localUpperCoordinate and yRight <= localUpperCoordinate)) {
197  layerHits[hitData.layer] = true;
198  containedHits.emplace_back(hit);
199  }
200  }
201 
202  if (layerFilter(layerHits) > 0) {
203  // recursive call of fastInterceptFinder2d, until currentRecursion == m_maxRecursionLevel
204  if (currentRecursion < m_maxRecursionLevel) {
205  fastInterceptFinder2d(containedHits, left, right, lowerIndex, upperIndex, currentRecursion + 1);
206  } else {
207  m_activeSectors.insert({std::make_pair(localIndexX, localIndexY), std::make_pair(-layerFilter(layerHits), containedHits) });
208  }
209  }
210  }
211  }
212 }
213 
214 
216 {
217  m_clusterCount = 1;
218 
219  for (auto& currentCell : m_activeSectors) {
220 
221  // cell content meanings:
222  // -3, -4 : active sector, not yet visited
223  // 0 : non-active sector (will never be visited, only checked)
224  // 1,2,3...: index of the clusters
225  if (currentCell.second.first > -1) continue;
226 
227  m_clusterInitialPosition = std::make_pair(currentCell.first.first, currentCell.first.second);
228  m_clusterSize = 1;
229  currentCell.second.first = m_clusterCount;
230 
231  m_currentTrackCandidate.clear();
232  for (VXDHoughState* hit : currentCell.second.second) {
233  m_currentTrackCandidate.emplace_back(hit);
234  }
235 
236  // Check for HS sectors connected to each other which could form a cluster
237  DepthFirstSearch(currentCell.first.first, currentCell.first.second);
238  // if cluster valid (i.e. not too small and not too big): finalize!
240 
242  m_currentTrackCandidate.clear();
243  }
244  m_clusterCount++;
245  }
246 }
247 
248 void SingleHoughSpaceFastInterceptFinder::DepthFirstSearch(uint lastIndexX, uint lastIndexY)
249 {
250  if (m_clusterSize >= m_MaximumHSClusterSize) return;
251 
252  for (uint currentIndexY = lastIndexY; currentIndexY >= lastIndexY - 1; currentIndexY--) {
253  if (abs((int)m_clusterInitialPosition.second - (int)currentIndexY) >= m_MaximumHSClusterSizeY or
254  m_clusterSize >= m_MaximumHSClusterSize or currentIndexY > m_nVerticalSectors) return;
255  for (uint currentIndexX = lastIndexX; currentIndexX <= lastIndexX + 1; currentIndexX++) {
256  if (abs((int)m_clusterInitialPosition.first - (int)currentIndexX) >= m_MaximumHSClusterSizeX or
257  m_clusterSize >= m_MaximumHSClusterSize or currentIndexX > m_nAngleSectors) return;
258 
259  // The cell (currentIndexX, currentIndexY) is the current one has already been checked, so continue
260  if (lastIndexX == currentIndexX && lastIndexY == currentIndexY) continue;
261 
262  // first check bounds to avoid out-of-bound array access
263  // as they are uints, they are always >= 0, and in case of an overflow they would be too large
264  if (currentIndexX < m_nAngleSectors and currentIndexY < m_nVerticalSectors) {
265 
266  auto activeSector = m_activeSectors.find({currentIndexX, currentIndexY});
267  // Only continue searching if the current cluster is smaller than the maximum cluster size
268  if (activeSector != m_activeSectors.end() and activeSector->second.first < 0 /*and m_clusterSize < m_MaximumHSClusterSize*/) {
269  activeSector->second.first = m_clusterCount;
270  m_clusterSize++;
271 
272  // No need to check whether currentIndex exists as a key in m_activeSectors as they were created at the same time
273  // so it's certain the key exists.
274  for (VXDHoughState* hit : activeSector->second.second) {
275  if (not TrackFindingCDC::is_in(hit, m_currentTrackCandidate)) {
276  m_currentTrackCandidate.emplace_back(hit);
277  }
278  }
279 
280  // search in the next Hough Space cells...
281  DepthFirstSearch(currentIndexX, currentIndexY);
282  }
283  }
284  }
285  }
286 }
The Module parameter list class.
void initialize() override
Receive and dispatch signal before the start of the event processing.
virtual void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix)
Forward prefixed parameters of this findlet to the module parameter list.
Definition: Findlet.h:69
Interface for an algorithm part that needs to receive the module processing signals.
std::array< double, 16384 > m_HSCenterSinValuesLUT
sine values of the Hough Space sector center coordinates
uint m_nVerticalSectors
number of sectors of the Hough Space on the vertical axis
uint m_MinimumHSClusterSize
minimum cluster size of sectors belonging to intercepts in the Hough Space
std::array< double, 16384 > m_HSYCenterLUT
y values of the Hough Space sector centers
std::array< double, 16385 > m_HSYLUT
y values of the Hough Space sector boarders
std::array< double, 16384 > m_HSCenterCosValuesLUT
cosine values of the Hough Space sector center coordinates
std::map< std::pair< uint, uint >, std::pair< int, std::vector< VXDHoughState * > >, paircompare > m_activeSectors
Map containing only active HS sectors, i.e.
uint m_nAngleSectors
number of sectors of the Hough Space on the horizontal axis
std::array< double, 16385 > m_HSXLUT
x values of the Hough Space sector boarders
double m_minimumX
minimum x value of the Hough Space, defaults to the value for u-side
std::vector< std::vector< VXDHoughState * > > m_trackCandidates
vector containing track candidates, consisting of the found intersection values in the Hough Space
double m_verticalHoughSpaceSize
vertical size of the Hough Space, defaults to the value for u-side
unsigned short layerFilter(const std::bitset< 8 > &layer)
layer filter, checks if at least hits from 3 layers are in a set of hits
void DepthFirstSearch(uint lastIndexX, uint lastIndexY)
Perform depth first search recursive algorithm to find clusters in the Hough Space.
std::pair< uint, uint > m_clusterInitialPosition
start cell of the recursive cluster finding in the Hough Space
uint m_MaximumHSClusterSizeX
maximum cluster size in x of sectors belonging to intercepts in the Hough Space
void fastInterceptFinder2d(const std::vector< VXDHoughState * > &hits, uint xmin, uint xmax, uint ymin, uint ymax, uint currentRecursion)
find intercepts in the 2D Hough Space by recursively calling itself until no hits are assinged to a g...
std::array< double, 16385 > m_HSSinValuesLUT
Look-Up-Tables for values as cache to speed up calculation sine values of the Hough Space sector boar...
void apply(std::vector< VXDHoughState > &hits, std::vector< std::vector< VXDHoughState * >> &rawTrackCandidates) override
Load in the prepared hits and create track candidates for further processing like hit filtering and f...
std::vector< VXDHoughState * > m_currentTrackCandidate
the current track candidate
double m_maximumX
maximum x value of the Hough Space, defaults to the value for u-side
uint m_MaximumHSClusterSizeY
maximum cluster size in y of sectors belonging to intercepts in the Hough Space
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) override
Expose the parameters of the sub findlets.
uint m_MaximumHSClusterSize
maximum cluster size of sectors belonging to intercepts in the Hough Space
std::array< double, 16385 > m_HSCosValuesLUT
cosine values of the Hough Space sector boarder coordinates
std::array< double, 16384 > m_HSXCenterLUT
x values of the Hough Space sector centers
uint m_maxRecursionLevel
maximum number of recursive calls of FastInterceptFinder2d
Simple container for hit information to be used during intercept finding.
Definition: VXDHoughState.h:24
void addParameter(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module list.
Abstract base class for different kinds of events.
Cache containing the most important information of this state which will often be needed.
Definition: VXDHoughState.h:70
float yConformal
conformal transformed y coordinate of this hit
Definition: VXDHoughState.h:80
unsigned short layer
Geometrical Layer this state is based on.
Definition: VXDHoughState.h:96
float xConformal
conformal transformed x coordinate of this hit
Definition: VXDHoughState.h:78