Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
TransverseAssociationAlgorithm.cc
Go to the documentation of this file.
1
10
12
14
16
17using namespace pandora;
18
19namespace lar_content
20{
21
23 m_firstLengthCut(1.5f),
24 m_secondLengthCut(7.5f),
25 m_clusterWindow(3.f),
26 m_clusterAngle(45.f),
27 m_clusterCosAngle(std::cos(m_clusterAngle * M_PI / 180.f)),
28 m_clusterTanAngle(std::tan(m_clusterAngle * M_PI / 180.f)),
29 m_maxTransverseOverlap(0.5f),
30 m_maxProjectedOverlap(1.f),
31 m_maxLongitudinalOverlap(1.5f),
32 m_transverseClusterMinCosTheta(0.866f),
33 m_transverseClusterMinLength(0.5f),
34 m_transverseClusterMaxDisplacement(1.5f),
35 m_searchRegionX(3.5f),
36 m_searchRegionZ(2.f)
37{
38}
39
40//------------------------------------------------------------------------------------------------------------------------------------------
41
42void TransverseAssociationAlgorithm::GetListOfCleanClusters(const ClusterList *const pClusterList, ClusterVector &clusterVector) const
43{
44 clusterVector.clear();
45 clusterVector.insert(clusterVector.begin(), pClusterList->begin(), pClusterList->end());
46 std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
47}
48
49//------------------------------------------------------------------------------------------------------------------------------------------
50
52{
53 TransverseClusterList transverseClusterList;
54
55 try
56 {
57 ClusterToClustersMap nearbyClusters;
58 this->GetNearbyClusterMap(allClusters, nearbyClusters);
59
60 if (nearbyClusters.empty())
61 return;
62
63 // Step 1: Sort the input clusters into sub-samples
64 // (a) shortClusters: below first length cut
65 // (b) mediumClusters: between first and second length cuts (separated into transverse and longitudinal)
66 // (c) longClusters: above second length cut
67 ClusterVector shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters;
68 this->SortInputClusters(allClusters, shortClusters, transverseMediumClusters, longitudinalMediumClusters, longClusters);
69
70 ClusterVector transverseClusters(shortClusters.begin(), shortClusters.end());
71 transverseClusters.insert(transverseClusters.end(), transverseMediumClusters.begin(), transverseMediumClusters.end());
72
73 ClusterVector establishedClusters(transverseMediumClusters.begin(), transverseMediumClusters.end());
74 establishedClusters.insert(establishedClusters.end(), longitudinalMediumClusters.begin(), longitudinalMediumClusters.end());
75 establishedClusters.insert(establishedClusters.end(), longClusters.begin(), longClusters.end());
76
77 // Step 2: Form loose transverse associations between short clusters,
78 // without hopping over any established clusters
79 ClusterAssociationMap firstAssociationMap;
80 this->FillReducedAssociationMap(nearbyClusters, shortClusters, establishedClusters, firstAssociationMap);
81
82 // Step 3: Form transverse cluster objects. Basically, try to assign a direction to each
83 // of the clusters in the 'transverseClusters' list. For the short clusters in
84 // this list, the direction is obtained from a straight line fit to its associated
85 // clusters as selected in the previous step.
86 this->FillTransverseClusterList(nearbyClusters, transverseClusters, firstAssociationMap, transverseClusterList);
87
88 // Step 4: Form loose transverse associations between transverse clusters
89 // (First, associate medium clusters, without hopping over long clusters
90 // Next, associate all transverse clusters, without hopping over any clusters)
91 ClusterAssociationMap secondAssociationMap;
92 this->FillReducedAssociationMap(nearbyClusters, transverseMediumClusters, longClusters, secondAssociationMap);
93 this->FillReducedAssociationMap(nearbyClusters, transverseClusters, allClusters, secondAssociationMap);
94
95 // Step 5: Form associations between transverse cluster objects
96 // (These transverse associations must already exist as loose associations
97 // between transverse clusters as identified in the previous step).
98 ClusterAssociationMap transverseAssociationMap;
99 this->FillTransverseAssociationMap(nearbyClusters, transverseClusterList, secondAssociationMap, transverseAssociationMap);
100
101 // Step 6: Finalise the forward/backward transverse associations by symmetrising the
102 // transverse association map and removing any double-counting
103 this->FinalizeClusterAssociationMap(transverseAssociationMap, clusterAssociationMap);
104 }
105 catch (StatusCodeException &statusCodeException)
106 {
107 std::cout << "TransverseAssociationAlgorithm: exception " << statusCodeException.ToString() << std::endl;
108 }
109
110 for (TransverseClusterList::const_iterator iter = transverseClusterList.begin(), iterEnd = transverseClusterList.end(); iter != iterEnd; ++iter)
111 {
112 delete *iter;
113 }
114}
115
116//------------------------------------------------------------------------------------------------------------------------------------------
117
119{
120 HitToClusterMap hitToClusterMap;
121 CaloHitList allCaloHits;
122
123 for (const Cluster *const pCluster : allClusters)
124 {
125 CaloHitList daughterHits;
126 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
127 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
128
129 for (const CaloHit *const pCaloHit : daughterHits)
130 (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
131 }
132
133 HitKDTree2D kdTree;
134 HitKDNode2DList hitKDNode2DList;
135
136 KDTreeBox hitsBoundingRegion2D(fill_and_bound_2d_kd_tree(allCaloHits, hitKDNode2DList));
137 kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
138
139 for (const Cluster *const pCluster : allClusters)
140 {
141 CaloHitList daughterHits;
142 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
143
144 for (const CaloHit *const pCaloHit : daughterHits)
145 {
147
148 HitKDNode2DList found;
149 kdTree.search(searchRegionHits, found);
150
151 for (const auto &hit : found)
152 (void)nearbyClusters[pCluster].insert(hitToClusterMap.at(hit.data));
153 }
154 }
155}
156
157//------------------------------------------------------------------------------------------------------------------------------------------
158
160 ClusterVector &transverseMediumVector, ClusterVector &longitudinalMediumVector, ClusterVector &longVector) const
161{
162 for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
163 {
164 const Cluster *const pCluster = *iter;
165
166 const float clusterLengthT(this->GetTransverseSpan(pCluster));
167 const float clusterLengthL(this->GetLongitudinalSpan(pCluster));
168 const float clusterLengthSquared(clusterLengthT * clusterLengthT + clusterLengthL * clusterLengthL);
169
170 if (clusterLengthSquared < m_firstLengthCut * m_firstLengthCut)
171 {
172 shortVector.push_back(pCluster);
173 }
174 else if (clusterLengthSquared < m_secondLengthCut * m_secondLengthCut)
175 {
176 if (clusterLengthL < clusterLengthT * std::fabs(m_clusterTanAngle))
177 transverseMediumVector.push_back(pCluster);
178 else
179 longitudinalMediumVector.push_back(pCluster);
180 }
181 else
182 {
183 longVector.push_back(pCluster);
184 }
185 }
186
187 std::sort(shortVector.begin(), shortVector.end(), LArClusterHelper::SortByNHits);
188 std::sort(transverseMediumVector.begin(), transverseMediumVector.end(), LArClusterHelper::SortByNHits);
189 std::sort(longitudinalMediumVector.begin(), longitudinalMediumVector.end(), LArClusterHelper::SortByNHits);
190 std::sort(longVector.begin(), longVector.end(), LArClusterHelper::SortByNHits);
191}
192
193//------------------------------------------------------------------------------------------------------------------------------------------
194
196 const ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
197{
198 // To build a 'reduced' association map, form associations between clusters in the first cluster vector,
199 // but prevent these associations from hopping over any clusters in the second cluster vector.
200 // i.e. A->B from the first vector is forbidden if A->C->B exists with C from the second vector
201
202 ClusterAssociationMap firstAssociationMap, firstAssociationMapSwapped;
203 ClusterAssociationMap secondAssociationMap, secondAssociationMapSwapped;
204
205 this->FillAssociationMap(nearbyClusters, firstVector, firstVector, firstAssociationMap, firstAssociationMapSwapped);
206 this->FillAssociationMap(nearbyClusters, firstVector, secondVector, secondAssociationMap, secondAssociationMapSwapped);
207 this->FillReducedAssociationMap(firstAssociationMap, secondAssociationMap, secondAssociationMapSwapped, clusterAssociationMap);
208}
209
210//------------------------------------------------------------------------------------------------------------------------------------------
211
213 const ClusterVector &secondVector, ClusterAssociationMap &firstAssociationMap, ClusterAssociationMap &secondAssociationMap) const
214{
215 for (ClusterVector::const_iterator iterI = firstVector.begin(), iterEndI = firstVector.end(); iterI != iterEndI; ++iterI)
216 {
217 const Cluster *const pClusterI = *iterI;
218
219 for (ClusterVector::const_iterator iterJ = secondVector.begin(), iterEndJ = secondVector.end(); iterJ != iterEndJ; ++iterJ)
220 {
221 const Cluster *const pClusterJ = *iterJ;
222
223 if (pClusterI == pClusterJ)
224 continue;
225
226 if (this->IsAssociated(true, pClusterI, pClusterJ, nearbyClusters))
227 {
228 firstAssociationMap[pClusterI].m_forwardAssociations.insert(pClusterJ);
229 secondAssociationMap[pClusterJ].m_backwardAssociations.insert(pClusterI);
230 }
231
232 if (this->IsAssociated(false, pClusterI, pClusterJ, nearbyClusters))
233 {
234 firstAssociationMap[pClusterI].m_backwardAssociations.insert(pClusterJ);
235 secondAssociationMap[pClusterJ].m_forwardAssociations.insert(pClusterI);
236 }
237 }
238 }
239}
240
241//------------------------------------------------------------------------------------------------------------------------------------------
242
244 const ClusterAssociationMap &inputAssociationMap, TransverseClusterList &transverseClusterList) const
245{
246 for (ClusterVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
247 {
248 const Cluster *const pCluster = *iter;
249 ClusterVector associatedClusters;
250
251 this->GetAssociatedClusters(nearbyClusters, pCluster, inputAssociationMap, associatedClusters);
252
253 if (this->GetTransverseSpan(pCluster, associatedClusters) < m_transverseClusterMinLength)
254 continue;
255
256 transverseClusterList.push_back(new LArTransverseCluster(pCluster, associatedClusters));
257 }
258}
259
260//------------------------------------------------------------------------------------------------------------------------------------------
261
263 const TransverseClusterList &transverseClusterList, const ClusterAssociationMap &transverseAssociationMap,
264 ClusterAssociationMap &clusterAssociationMap) const
265{
266 for (TransverseClusterList::const_iterator iter1 = transverseClusterList.begin(), iterEnd1 = transverseClusterList.end(); iter1 != iterEnd1; ++iter1)
267 {
268 LArTransverseCluster *const pInnerTransverseCluster = *iter1;
269 const Cluster *const pInnerCluster(pInnerTransverseCluster->GetSeedCluster());
270
271 ClusterAssociationMap::const_iterator iterInner = transverseAssociationMap.find(pInnerCluster);
272 if (transverseAssociationMap.end() == iterInner)
273 continue;
274
275 for (TransverseClusterList::const_iterator iter2 = transverseClusterList.begin(), iterEnd2 = transverseClusterList.end();
276 iter2 != iterEnd2; ++iter2)
277 {
278 LArTransverseCluster *const pOuterTransverseCluster = *iter2;
279 const Cluster *const pOuterCluster(pOuterTransverseCluster->GetSeedCluster());
280
281 ClusterAssociationMap::const_iterator iterOuter = transverseAssociationMap.find(pOuterCluster);
282 if (transverseAssociationMap.end() == iterOuter)
283 continue;
284
285 if (pInnerCluster == pOuterCluster)
286 continue;
287
288 if (iterInner->second.m_forwardAssociations.count(pOuterCluster) == 0 || iterOuter->second.m_backwardAssociations.count(pInnerCluster) == 0)
289 continue;
290
291 if (!this->IsExtremalCluster(true, pInnerCluster, pOuterCluster) || !this->IsExtremalCluster(false, pOuterCluster, pInnerCluster))
292 continue;
293
294 if (!this->IsTransverseAssociated(pInnerTransverseCluster, pOuterTransverseCluster, nearbyClusters))
295 continue;
296
297 clusterAssociationMap[pInnerCluster].m_forwardAssociations.insert(pOuterCluster);
298 clusterAssociationMap[pOuterCluster].m_backwardAssociations.insert(pInnerCluster);
299 }
300 }
301}
302
303//------------------------------------------------------------------------------------------------------------------------------------------
304
306 const ClusterAssociationMap &associationMap, ClusterVector &associatedVector) const
307{
308 ClusterAssociationMap::const_iterator iterI = associationMap.find(pClusterI);
309 if (associationMap.end() == iterI)
310 return;
311
312 for (ClusterSet::const_iterator iterJ = iterI->second.m_forwardAssociations.begin(), iterEndJ = iterI->second.m_forwardAssociations.end();
313 iterJ != iterEndJ; ++iterJ)
314 {
315 const Cluster *const pClusterJ = *iterJ;
316
317 if (this->IsTransverseAssociated(pClusterI, pClusterJ, nearbyClusters))
318 associatedVector.push_back(pClusterJ);
319 }
320
321 for (ClusterSet::const_iterator iterJ = iterI->second.m_backwardAssociations.begin(), iterEndJ = iterI->second.m_backwardAssociations.end();
322 iterJ != iterEndJ; ++iterJ)
323 {
324 const Cluster *const pClusterJ = *iterJ;
325
326 if (this->IsTransverseAssociated(pClusterJ, pClusterI, nearbyClusters))
327 associatedVector.push_back(pClusterJ);
328 }
329
330 std::sort(associatedVector.begin(), associatedVector.end(), LArClusterHelper::SortByNHits);
331}
332
333//------------------------------------------------------------------------------------------------------------------------------------------
334
335bool TransverseAssociationAlgorithm::IsAssociated(const bool isForward, const Cluster *const pFirstCluster,
336 const Cluster *const pSecondCluster, const ClusterToClustersMap &nearbyClusters) const
337{
338 if ((0 == nearbyClusters.at(pFirstCluster).count(pSecondCluster)) || (0 == nearbyClusters.at(pSecondCluster).count(pFirstCluster)))
339 return false;
340
341 CartesianVector firstInner(0.f, 0.f, 0.f), firstOuter(0.f, 0.f, 0.f);
342 CartesianVector secondInner(0.f, 0.f, 0.f), secondOuter(0.f, 0.f, 0.f);
343 this->GetExtremalCoordinatesX(pFirstCluster, firstInner, firstOuter);
344 this->GetExtremalCoordinatesX(pSecondCluster, secondInner, secondOuter);
345
346 const CartesianVector firstCoordinate(isForward ? firstOuter : firstInner);
347 const CartesianVector secondCoordinate(isForward ? secondOuter : secondInner);
348
349 if ((firstCoordinate.GetZ() > std::max(secondInner.GetZ(), secondOuter.GetZ()) + m_maxLongitudinalOverlap) ||
350 (firstCoordinate.GetZ() < std::min(secondInner.GetZ(), secondOuter.GetZ()) - m_maxLongitudinalOverlap))
351 return false;
352
353 if ((isForward && secondCoordinate.GetX() < firstCoordinate.GetX()) || (!isForward && secondCoordinate.GetX() > firstCoordinate.GetX()))
354 return false;
355
356 const CartesianVector firstProjection(LArClusterHelper::GetClosestPosition(firstCoordinate, pSecondCluster));
357
358 if ((isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_maxTransverseOverlap) ||
359 (!isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_maxTransverseOverlap))
360 return false;
361
362 if ((isForward && firstProjection.GetX() > firstCoordinate.GetX() + m_clusterWindow) ||
363 (!isForward && firstProjection.GetX() < firstCoordinate.GetX() - m_clusterWindow))
364 return false;
365
366 return true;
367}
368
369//------------------------------------------------------------------------------------------------------------------------------------------
370
372 const Cluster *const pInnerCluster, const Cluster *const pOuterCluster, const ClusterToClustersMap &nearbyClusters) const
373{
374 if ((0 == nearbyClusters.at(pInnerCluster).count(pOuterCluster)) || (0 == nearbyClusters.at(pOuterCluster).count(pInnerCluster)))
375 return false;
376
377 CartesianVector innerInner(0.f, 0.f, 0.f), innerOuter(0.f, 0.f, 0.f);
378 CartesianVector outerInner(0.f, 0.f, 0.f), outerOuter(0.f, 0.f, 0.f);
379 this->GetExtremalCoordinatesX(pInnerCluster, innerInner, innerOuter);
380 this->GetExtremalCoordinatesX(pOuterCluster, outerInner, outerOuter);
381
382 const CartesianVector innerCentroid((innerInner + innerOuter) * 0.5);
383 const CartesianVector outerCentroid((outerInner + outerOuter) * 0.5);
384
385 if ((std::fabs(innerCentroid.GetZ() - outerInner.GetZ()) > std::fabs(innerCentroid.GetX() - outerInner.GetX()) * std::fabs(m_clusterTanAngle)) &&
386 (std::fabs(innerCentroid.GetZ() - outerOuter.GetZ()) > std::fabs(innerCentroid.GetX() - outerOuter.GetX()) * std::fabs(m_clusterTanAngle)))
387 return false;
388
389 if ((std::fabs(outerCentroid.GetZ() - innerInner.GetZ()) > std::fabs(outerCentroid.GetX() - innerInner.GetX()) * std::fabs(m_clusterTanAngle)) &&
390 (std::fabs(outerCentroid.GetZ() - innerOuter.GetZ()) > std::fabs(outerCentroid.GetX() - innerOuter.GetX()) * std::fabs(m_clusterTanAngle)))
391 return false;
392
393 const CartesianVector innerProjection(LArClusterHelper::GetClosestPosition(outerInner, pInnerCluster));
394 const CartesianVector outerProjection(LArClusterHelper::GetClosestPosition(innerOuter, pOuterCluster));
395
396 if (innerOuter.GetX() > innerProjection.GetX() + m_maxTransverseOverlap || outerInner.GetX() < outerProjection.GetX() - m_maxTransverseOverlap)
397 return false;
398
399 return true;
400}
401
402//------------------------------------------------------------------------------------------------------------------------------------------
403
405 const LArTransverseCluster *const pOuterTransverseCluster, const ClusterToClustersMap &nearbyClusters) const
406{
407 if (pInnerTransverseCluster->GetDirection().GetDotProduct(pOuterTransverseCluster->GetDirection()) < m_transverseClusterMinCosTheta)
408 return false;
409
410 if (!this->IsTransverseAssociated(pInnerTransverseCluster, pOuterTransverseCluster->GetInnerVertex()))
411 return false;
412
413 if (!this->IsTransverseAssociated(pOuterTransverseCluster, pInnerTransverseCluster->GetOuterVertex()))
414 return false;
415
416 if (!this->IsTransverseAssociated(pInnerTransverseCluster->GetSeedCluster(), pOuterTransverseCluster->GetSeedCluster(), nearbyClusters))
417 return false;
418
419 if (this->IsOverlapping(pInnerTransverseCluster->GetSeedCluster(), pOuterTransverseCluster->GetSeedCluster()))
420 return false;
421
422 return true;
423}
424
425//------------------------------------------------------------------------------------------------------------------------------------------
426
427bool TransverseAssociationAlgorithm::IsTransverseAssociated(const LArTransverseCluster *const pTransverseCluster, const CartesianVector &testVertex) const
428{
429 const CartesianVector &innerVertex(pTransverseCluster->GetInnerVertex());
430 const CartesianVector &outerVertex(pTransverseCluster->GetOuterVertex());
431 const CartesianVector &direction(pTransverseCluster->GetDirection());
432
434 return false;
435
436 if ((direction.GetDotProduct(testVertex - innerVertex) < -1.f * m_clusterWindow) ||
437 (direction.GetDotProduct(testVertex - outerVertex) > +1.f * m_clusterWindow))
438 return false;
439
440 return true;
441}
442
443//------------------------------------------------------------------------------------------------------------------------------------------
444
445bool TransverseAssociationAlgorithm::IsOverlapping(const Cluster *const pInnerCluster, const Cluster *const pOuterCluster) const
446{
447 CartesianVector innerInner(0.f, 0.f, 0.f), innerOuter(0.f, 0.f, 0.f);
448 CartesianVector outerInner(0.f, 0.f, 0.f), outerOuter(0.f, 0.f, 0.f);
449 this->GetExtremalCoordinatesX(pInnerCluster, innerInner, innerOuter);
450 this->GetExtremalCoordinatesX(pOuterCluster, outerInner, outerOuter);
451
452 const CartesianVector innerProjection(LArClusterHelper::GetClosestPosition(outerInner, pInnerCluster));
453 const CartesianVector outerProjection(LArClusterHelper::GetClosestPosition(innerOuter, pOuterCluster));
454
455 const float innerOverlapSquared((innerProjection - innerOuter).GetMagnitudeSquared());
456 const float outerOverlapSquared((outerProjection - outerInner).GetMagnitudeSquared());
457
458 return (std::max(innerOverlapSquared, outerOverlapSquared) > m_maxProjectedOverlap * m_maxProjectedOverlap);
459}
460
461//------------------------------------------------------------------------------------------------------------------------------------------
462
464{
465 float minX(+std::numeric_limits<float>::max());
466 float maxX(-std::numeric_limits<float>::max());
467
468 this->GetExtremalCoordinatesX(pCluster, minX, maxX);
469
470 return (maxX - minX);
471}
472
473//------------------------------------------------------------------------------------------------------------------------------------------
474
476{
477 float minZ(+std::numeric_limits<float>::max());
478 float maxZ(-std::numeric_limits<float>::max());
479
480 this->GetExtremalCoordinatesZ(pCluster, minZ, maxZ);
481
482 return (maxZ - minZ);
483}
484
485//------------------------------------------------------------------------------------------------------------------------------------------
486
487float TransverseAssociationAlgorithm::GetTransverseSpan(const Cluster *const pCentralCluster, const ClusterVector &associatedClusters) const
488{
489 float overallMinX(+std::numeric_limits<float>::max());
490 float overallMaxX(-std::numeric_limits<float>::max());
491
492 this->GetExtremalCoordinatesX(pCentralCluster, overallMinX, overallMaxX);
493
494 float localMinX(+std::numeric_limits<float>::max());
495 float localMaxX(-std::numeric_limits<float>::max());
496
497 for (ClusterVector::const_iterator iter = associatedClusters.begin(), iterEnd = associatedClusters.end(); iter != iterEnd; ++iter)
498 {
499 const Cluster *const pAssociatedCluster = *iter;
500
501 this->GetExtremalCoordinatesX(pAssociatedCluster, localMinX, localMaxX);
502
503 if (localMinX < overallMinX)
504 overallMinX = localMinX;
505
506 if (localMaxX > overallMaxX)
507 overallMaxX = localMaxX;
508 }
509
510 return (overallMaxX - overallMinX);
511}
512
513//------------------------------------------------------------------------------------------------------------------------------------------
514
515bool TransverseAssociationAlgorithm::IsExtremalCluster(const bool isForward, const Cluster *const pCurrentCluster, const Cluster *const pTestCluster) const
516{
517 float currentMinX(0.f), currentMaxX(0.f);
518 this->GetExtremalCoordinatesX(pCurrentCluster, currentMinX, currentMaxX);
519
520 float testMinX(0.f), testMaxX(0.f);
521 this->GetExtremalCoordinatesX(pTestCluster, testMinX, testMaxX);
522
523 if (isForward)
524 {
525 if (std::fabs(testMaxX - currentMaxX) > std::numeric_limits<float>::epsilon())
526 return (testMaxX > currentMaxX);
527 }
528 else
529 {
530 if (std::fabs(testMinX - currentMaxX) > std::numeric_limits<float>::epsilon())
531 return (testMinX < currentMinX);
532 }
533
534 return LArClusterHelper::SortByNHits(pTestCluster, pCurrentCluster);
535}
536
537//------------------------------------------------------------------------------------------------------------------------------------------
538
539void TransverseAssociationAlgorithm::GetExtremalCoordinatesX(const Cluster *const pCluster, float &minX, float &maxX) const
540{
541 return this->GetExtremalCoordinatesXZ(pCluster, true, minX, maxX);
542}
543
544//------------------------------------------------------------------------------------------------------------------------------------------
545
546void TransverseAssociationAlgorithm::GetExtremalCoordinatesZ(const Cluster *const pCluster, float &minZ, float &maxZ) const
547{
548 return this->GetExtremalCoordinatesXZ(pCluster, false, minZ, maxZ);
549}
550
551//------------------------------------------------------------------------------------------------------------------------------------------
552
553void TransverseAssociationAlgorithm::GetExtremalCoordinatesXZ(const Cluster *const pCluster, const bool useX, float &minXZ, float &maxXZ) const
554{
555 minXZ = +std::numeric_limits<float>::max();
556 maxXZ = -std::numeric_limits<float>::max();
557
558 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
559
560 for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
561 {
562 for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
563 {
564 const float caloHitXZ(useX ? (*hitIter)->GetPositionVector().GetX() : (*hitIter)->GetPositionVector().GetZ());
565
566 if (caloHitXZ < minXZ)
567 minXZ = caloHitXZ;
568
569 if (caloHitXZ > maxXZ)
570 maxXZ = caloHitXZ;
571 }
572 }
573
574 if (maxXZ < minXZ)
575 throw pandora::StatusCodeException(STATUS_CODE_FAILURE);
576}
577
578//------------------------------------------------------------------------------------------------------------------------------------------
579
581 const Cluster *const pCluster, CartesianVector &innerCoordinate, CartesianVector &outerCoordinate) const
582{
583 CartesianVector firstCoordinate(0.f, 0.f, 0.f), secondCoordinate(0.f, 0.f, 0.f);
584 LArClusterHelper::GetExtremalCoordinates(pCluster, firstCoordinate, secondCoordinate);
585
586 innerCoordinate = (firstCoordinate.GetX() < secondCoordinate.GetX() ? firstCoordinate : secondCoordinate);
587 outerCoordinate = (firstCoordinate.GetX() > secondCoordinate.GetX() ? firstCoordinate : secondCoordinate);
588}
589
590//------------------------------------------------------------------------------------------------------------------------------------------
591
593 const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
594{
595 return this->FillReducedAssociationMap(inputAssociationMap, inputAssociationMap, inputAssociationMap, outputAssociationMap);
596}
597
598//------------------------------------------------------------------------------------------------------------------------------------------
599
601 const ClusterAssociationMap &secondAssociationMap, const ClusterAssociationMap &secondAssociationMapSwapped,
602 ClusterAssociationMap &clusterAssociationMap) const
603{
604 // Remove associations A->B from the first association map
605 // if A->C exists in the second map and C->B exists in the reversed second map
606
607 // Method can also be accessed through FillReducedAssociationMap(input,output) method,
608 // which will remove association A->B from the input map if an association A->C and C->B
609 // already exists in the map.
610
611 ClusterVector sortedClusters;
612 for (const auto &mapEntry : firstAssociationMap)
613 sortedClusters.push_back(mapEntry.first);
614 std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
615
616 for (const Cluster *const pCluster : sortedClusters)
617 {
618 const ClusterAssociation &firstAssociation(firstAssociationMap.at(pCluster));
619
620 ClusterVector sortedOuterClusters(firstAssociation.m_forwardAssociations.begin(), firstAssociation.m_forwardAssociations.end());
621 std::sort(sortedOuterClusters.begin(), sortedOuterClusters.end(), LArClusterHelper::SortByNHits);
622
623 ClusterVector sortedInnerClusters(firstAssociation.m_backwardAssociations.begin(), firstAssociation.m_backwardAssociations.end());
624 std::sort(sortedInnerClusters.begin(), sortedInnerClusters.end(), LArClusterHelper::SortByNHits);
625
626 ClusterAssociationMap::const_iterator iterSecond = secondAssociationMap.find(pCluster);
627 ClusterVector sortedMiddleClustersF, sortedMiddleClustersB;
628
629 if (secondAssociationMap.end() != iterSecond)
630 {
631 sortedMiddleClustersF.insert(sortedMiddleClustersF.end(), iterSecond->second.m_forwardAssociations.begin(),
632 iterSecond->second.m_forwardAssociations.end());
633 sortedMiddleClustersB.insert(sortedMiddleClustersB.end(), iterSecond->second.m_backwardAssociations.begin(),
634 iterSecond->second.m_backwardAssociations.end());
635 std::sort(sortedMiddleClustersF.begin(), sortedMiddleClustersF.end(), LArClusterHelper::SortByNHits);
636 std::sort(sortedMiddleClustersB.begin(), sortedMiddleClustersB.end(), LArClusterHelper::SortByNHits);
637 }
638
639 for (const Cluster *const pOuterCluster : sortedOuterClusters)
640 {
641 bool isNeighbouringCluster(true);
642
643 for (const Cluster *const pMiddleCluster : sortedMiddleClustersF)
644 {
645 ClusterAssociationMap::const_iterator iterSecondCheck = secondAssociationMapSwapped.find(pMiddleCluster);
646 if (secondAssociationMapSwapped.end() == iterSecondCheck)
647 continue;
648
649 if (iterSecondCheck->second.m_forwardAssociations.count(pOuterCluster) > 0)
650 {
651 isNeighbouringCluster = false;
652 break;
653 }
654 }
655
656 if (isNeighbouringCluster)
657 clusterAssociationMap[pCluster].m_forwardAssociations.insert(pOuterCluster);
658 }
659
660 for (const Cluster *const pInnerCluster : sortedInnerClusters)
661 {
662 bool isNeighbouringCluster(true);
663
664 for (const Cluster *const pMiddleCluster : sortedMiddleClustersB)
665 {
666 ClusterAssociationMap::const_iterator iterSecondCheck = secondAssociationMapSwapped.find(pMiddleCluster);
667 if (secondAssociationMapSwapped.end() == iterSecondCheck)
668 continue;
669
670 if (iterSecondCheck->second.m_backwardAssociations.count(pInnerCluster) > 0)
671 {
672 isNeighbouringCluster = false;
673 break;
674 }
675 }
676
677 if (isNeighbouringCluster)
678 clusterAssociationMap[pCluster].m_backwardAssociations.insert(pInnerCluster);
679 }
680 }
681}
682
683//------------------------------------------------------------------------------------------------------------------------------------------
684
686 const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
687{
688 // Generate a symmetrised association map, so that both A--Fwd-->B and B--Bwd-->A both exist.
689 // If A is associated to B through both a backward and forward association (very bad!),
690 // try to rationalise this through majority voting, otherwise remove the association.
691
692 ClusterVector sortedClusters;
693 for (const auto &mapEntry : inputAssociationMap)
694 sortedClusters.push_back(mapEntry.first);
695 std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
696
697 for (const Cluster *const pCluster : sortedClusters)
698 {
699 const ClusterAssociation &inputAssociation(inputAssociationMap.at(pCluster));
700
701 ClusterVector sortedForwardClusters(inputAssociation.m_forwardAssociations.begin(), inputAssociation.m_forwardAssociations.end());
702 std::sort(sortedForwardClusters.begin(), sortedForwardClusters.end(), LArClusterHelper::SortByNHits);
703
704 ClusterVector sortedBackwardClusters(inputAssociation.m_backwardAssociations.begin(), inputAssociation.m_backwardAssociations.end());
705 std::sort(sortedBackwardClusters.begin(), sortedBackwardClusters.end(), LArClusterHelper::SortByNHits);
706
707 // Symmetrise forward associations
708 for (const Cluster *const pForwardCluster : sortedForwardClusters)
709 {
710 int nCounter(+1);
711
712 if (inputAssociation.m_backwardAssociations.count(pForwardCluster))
713 --nCounter;
714
715 ClusterAssociationMap::const_iterator iterCheck = inputAssociationMap.find(pForwardCluster);
716 if (inputAssociationMap.end() != iterCheck)
717 {
718 if (iterCheck->second.m_forwardAssociations.count(pCluster))
719 --nCounter;
720
721 if (iterCheck->second.m_backwardAssociations.count(pCluster))
722 ++nCounter;
723 }
724
725 if (nCounter > 0)
726 {
727 if (!(outputAssociationMap[pCluster].m_backwardAssociations.count(pForwardCluster) == 0 &&
728 outputAssociationMap[pForwardCluster].m_forwardAssociations.count(pCluster) == 0))
729 throw StatusCodeException(STATUS_CODE_FAILURE);
730
731 outputAssociationMap[pCluster].m_forwardAssociations.insert(pForwardCluster);
732 outputAssociationMap[pForwardCluster].m_backwardAssociations.insert(pCluster);
733 }
734 }
735
736 // Symmetrise backward associations
737 for (const Cluster *const pBackwardCluster : sortedBackwardClusters)
738 {
739 int nCounter(-1);
740
741 if (inputAssociation.m_forwardAssociations.count(pBackwardCluster))
742 ++nCounter;
743
744 ClusterAssociationMap::const_iterator iterCheck = inputAssociationMap.find(pBackwardCluster);
745 if (inputAssociationMap.end() != iterCheck)
746 {
747 if (iterCheck->second.m_backwardAssociations.count(pCluster))
748 ++nCounter;
749
750 if (iterCheck->second.m_forwardAssociations.count(pCluster))
751 --nCounter;
752 }
753
754 if (nCounter < 0)
755 {
756 if (!(outputAssociationMap[pCluster].m_forwardAssociations.count(pBackwardCluster) == 0 &&
757 outputAssociationMap[pBackwardCluster].m_backwardAssociations.count(pCluster) == 0))
758 throw StatusCodeException(STATUS_CODE_FAILURE);
759
760 outputAssociationMap[pCluster].m_backwardAssociations.insert(pBackwardCluster);
761 outputAssociationMap[pBackwardCluster].m_forwardAssociations.insert(pCluster);
762 }
763 }
764 }
765}
766
767//------------------------------------------------------------------------------------------------------------------------------------------
768
770 const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
771{
772 ClusterAssociationMap intermediateAssociationMap;
773 this->FillSymmetricAssociationMap(inputAssociationMap, intermediateAssociationMap);
774 this->FillReducedAssociationMap(intermediateAssociationMap, outputAssociationMap);
775}
776
777//------------------------------------------------------------------------------------------------------------------------------------------
778//------------------------------------------------------------------------------------------------------------------------------------------
779
781 m_pSeedCluster(pSeedCluster),
782 m_associatedClusters(associatedClusters),
783 m_innerVertex(0.f, 0.f, 0.f),
784 m_outerVertex(0.f, 0.f, 0.f),
785 m_direction(0.f, 0.f, 0.f)
786{
787 double Swxx(0.), Swzx(0.), Swz(0.), Swx(0.), Sw(0.);
788 double minX(std::numeric_limits<double>::max());
789 double maxX(-std::numeric_limits<double>::max());
790
791 ClusterList clusterList(1, pSeedCluster);
792 clusterList.insert(clusterList.end(), associatedClusters.begin(), associatedClusters.end());
793
794 for (ClusterList::const_iterator iterI = clusterList.begin(), iterEndI = clusterList.end(); iterI != iterEndI; ++iterI)
795 {
796 for (OrderedCaloHitList::const_iterator iterJ = (*iterI)->GetOrderedCaloHitList().begin(),
797 iterEndJ = (*iterI)->GetOrderedCaloHitList().end();
798 iterJ != iterEndJ; ++iterJ)
799 {
800 for (CaloHitList::const_iterator iterK = iterJ->second->begin(), iterEndK = iterJ->second->end(); iterK != iterEndK; ++iterK)
801 {
802 const CaloHit *const pCaloHit = *iterK;
803
804 if (pCaloHit->GetPositionVector().GetX() < minX)
805 minX = pCaloHit->GetPositionVector().GetX();
806
807 if (pCaloHit->GetPositionVector().GetX() > maxX)
808 maxX = pCaloHit->GetPositionVector().GetX();
809
810 Swxx += pCaloHit->GetPositionVector().GetX() * pCaloHit->GetPositionVector().GetX();
811 Swzx += pCaloHit->GetPositionVector().GetZ() * pCaloHit->GetPositionVector().GetX();
812 Swz += pCaloHit->GetPositionVector().GetZ();
813 Swx += pCaloHit->GetPositionVector().GetX();
814 Sw += 1.;
815 }
816 }
817 }
818
819 if (Sw > 0.f)
820 {
821 const double averageX(Swx / Sw);
822 const double averageZ(Swz / Sw);
823
824 if (Sw * Swxx - Swx * Swx > 0.)
825 {
826 double m((Sw * Swzx - Swx * Swz) / (Sw * Swxx - Swx * Swx));
827 double px(1. / std::sqrt(1. + m * m));
828 double pz(m / std::sqrt(1. + m * m));
829
830 m_innerVertex.SetValues(static_cast<float>(minX), 0.f, static_cast<float>(averageZ + m * (minX - averageX)));
831 m_outerVertex.SetValues(static_cast<float>(maxX), 0.f, static_cast<float>(averageZ + m * (maxX - averageX)));
832 m_direction.SetValues(static_cast<float>(px), 0.f, static_cast<float>(pz));
833 }
834 else
835 {
836 m_innerVertex.SetValues(static_cast<float>(averageX), 0.f, static_cast<float>(averageZ));
837 m_outerVertex.SetValues(static_cast<float>(averageX), 0.f, static_cast<float>(averageZ));
838 m_direction.SetValues(1.f, 0.f, 0.f);
839 }
840 }
841 else
842 {
843 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
844 }
845}
846
847//------------------------------------------------------------------------------------------------------------------------------------------
848//------------------------------------------------------------------------------------------------------------------------------------------
849
851{
852 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FirstLengthCut", m_firstLengthCut));
853
854 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SecondLengthCut", m_secondLengthCut));
855
856 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ClusterWindow", m_clusterWindow));
857
858 const StatusCode angleStatusCode(XmlHelper::ReadValue(xmlHandle, "clusterAngle", m_clusterAngle));
859
860 if (STATUS_CODE_SUCCESS == angleStatusCode)
861 {
862 m_clusterCosAngle = std::cos(m_clusterAngle * M_PI / 180.f);
863 m_clusterTanAngle = std::tan(m_clusterAngle * M_PI / 180.f);
864 }
865 else if (STATUS_CODE_NOT_FOUND != angleStatusCode)
866 {
867 return angleStatusCode;
868 }
869
871 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTransverseOverlap", m_maxTransverseOverlap));
872
874 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxProjectedOverlap", m_maxProjectedOverlap));
875
877 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxLongitudinalOverlap", m_maxLongitudinalOverlap));
878
879 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
880 XmlHelper::ReadValue(xmlHandle, "TransverseClusterMinCosTheta", m_transverseClusterMinCosTheta));
881
882 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
883 XmlHelper::ReadValue(xmlHandle, "TransverseClusterMinLength", m_transverseClusterMinLength));
884
885 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
886 XmlHelper::ReadValue(xmlHandle, "TransverseClusterMaxDisplacement", m_transverseClusterMaxDisplacement));
887
889}
890
891} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the kd tree linker algo template class.
Header file for the cluster helper class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
Header file for the transverse association algorithm class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
pandora::ClusterSet m_forwardAssociations
The list of forward associations.
pandora::ClusterSet m_backwardAssociations
The list of backward associations.
std::unordered_map< const pandora::Cluster *, ClusterAssociation > ClusterAssociationMap
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > &region)
Build the KD tree from the "eltList" in the space define by "region".
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position,...
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z)
const pandora::CartesianVector & GetOuterVertex() const
Get the outer vertex position.
const pandora::CartesianVector & GetDirection() const
Get the direction.
LArTransverseCluster(const pandora::Cluster *const pSeedCluster, const pandora::ClusterVector &associatedClusters)
Constructor.
const pandora::CartesianVector & GetInnerVertex() const
Get the inner vertex position.
void FillSymmetricAssociationMap(const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
Symmetrise an association map.
void FillTransverseAssociationMap(const ClusterToClustersMap &nearbyClusters, const TransverseClusterList &transverseClusterList, const ClusterAssociationMap &transverseAssociationMap, ClusterAssociationMap &clusterAssociationMap) const
Form associations between transverse cluster objects.
void FinalizeClusterAssociationMap(const ClusterAssociationMap &inputAssociationMap, ClusterAssociationMap &outputAssociationMap) const
Symmetrise and then remove double-counting from an association map.
bool IsOverlapping(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2) const
Determine whether two clusters are overlapping.
float m_searchRegionX
Search region, applied to x dimension, for look-up from kd-trees.
void SortInputClusters(const pandora::ClusterVector &inputClusters, pandora::ClusterVector &shortClusters, pandora::ClusterVector &transverseMediumClusters, pandora::ClusterVector &longitudinalMediumClusters, pandora::ClusterVector &longClusters) const
Separate input clusters by length.
float m_searchRegionZ
Search region, applied to u/v/w dimension, for look-up from kd-trees.
void GetAssociatedClusters(const ClusterToClustersMap &nearbyClusters, const pandora::Cluster *const pCluster, const ClusterAssociationMap &inputAssociationMap, pandora::ClusterVector &associatedClusters) const
Find the clusters that are transversely associated with a target cluster.
float GetLongitudinalSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in Z for a clusters.
bool IsTransverseAssociated(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether two clusters are within the same cluster window.
void PopulateClusterAssociationMap(const pandora::ClusterVector &clusterVector, ClusterAssociationMap &clusterAssociationMap) const
Populate the cluster association map.
void GetExtremalCoordinatesZ(const pandora::Cluster *const pCluster, float &minZ, float &maxZ) const
Get minimum and maximum Z coordinates for a given cluster.
float GetTransverseSpan(const pandora::Cluster *const pCluster) const
Calculate the overall span in X for a clusters.
bool IsExtremalCluster(const bool isForward, const pandora::Cluster *const pCurrentCluster, const pandora::Cluster *const pTestCluster) const
Determine which of two clusters is extremal.
std::vector< LArTransverseCluster * > TransverseClusterList
bool IsAssociated(const bool isForward, const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const ClusterToClustersMap &nearbyClusters) const
Determine whether clusters are association.
void GetNearbyClusterMap(const pandora::ClusterVector &allClusters, ClusterToClustersMap &nearbyClusters) const
Use a kd-tree to obtain details of all nearby cluster combinations.
void GetExtremalCoordinatesXZ(const pandora::Cluster *const pCluster, const bool useX, float &minXZ, float &maxXZ) const
Get minimum and maximum X or Z coordinates for a given cluster.
void FillTransverseClusterList(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &inputClusters, const ClusterAssociationMap &inputAssociationMap, TransverseClusterList &transverseClusterList) const
Create transverse cluster objects, these are protoclusters with a direction and inner/outer vertices.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void FillAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &firstAssociationMap, ClusterAssociationMap &secondAssociationMap) const
Form associations between two input lists of cluster.
void FillReducedAssociationMap(const ClusterToClustersMap &nearbyClusters, const pandora::ClusterVector &firstVector, const pandora::ClusterVector &secondVector, ClusterAssociationMap &clusterAssociationMap) const
Form a reduced set of associations between two input lists of clusters.
void GetExtremalCoordinatesX(const pandora::Cluster *const pCluster, float &minX, float &maxX) const
Get minimum and maximum X coordinates for a given cluster.
void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
Populate cluster vector with subset of cluster list, containing clusters judged to be clean.
std::unordered_map< const pandora::Cluster *, pandora::ClusterSet > ClusterToClustersMap
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
CaloHit class.
Definition CaloHit.h:26
const CartesianVector & GetPositionVector() const
Get the position vector of center of calorimeter cell, units mm.
Definition CaloHit.h:350
CartesianVector class.
void SetValues(float x, float y, float z)
Set the values of cartesian vector components.
float GetMagnitudeSquared() const
Get the magnitude squared.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
CartesianVector GetCrossProduct(const CartesianVector &rhs) const
Get the cross product of the cartesian vector with a second cartesian vector.
Cluster class.
Definition Cluster.h:31
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
Calo hit lists arranged by pseudo layer.
const_iterator end() const
Returns a const iterator referring to the past-the-end element in the ordered calo hit list.
const_iterator begin() const
Returns a const iterator referring to the first element in the ordered calo hit list.
TheList::const_iterator const_iterator
StatusCodeException class.
std::string ToString() const
Get status code as a string.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 > > &nodes)
fill_and_bound_2d_kd_tree
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.