Belle II Software  release-06-01-15
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_param_maxRecursionLevel,
31  "Maximum recursion level for the fast Hough trafo algorithm.", m_param_maxRecursionLevel);
32 
33  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "nAngleSectors"), m_param_nAngleSectors,
34  "Number of angle sectors (= x-axis) dividing the Hough space.", m_param_nAngleSectors);
35 
36  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "nVerticalSectors"), m_param_nVerticalSectors,
37  "Number of vertical sectors (= y-axis) dividing the Hough space.", m_param_nVerticalSectors);
38 
39  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "verticalHoughSpaceSize"), m_param_verticalHoughSpaceSize,
40  "Vertical size of the Hough space.", m_param_verticalHoughSpaceSize);
41 
42  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "HoughSpaceMinimumX"), m_param_minimumX,
43  "Minimum x value of the Hough space.", m_param_minimumX);
44 
45  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "HoughSpaceMaximumX"), m_param_maximumX,
46  "Maximum x value of the Hough space.", m_param_maximumX);
47 
48  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "minimumHSClusterSize"), m_param_MinimumHSClusterSize,
49  "Maximum x value of the Hough space.", m_param_MinimumHSClusterSize);
50 
51  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumHSClusterSize"), m_param_MaximumHSClusterSize,
52  "Maximum x value of the Hough space.", m_param_MaximumHSClusterSize);
53 
54  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumHSClusterSizeX"), m_param_MaximumHSClusterSizeX,
55  "Maximum x value of the Hough space.", m_param_MaximumHSClusterSizeX);
56 
57  moduleParamList->addParameter(TrackFindingCDC::prefixed(prefix, "maximumHSClusterSizeY"), m_param_MaximumHSClusterSizeY,
58  "Maximum x value of the Hough space.", m_param_MaximumHSClusterSizeY);
59 
60 }
61 
63 {
65 
67  B2ASSERT("The maximum number of recursions (maximumRecursionLevel) must not be larger than 14, but it is " <<
69  ", please choose a smaller value for maximumRecursionLevel, and / or for nAngleSectors and / or nVerticalSectors.",
72  for (uint i = 0; i < m_param_nAngleSectors; i++) {
73  double x = m_param_minimumX + m_unitX * (double)i;
74  double xc = x + 0.5 * m_unitX;
75 
76  m_HSXLUT[i] = x;
77  m_HSSinValuesLUT[i] = sin(x);
78  m_HSCosValuesLUT[i] = cos(x);
79  m_HSCenterSinValuesLUT[i] = sin(xc);
80  m_HSCenterCosValuesLUT[i] = cos(xc);
81  m_HSXCenterLUT[i] = xc;
82  }
86 
88  for (uint i = 0; i <= m_param_nVerticalSectors; i++) {
91  }
92  B2DEBUG(29, "HS size x: " << (m_param_maximumX - m_param_minimumX) << " HS size y: " << m_param_verticalHoughSpaceSize <<
93  " unitX: " << m_unitX << " unitY: " << m_unitY);
94 }
95 
96 
97 void SingleHoughSpaceFastInterceptFinder::apply(std::vector<VXDHoughState>& hits,
98  std::vector<std::vector<VXDHoughState*>>& rawTrackCandidates)
99 {
100  m_trackCandidates.clear();
101  m_activeSectors.clear();
102 
103  const std::vector<VXDHoughState*> currentEventHitList = TrackFindingCDC::as_pointers<VXDHoughState>(hits);
104 
106 
108 
109  for (auto& trackCand : m_trackCandidates) {
110  // sort for layer, and 2D radius in case of same layer before storing as SpacePointTrackCand
111  // outer hit goes first, as later on tracks are build from outside to inside
112  std::sort(trackCand.begin(), trackCand.end(),
113  [](const VXDHoughState * a, const VXDHoughState * b) {
114  return
115  (a->getDataCache().layer > b->getDataCache().layer) or
116  (a->getDataCache().layer == b->getDataCache().layer
117  and a->getHit()->getPosition().Perp() > b->getHit()->getPosition().Perp());
118  });
119 
120  rawTrackCandidates.emplace_back(trackCand);
121  }
122 
123  B2DEBUG(29, "m_trackCandidates.size: " << m_trackCandidates.size());
124 
125 }
126 
127 
128 void SingleHoughSpaceFastInterceptFinder::fastInterceptFinder2d(const std::vector<VXDHoughState*>& hits, uint xmin, uint xmax,
129  uint ymin,
130  uint ymax, uint currentRecursion)
131 {
132  std::vector<VXDHoughState*> containedHits;
133  containedHits.reserve(hits.size());
134  std::bitset<8> layerHits; /* For layer filter */
135 
136  if (currentRecursion == m_param_maxRecursionLevel + 1) return;
137 
138  // these int-divisions can cause {min, center} or {center, max} to be the same, which is a desired behaviour
139  const uint centerx = xmin + (uint)((xmax - xmin) / 2);
140  const uint centery = ymin + (uint)((ymax - ymin) / 2);
141  const uint xIndexCache[3] = {xmin, centerx, xmax};
142  const uint yIndexCache[3] = {ymin, centery, ymax};
143 
144  for (int i = 0; i < 2 ; ++i) {
145  const uint left = xIndexCache[i];
146  const uint right = xIndexCache[i + 1];
147  const uint localIndexX = left;
148 
149  if (left == right) continue;
150 
151  const double& sinLeft = m_HSSinValuesLUT[left];
152  const double& cosLeft = m_HSCosValuesLUT[left];
153  const double& sinRight = m_HSSinValuesLUT[right];
154  const double& cosRight = m_HSCosValuesLUT[right];
155 
156  // the sin and cos of the current center can't be stored in a LUT, as the number of possible centers
157  // is quite large and the logic would become rather complex
158  const double sinCenter = m_HSCenterSinValuesLUT[(left + right) / 2];
159  const double cosCenter = m_HSCenterCosValuesLUT[(left + right) / 2];
160 
161  for (int j = 0; j < 2; ++j) {
162  const uint lowerIndex = yIndexCache[j];
163  const uint upperIndex = yIndexCache[j + 1];
164 
165  if (lowerIndex == upperIndex) continue;
166 
167  const uint localIndexY = lowerIndex;
168  const double& localUpperCoordinate = m_HSYLUT[lowerIndex];
169  const double& localLowerCoordinate = m_HSYLUT[upperIndex];
170 
171  // reset layerHits and containedHits
172  layerHits = 0;
173  containedHits.clear();
174  for (VXDHoughState* hit : hits) {
175 
176  const VXDHoughState::DataCache& hitData = hit->getDataCache();
177  const double& m = hitData.xConformal;
178  const double& a = hitData.yConformal;
179 
180  const double derivativeyLeft = m * -sinLeft + a * cosLeft;
181  const double derivativeyRight = m * -sinRight + a * cosRight;
182  const double derivativeyCenter = m * -sinCenter + a * cosCenter;
183 
184  // Only interested in the rising arm of the sinosoidal curves.
185  // Thus if derivative on both sides of the cell is negative, ignore and continue.
186  if (derivativeyLeft < 0 and derivativeyRight < 0 and derivativeyCenter < 0) continue;
187 
188  const double yLeft = m * cosLeft + a * sinLeft;
189  const double yRight = m * cosRight + a * sinRight;
190  const double yCenter = m * cosCenter + a * sinCenter;
191 
192  /* Check if HS-parameter curve is inside (or outside) actual sub-HS */
193  if ((yLeft <= localUpperCoordinate and yRight >= localLowerCoordinate) or
194  (yCenter <= localUpperCoordinate and yLeft >= localLowerCoordinate and yRight >= localLowerCoordinate) or
195  (yCenter >= localLowerCoordinate and yLeft <= localUpperCoordinate and yRight <= localUpperCoordinate)) {
196  layerHits[hitData.layer] = true;
197  containedHits.emplace_back(hit);
198  }
199  }
200 
201  if (layerFilter(layerHits) > 0) {
202  // recursive call of fastInterceptFinder2d, until currentRecursion == m_param_maxRecursionLevel
203  if (currentRecursion < m_param_maxRecursionLevel) {
204  fastInterceptFinder2d(containedHits, left, right, lowerIndex, upperIndex, currentRecursion + 1);
205  } else {
206  m_activeSectors.insert({std::make_pair(localIndexX, localIndexY), std::make_pair(-layerFilter(layerHits), containedHits) });
207  }
208  }
209  }
210  }
211 }
212 
213 
215 {
216  m_clusterCount = 1;
217 
218  for (auto& currentCell : m_activeSectors) {
219 
220  // cell content meanings:
221  // -3, -4 : active sector, not yet visited
222  // 0 : non-active sector (will never be visited, only checked)
223  // 1,2,3...: index of the clusters
224  if (currentCell.second.first > -1) continue;
225 
226  m_clusterInitialPosition = std::make_pair(currentCell.first.first, currentCell.first.second);
227  m_clusterSize = 1;
228  currentCell.second.first = m_clusterCount;
229 
230  m_currentTrackCandidate.clear();
231  for (VXDHoughState* hit : currentCell.second.second) {
232  m_currentTrackCandidate.emplace_back(hit);
233  }
234 
235  // Check for HS sectors connected to each other which could form a cluster
236  DepthFirstSearch(currentCell.first.first, currentCell.first.second);
237  // if cluster valid (i.e. not too small and not too big): finalize!
239 
241  m_currentTrackCandidate.clear();
242  }
243  m_clusterCount++;
244  }
245 }
246 
247 void SingleHoughSpaceFastInterceptFinder::DepthFirstSearch(uint lastIndexX, uint lastIndexY)
248 {
250 
251  for (uint currentIndexY = lastIndexY; currentIndexY >= lastIndexY - 1; currentIndexY--) {
252  if (abs((int)m_clusterInitialPosition.second - (int)currentIndexY) >= m_param_MaximumHSClusterSizeY or
254  for (uint currentIndexX = lastIndexX; currentIndexX <= lastIndexX + 1; currentIndexX++) {
255  if (abs((int)m_clusterInitialPosition.first - (int)currentIndexX) >= m_param_MaximumHSClusterSizeX or
257 
258  // The cell (currentIndexX, currentIndexY) is the current one has already been checked, so continue
259  if (lastIndexX == currentIndexX && lastIndexY == currentIndexY) continue;
260 
261  // first check bounds to avoid out-of-bound array access
262  // as they are uints, they are always >= 0, and in case of an overflow they would be too large
263  if (currentIndexX < m_param_nAngleSectors and currentIndexY < m_param_nVerticalSectors) {
264 
265  auto activeSector = m_activeSectors.find({currentIndexX, currentIndexY});
266  // Only continue searching if the current cluster is smaller than the maximum cluster size
267  if (activeSector != m_activeSectors.end() and activeSector->second.first < 0 /*and m_clusterSize < m_param_MaximumHSClusterSize*/) {
268  activeSector->second.first = m_clusterCount;
269  m_clusterSize++;
270 
271  // No need to check whether currentIndex exists as a key in m_activeSectors as they were created at the same time
272  // so it's certain the key exists.
273  for (VXDHoughState* hit : activeSector->second.second) {
274  if (not TrackFindingCDC::is_in(hit, m_currentTrackCandidate)) {
275  m_currentTrackCandidate.emplace_back(hit);
276  }
277  }
278 
279  // search in the next Hough Space cells...
280  DepthFirstSearch(currentIndexX, currentIndexY);
281  }
282  }
283  }
284  }
285 }
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_param_MinimumHSClusterSize
minimum cluster size of sectors belonging to intercepts in the Hough Space
unsigned short layerFilter(std::bitset< 8 > &layer)
layer filter, checks if at least hits from 3 layers are in a set of hits
double m_param_maximumX
maximum x value of the Hough Space, defaults to the value for u-side
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.
std::array< double, 16385 > m_HSXLUT
x values of the Hough Space sector boarders
std::vector< std::vector< VXDHoughState * > > m_trackCandidates
vector containing track candidates, consisting of the found intersection values in the Hough Space
uint m_param_nVerticalSectors
number of sectors of the Hough Space on the vertical axis
void DepthFirstSearch(uint lastIndexX, uint lastIndexY)
Perform depth first search recursive algorithm to find clusters in the Hough Space.
uint m_param_maxRecursionLevel
maximum number of recursive calls of fastInterceptFinder2d
std::pair< uint, uint > m_clusterInitialPosition
start cell of the recursive cluster finding 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...
double m_param_minimumX
minimum x value of the Hough Space, defaults to the value for u-side
uint m_param_nAngleSectors
number of sectors of the Hough Space on the horizontal axis
double m_param_verticalHoughSpaceSize
vertical size of the Hough Space, defaults to the value for u-side
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...
uint m_param_MaximumHSClusterSizeX
maximum cluster size in x of sectors belonging to intercepts in the Hough Space
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...
uint m_param_MaximumHSClusterSize
maximum cluster size of sectors belonging to intercepts in the Hough Space
std::vector< VXDHoughState * > m_currentTrackCandidate
the current track candidate
void exposeParameters(ModuleParamList *moduleParamList, const std::string &prefix) override
Expose the parameters of the sub findlets.
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_param_MaximumHSClusterSizeY
maximum cluster size in y of sectors belonging to intercepts in the Hough Space
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