Belle II Software development
QuadTreeProcessor< AX, AY, AData > Class Template Referenceabstract

This abstract class serves as a base class for all implementations of track processors. More...

#include <QuadTreeProcessor.h>

Public Types

using Item = QuadTreeItem<AData>
 The QuadTree will only see items of this type.
 
using QuadTree = QuadTreeNode<AX, AY, Item>
 The used QuadTree.
 
using XSpan = typename QuadTree::XSpan
 This pair describes the span in X for a node.
 
using YSpan = typename QuadTree::YSpan
 This pair describes the span in Y for a node.
 
using XYSpans = std::pair<XSpan, YSpan>
 This pair of spans describes the span of a node.
 
using QuadTreeChildren = typename QuadTree::Children
 Alias for the QuadTree Children.
 
using CandidateReceiver = std::function<void(const std::vector<AData*>&, QuadTree*)>
 This lambda function can be used for postprocessing.
 

Public Member Functions

 QuadTreeProcessor (int lastLevel, int seedLevel, const XYSpans &xySpans, bool debugOutput=false)
 Constructor is very simple.
 
virtual ~QuadTreeProcessor ()
 Destructor deletes the quad tree.
 
void clear ()
 Delete all the QuadTreeItems in the tree and clear the tree.
 
void seed (const std::vector< AData * > &datas)
 Fill in the items in the given vector.
 
std::vector< AData * > getAssignedItems ()
 Get items that have been assigned to the seed level The returned elements are unique even if items are assigned multiple times.
 
void fill (const CandidateReceiver &candidateReceiver, int nHitsThreshold)
 Start filling the already created tree.
 
void fill (const CandidateReceiver &candidateReceiver, int nHitsThreshold, float yLimit)
 Fill vector of QuadTree instances with hits.
 
virtual void afterFillDebugHook (QuadTreeChildren &children)
 Override that function if you want to receive debug output whenever the children of a node are filled the first time Maybe you want to make some nice plots or statistics.
 
const std::map< std::pair< AX, AY >, std::vector< Item * > > & getDebugInformation () const
 Return the debug information if collected.
 

Protected Member Functions

virtual XYSpans createChild (QuadTree *node, int iX, int iY) const
 Implement that function if you want to provide a new processor.
 
virtual bool isInNode (QuadTree *node, AData *item) const =0
 Implement that function if you want to provide a new processor.
 
virtual void insertItemsInNodes (const std::vector< QuadTree * > &nodes, const std::vector< Item * > &items)
 Insert each of the given items into every one of the given nodes it belongs to.
 
virtual bool isLeaf (QuadTree *node) const
 Function which checks if given node is leaf Implemented as virtual to keep possibility of changing lastLevel values depending on region is phase-space (i.e.
 
int getLastLevel () const
 Return the parameter last level.
 

Protected Attributes

std::unique_ptr< QuadTreem_quadTree
 The quad tree we work with.
 
std::deque< Itemm_items
 Storage space for the items that are referenced by the quad tree nodes.
 
std::vector< Item * > m_itemPtrs
 Reusable buffer with pointers to all items - used to seed the tree.
 
std::vector< QuadTree * > m_childPtrs
 Reusable buffer with pointers to the children of the node currently being filled.
 
std::vector< QuadTree * > m_seededTrees
 Vector of QuadTrees QuadTree instances (which are filled in the vector) cover the whole Legendre phase-space; each instance is processes independently.
 

Private Member Functions

void fillGivenTree (QuadTree *node, const CandidateReceiver &candidateReceiver, int nItemsThreshold, AY yLimit)
 Internal function to do the real quad tree search: fill the nodes, check which of the n*m bins we need to process further and go one level deeper.
 
void createChildren (QuadTree *node, QuadTreeChildren &m_children) const
 Creates the sub node of a given node.
 
void fillChildren (QuadTree *node, const std::vector< Item * > &items)
 This function is called by fillGivenTree and fills the items into the corresponding children.
 

Static Private Member Functions

static void callResultFunction (QuadTree *node, const CandidateReceiver &candidateReceiver)
 When a node is accepted as a result, we extract a vector with the items (back transformed to AData*) and pass it together with the result node to the candidate receiver function.
 

Private Attributes

int m_lastLevel
 The last level to be filled.
 
int m_seedLevel
 The first level to be filled, effectively skip forward to this higher granularity level.
 
bool m_debugOutput
 A flag to control the creation of the debug output.
 
std::map< std::pair< AX, AY >, std::vector< Item * > > m_debugOutputMap
 The calculated debug map.
 

Static Private Attributes

static const int c_maxNChildren = 16
 Upper bound on the number of children of a node - they are kept on the stack.
 

Detailed Description

template<typename AX, typename AY, class AData>
class Belle2::TrackFindingCDC::QuadTreeProcessor< AX, AY, AData >

This abstract class serves as a base class for all implementations of track processors.

It provides some functions to create, fill, clear and postprocess a quad tree. If you want to use your own class as a quad tree item, you have to overload this processor. You have provide only the two functions isInNode and createChild.

Definition at line 43 of file QuadTreeProcessor.h.

Member Typedef Documentation

◆ CandidateReceiver

template<typename AX, typename AY, class AData>
using CandidateReceiver = std::function<void(const std::vector<AData*>&, QuadTree*)>

This lambda function can be used for postprocessing.

Definition at line 69 of file QuadTreeProcessor.h.

◆ Item

template<typename AX, typename AY, class AData>
using Item = QuadTreeItem<AData>

The QuadTree will only see items of this type.

Definition at line 51 of file QuadTreeProcessor.h.

◆ QuadTree

template<typename AX, typename AY, class AData>
using QuadTree = QuadTreeNode<AX, AY, Item>

The used QuadTree.

Definition at line 54 of file QuadTreeProcessor.h.

◆ QuadTreeChildren

template<typename AX, typename AY, class AData>
using QuadTreeChildren = typename QuadTree::Children

Alias for the QuadTree Children.

Definition at line 66 of file QuadTreeProcessor.h.

◆ XSpan

template<typename AX, typename AY, class AData>
using XSpan = typename QuadTree::XSpan

This pair describes the span in X for a node.

Definition at line 57 of file QuadTreeProcessor.h.

◆ XYSpans

template<typename AX, typename AY, class AData>
using XYSpans = std::pair<XSpan, YSpan>

This pair of spans describes the span of a node.

Definition at line 63 of file QuadTreeProcessor.h.

◆ YSpan

template<typename AX, typename AY, class AData>
using YSpan = typename QuadTree::YSpan

This pair describes the span in Y for a node.

Definition at line 60 of file QuadTreeProcessor.h.

Constructor & Destructor Documentation

◆ QuadTreeProcessor()

template<typename AX, typename AY, class AData>
QuadTreeProcessor ( int lastLevel,
int seedLevel,
const XYSpans & xySpans,
bool debugOutput = false )
inline

Constructor is very simple.

The QuadTree has to be constructed elsewhere.

Parameters
lastLeveldescribing the last search level for the quad tree creation
seedLevelfirst level to be filled, effectively skip forward to this higher granularity level
xySpanspair of spans describing the span of a node
debugOutputenable debug output

Definition at line 79 of file QuadTreeProcessor.h.

83 : m_quadTree{std::make_unique<QuadTree>(xySpans.first, xySpans.second, 0, nullptr)}
84 , m_lastLevel(lastLevel)
85 , m_seedLevel(seedLevel)
86 , m_debugOutput(debugOutput)
87 , m_debugOutputMap()
88 {
89 }

◆ ~QuadTreeProcessor()

template<typename AX, typename AY, class AData>
virtual ~QuadTreeProcessor ( )
inlinevirtual

Destructor deletes the quad tree.

Definition at line 94 of file QuadTreeProcessor.h.

95 {
96 clear();
97 }

Member Function Documentation

◆ afterFillDebugHook()

template<typename AX, typename AY, class AData>
virtual void afterFillDebugHook ( QuadTreeChildren & children)
inlinevirtual

Override that function if you want to receive debug output whenever the children of a node are filled the first time Maybe you want to make some nice plots or statistics.

Definition at line 392 of file QuadTreeProcessor.h.

393 {
394 if (not m_debugOutput) return;
395 for (const QuadTree& childNode : children) {
396 if (childNode.getLevel() != getLastLevel()) continue; // Only write the lowest level
397 //m_debugOutputMap[ {childNode.getXMean(), childNode.getYMean()}] = childNode.getItems();
398 }
399 }

◆ callResultFunction()

template<typename AX, typename AY, class AData>
static void callResultFunction ( QuadTree * node,
const CandidateReceiver & candidateReceiver )
inlinestaticprivate

When a node is accepted as a result, we extract a vector with the items (back transformed to AData*) and pass it together with the result node to the candidate receiver function.

Definition at line 301 of file QuadTreeProcessor.h.

302 {
303 const std::vector<Item*>& foundItems = node->getItems();
304 std::vector<AData*> candidate;
305 candidate.reserve(foundItems.size());
306
307 for (Item* item : foundItems) {
308 item->setUsedFlag();
309 candidate.push_back(item->getPointer());
310 }
311
312 candidateReceiver(candidate, node);
313 }

◆ clear()

template<typename AX, typename AY, class AData>
void clear ( )
inline

Delete all the QuadTreeItems in the tree and clear the tree.

Definition at line 102 of file QuadTreeProcessor.h.

103 {
104 m_seededTrees.clear();
105 m_quadTree->clearChildren();
106 m_quadTree->clearItems();
107 m_items.clear();
108 }

◆ createChild()

template<typename AX, typename AY, class AData>
virtual XYSpans createChild ( QuadTree * node,
int iX,
int iY ) const
inlineprotectedvirtual

Implement that function if you want to provide a new processor.

It decides which node-spans the n * m children of the node should have. It is called when creating the nodes. The two indices iX and iY tell you where the new node will be created (as node.children[iX][iY]). You can check some information on the level or the x- or y-values by using the methods implemented for node.

Returns
a XYSpan pair of a x- and a y-span that the new child should have. If you don nt want to provide custom spans, just return XYSpans(XSpan(node->getXBinBound(iX), node->getXBinBound(iX + 1)), YSpan(node->getYBinBound(iY), node->getYBinBound(iY + 1)));

Definition at line 324 of file QuadTreeProcessor.h.

325 {
326 AX xMin = node->getXLowerBound(iX);
327 AX xMax = node->getXUpperBound(iX);
328 AY yMin = node->getYLowerBound(iY);
329 AY yMax = node->getYUpperBound(iY);
330 return XYSpans({xMin, xMax}, {yMin, yMax});
331 }

◆ createChildren()

template<typename AX, typename AY, class AData>
void createChildren ( QuadTree * node,
QuadTreeChildren & m_children ) const
inlineprivate

Creates the sub node of a given node.

This function is called by fillGivenTree. To calculate the spans of the children nodes the user-defined function createChiildWithParent is used.

Definition at line 264 of file QuadTreeProcessor.h.

265 {
266 m_children.reserve(node->getXNbins() * node->getYNbins());
267 for (int i = 0; i < node->getXNbins(); ++i) {
268 for (int j = 0; j < node->getYNbins(); ++j) {
269 const XYSpans& xySpans = createChild(node, i, j);
270 const XSpan& xSpan = xySpans.first;
271 const YSpan& ySpan = xySpans.second;
272 m_children.push_back(QuadTree(xSpan, ySpan, node->getLevel() + 1, node));
273 }
274 }
275 }

◆ fill() [1/2]

template<typename AX, typename AY, class AData>
void fill ( const CandidateReceiver & candidateReceiver,
int nHitsThreshold )
inline

Start filling the already created tree.

Parameters
candidateReceiverthe lambda function to call after a node was selected
nHitsThresholdthe threshold on the number of items

Definition at line 179 of file QuadTreeProcessor.h.

180 {
181 fill(candidateReceiver, nHitsThreshold, std::numeric_limits<AY>::max());
182 }

◆ fill() [2/2]

template<typename AX, typename AY, class AData>
void fill ( const CandidateReceiver & candidateReceiver,
int nHitsThreshold,
float yLimit )
inline

Fill vector of QuadTree instances with hits.

Parameters
candidateReceiverthe lambda function to call after a node was selected
nHitsThresholdthe threshold on the number of items
yLimitthe threshold in the rho (curvature) variable

Definition at line 190 of file QuadTreeProcessor.h.

191 {
192 std::vector<QuadTree*> quadTrees = m_seededTrees;
193 std::sort(quadTrees.begin(), quadTrees.end(), [](const QuadTree * quadTree1, const QuadTree * quadTree2) {
194 return quadTree1->getNItems() > quadTree2->getNItems();
195 });
196
197 for (QuadTree* tree : quadTrees) {
198 erase_remove_if(tree->getItems(), [](Item * hit) { return hit->isUsed(); });
199 fillGivenTree(tree, candidateReceiver, nHitsThreshold, yLimit);
200 }
201 }

◆ fillChildren()

template<typename AX, typename AY, class AData>
void fillChildren ( QuadTree * node,
const std::vector< Item * > & items )
inlineprivate

This function is called by fillGivenTree and fills the items into the corresponding children.

For this the user-defined method isInNode is called.

Definition at line 281 of file QuadTreeProcessor.h.

282 {
283 // An item can be inserted into each child at most once
284 const size_t neededSize = items.size();
285 m_childPtrs.clear();
286 m_childPtrs.reserve(node->getChildren().size());
287 for (QuadTree& child : node->getChildren()) {
288 child.reserveItems(neededSize);
289 m_childPtrs.push_back(&child);
290 }
291
292 this->insertItemsInNodes(m_childPtrs, items);
293
294 afterFillDebugHook(node->getChildren());
295 }

◆ fillGivenTree()

template<typename AX, typename AY, class AData>
void fillGivenTree ( QuadTree * node,
const CandidateReceiver & candidateReceiver,
int nItemsThreshold,
AY yLimit )
inlineprivate

Internal function to do the real quad tree search: fill the nodes, check which of the n*m bins we need to process further and go one level deeper.

Definition at line 208 of file QuadTreeProcessor.h.

212 {
213 if (node->getNItems() < nItemsThreshold) {
214 return;
215 }
216
217 if ((node->getYMin() > yLimit) or (-node->getYMax() > yLimit)) {
218 return;
219 }
220
221 if (isLeaf(node)) {
222 callResultFunction(node, candidateReceiver);
223 return;
224 }
225
226 if (node->getChildren().empty()) {
227 this->createChildren(node, node->getChildren());
228 }
229
230 if (!node->checkFilled()) {
231 fillChildren(node, node->getItems());
232 node->setFilled();
233 }
234
235 // Kept on the stack - this function is called millions of times per event
236 std::array<QuadTree*, c_maxNChildren> children;
237 int nChildren = 0;
238 for (QuadTree& child : node->getChildren()) {
239 B2ASSERT("More children than the quad tree processor supports", nChildren < c_maxNChildren);
240 children[nChildren++] = &child;
241 }
242 const auto compareNItems = [](const QuadTree * lhs, const QuadTree * rhs) {
243 return lhs->getNItems() < rhs->getNItems();
244 };
245
246 // Explicitly count down the children
247 for (int nRemaining = nChildren; nRemaining > 0; --nRemaining) {
248 auto itHeaviestChild =
249 std::max_element(children.begin(), children.begin() + nRemaining, compareNItems);
250 QuadTree* heaviestChild = *itHeaviestChild;
251 // Drop the heaviest child from the list keeping the order of the remaining ones
252 std::move(itHeaviestChild + 1, children.begin() + nRemaining, itHeaviestChild);
253 // After we have processed some children we need to get rid of the already used hits in all the children,
254 // because this can change the number of items drastically
255 erase_remove_if(heaviestChild->getItems(), [&](Item * hit) { return hit->isUsed(); });
256 this->fillGivenTree(heaviestChild, candidateReceiver, nItemsThreshold, yLimit);
257 }
258 }

◆ getAssignedItems()

template<typename AX, typename AY, class AData>
std::vector< AData * > getAssignedItems ( )
inline

Get items that have been assigned to the seed level The returned elements are unique even if items are assigned multiple times.

Definition at line 160 of file QuadTreeProcessor.h.

161 {
162 std::vector<const TrackingUtilities::CDCWireHit*> result;
163 for (QuadTree* seededTree : m_seededTrees) {
164 for (Item* item : seededTree->getItems()) {
165 result.push_back(item->getPointer());
166 }
167 }
168 std::sort(result.begin(), result.end());
169 result.erase(std::unique(result.begin(), result.end()), result.end());
170 return result;
171 }

◆ getDebugInformation()

template<typename AX, typename AY, class AData>
const std::map< std::pair< AX, AY >, std::vector< Item * > > & getDebugInformation ( ) const
inline

Return the debug information if collected.

Definition at line 404 of file QuadTreeProcessor.h.

405 {
406 return m_debugOutputMap;
407 }

◆ getLastLevel()

template<typename AX, typename AY, class AData>
int getLastLevel ( ) const
inlineprotected

Return the parameter last level.

Definition at line 382 of file QuadTreeProcessor.h.

383 {
384 return m_lastLevel;
385 }

◆ insertItemsInNodes()

template<typename AX, typename AY, class AData>
virtual void insertItemsInNodes ( const std::vector< QuadTree * > & nodes,
const std::vector< Item * > & items )
inlineprotectedvirtual

Insert each of the given items into every one of the given nodes it belongs to.

The default implementation simply asks isInNode for each item and node pair. Processors may override it to share the parts of the containment check that only depend on the item or on a part of the node geometry over the given set of nodes. Any implementation has to insert the items into each node in the order in which they appear in the given item range.

Definition at line 351 of file QuadTreeProcessor.h.

353 {
354 for (Item* item : items) {
355 if (item->isUsed()) continue;
356
357 for (QuadTree* node : nodes) {
358 if (isInNode(node, item->getPointer())) {
359 node->insertItem(item);
360 }
361 }
362 }
363 }

◆ isInNode()

template<typename AX, typename AY, class AData>
virtual bool isInNode ( QuadTree * node,
AData * item ) const
protectedpure virtual

Implement that function if you want to provide a new processor.

It is called when filling the quad tree after creation. For every item in a node and every child node this function gets called and should decide, if the item should go into this child node or not.

Parameters
nodechild node
itemitem to be filled into the child node or not
Returns
true if this item belongs into this node.

◆ isLeaf()

template<typename AX, typename AY, class AData>
virtual bool isLeaf ( QuadTree * node) const
inlineprotectedvirtual

Function which checks if given node is leaf Implemented as virtual to keep possibility of changing lastLevel values depending on region is phase-space (i.e.

setting lastLevel as a function of Y-variable)

Definition at line 370 of file QuadTreeProcessor.h.

371 {
372 if (node->getLevel() >= m_lastLevel) {
373 return true;
374 } else {
375 return false;
376 }
377 }

◆ seed()

template<typename AX, typename AY, class AData>
void seed ( const std::vector< AData * > & datas)
inline

Fill in the items in the given vector.

They are transformed to QuadTreeItems internally.

Definition at line 113 of file QuadTreeProcessor.h.

114 {
115 // Create the items
116 for (AData* data : datas) {
117 m_items.emplace_back(data);
118 }
119
120 // Creating the seed level
121 long nSeedBins = pow(2, m_seedLevel);
122 m_seededTrees.reserve(nSeedBins * nSeedBins);
123
124 // Expand the first levels to the seed sectors
125 m_seededTrees.push_back(m_quadTree.get());
126 std::vector<QuadTree*> nextSeededTrees;
127
128 for (int level = 0; level < m_seedLevel; ++level) {
129 for (QuadTree* node : m_seededTrees) {
130 if (node->getChildren().empty()) {
131 this->createChildren(node, node->getChildren());
132 }
133 for (QuadTree& child : node->getChildren()) {
134 nextSeededTrees.push_back(&child);
135 }
136 }
137 std::swap(nextSeededTrees, m_seededTrees);
138 nextSeededTrees.clear();
139 }
140
141 // Fill the seed level with the items
142 m_itemPtrs.clear();
143 m_itemPtrs.reserve(m_items.size());
144 for (Item& item : m_items) {
145 m_itemPtrs.push_back(&item);
146 }
147
148 for (QuadTree* seededTree : m_seededTrees) {
149 seededTree->reserveItems(m_items.size());
150 }
151
152 this->insertItemsInNodes(m_seededTrees, m_itemPtrs);
153 }

Member Data Documentation

◆ c_maxNChildren

template<typename AX, typename AY, class AData>
const int c_maxNChildren = 16
staticprivate

Upper bound on the number of children of a node - they are kept on the stack.

Definition at line 47 of file QuadTreeProcessor.h.

◆ m_childPtrs

template<typename AX, typename AY, class AData>
std::vector<QuadTree*> m_childPtrs
protected

Reusable buffer with pointers to the children of the node currently being filled.

Definition at line 420 of file QuadTreeProcessor.h.

◆ m_debugOutput

template<typename AX, typename AY, class AData>
bool m_debugOutput
private

A flag to control the creation of the debug output.

Definition at line 437 of file QuadTreeProcessor.h.

◆ m_debugOutputMap

template<typename AX, typename AY, class AData>
std::map<std::pair<AX, AY>, std::vector<Item*> > m_debugOutputMap
private

The calculated debug map.

Definition at line 440 of file QuadTreeProcessor.h.

◆ m_itemPtrs

template<typename AX, typename AY, class AData>
std::vector<Item*> m_itemPtrs
protected

Reusable buffer with pointers to all items - used to seed the tree.

Definition at line 417 of file QuadTreeProcessor.h.

◆ m_items

template<typename AX, typename AY, class AData>
std::deque<Item> m_items
protected

Storage space for the items that are referenced by the quad tree nodes.

Definition at line 414 of file QuadTreeProcessor.h.

◆ m_lastLevel

template<typename AX, typename AY, class AData>
int m_lastLevel
private

The last level to be filled.

Definition at line 431 of file QuadTreeProcessor.h.

◆ m_quadTree

template<typename AX, typename AY, class AData>
std::unique_ptr<QuadTree> m_quadTree
protected

The quad tree we work with.

Definition at line 411 of file QuadTreeProcessor.h.

◆ m_seededTrees

template<typename AX, typename AY, class AData>
std::vector<QuadTree*> m_seededTrees
protected

Vector of QuadTrees QuadTree instances (which are filled in the vector) cover the whole Legendre phase-space; each instance is processes independently.

Definition at line 427 of file QuadTreeProcessor.h.

◆ m_seedLevel

template<typename AX, typename AY, class AData>
int m_seedLevel
private

The first level to be filled, effectively skip forward to this higher granularity level.

Definition at line 434 of file QuadTreeProcessor.h.


The documentation for this class was generated from the following file: