All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EventSlicingTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArEventBuilding/EventSlicingTool.cc
3  *
4  * @brief Implementation of the event slicing tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
15 
18 
20 
22 
23 using namespace pandora;
24 
25 namespace lar_content
26 {
27 
31 
32 //------------------------------------------------------------------------------------------------------------------------------------------
33 
34 EventSlicingTool::EventSlicingTool() :
35  m_minHitsPer3DCluster(20),
36  m_min3DHitsToSeedNewSlice(50),
37  m_halfWindowLayers(20),
38  m_usePointingAssociation(true),
39  m_minVertexLongitudinalDistance(-7.5f),
40  m_maxVertexLongitudinalDistance(60.f),
41  m_maxVertexTransverseDistance(10.5f),
42  m_vertexAngularAllowance(9.f),
43  m_maxClosestApproach(15.f),
44  m_maxInterceptDistance(60.f),
45  m_useProximityAssociation(true),
46  m_maxHitSeparationSquared(25.f * 25.f),
47  m_useShowerConeAssociation(true),
48  m_nConeFitLayers(20),
49  m_nConeFits(5),
50  m_coneLengthMultiplier(7.f),
51  m_maxConeLength(126.f),
52  m_coneTanHalfAngle1(0.5f),
53  m_coneBoundedFraction1(0.5f),
54  m_coneTanHalfAngle2(0.75f),
55  m_coneBoundedFraction2(0.75f),
56  m_use3DProjectionsInHitPickUp(true)
57 {
58 }
59 
60 //------------------------------------------------------------------------------------------------------------------------------------------
61 
62 void EventSlicingTool::RunSlicing(const Algorithm *const pAlgorithm, const HitTypeToNameMap &caloHitListNames,
63  const HitTypeToNameMap &clusterListNames, SliceList &sliceList)
64 {
65  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
66  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
67 
68  ClusterToPfoMap clusterToPfoMap;
69 
70  ClusterList trackClusters3D;
71  this->GetThreeDClusters(pAlgorithm, m_trackPfoListName, trackClusters3D, clusterToPfoMap);
72 
73  ClusterList showerClusters3D;
74  this->GetThreeDClusters(pAlgorithm, m_showerPfoListName, showerClusters3D, clusterToPfoMap);
75 
76  ClusterSliceList clusterSliceList;
77  this->GetClusterSliceList(trackClusters3D, showerClusters3D, clusterSliceList);
78 
79  if (clusterSliceList.size() < 2)
80  {
81  return this->CopyAllHitsToSingleSlice(pAlgorithm, caloHitListNames, sliceList);
82  }
83  else
84  {
85  ClusterToSliceIndexMap clusterToSliceIndexMap;
86  this->CreateSlices(clusterSliceList, sliceList, clusterToSliceIndexMap);
87 
88  ClusterSet assignedClusters;
89  this->CopyPfoHitsToSlices(clusterToSliceIndexMap, clusterToPfoMap, sliceList, assignedClusters);
90 
91  ClusterList remainingClusters;
92  this->GetRemainingClusters(pAlgorithm, clusterListNames, assignedClusters, remainingClusters);
93 
94  this->AssignRemainingHitsToSlices(remainingClusters, clusterToSliceIndexMap, sliceList);
95  }
96 }
97 
98 //------------------------------------------------------------------------------------------------------------------------------------------
99 
100 void EventSlicingTool::CopyAllHitsToSingleSlice(const Algorithm *const pAlgorithm, const HitTypeToNameMap &caloHitListNames, SliceList &sliceList) const
101 {
102  if (!sliceList.empty())
103  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
104 
105  const CaloHitList *pCaloHitListU(nullptr);
106  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
107  PandoraContentApi::GetList(*pAlgorithm, caloHitListNames.at(TPC_VIEW_U), pCaloHitListU));
108 
109  const CaloHitList *pCaloHitListV(nullptr);
110  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
111  PandoraContentApi::GetList(*pAlgorithm, caloHitListNames.at(TPC_VIEW_V), pCaloHitListV));
112 
113  const CaloHitList *pCaloHitListW(nullptr);
114  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=,
115  PandoraContentApi::GetList(*pAlgorithm, caloHitListNames.at(TPC_VIEW_W), pCaloHitListW));
116 
117  if (pCaloHitListU || pCaloHitListV || pCaloHitListW)
118  {
119  sliceList.push_back(Slice());
120  Slice &slice(sliceList.at(0));
121 
122  if (pCaloHitListU)
123  slice.m_caloHitListU = *pCaloHitListU;
124  if (pCaloHitListV)
125  slice.m_caloHitListV = *pCaloHitListV;
126  if (pCaloHitListW)
127  slice.m_caloHitListW = *pCaloHitListW;
128  }
129 }
130 
131 //------------------------------------------------------------------------------------------------------------------------------------------
132 
134  const Algorithm *const pAlgorithm, const std::string &pfoListName, ClusterList &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
135 {
136  const PfoList *pPfoList(nullptr);
137  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*pAlgorithm, pfoListName, pPfoList));
138 
139  if (!pPfoList || pPfoList->empty())
140  {
141  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
142  std::cout << "EventSlicingTool: unable to find pfo list " << pfoListName << std::endl;
143 
144  return;
145  }
146 
147  for (const ParticleFlowObject *const pPfo : *pPfoList)
148  {
149  ClusterList pfoClusters3D;
150  LArPfoHelper::GetThreeDClusterList(pPfo, pfoClusters3D);
151 
152  for (const Cluster *const pCluster3D : pfoClusters3D)
153  {
154  if (pCluster3D->GetNCaloHits() < m_minHitsPer3DCluster)
155  continue;
156 
157  if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
158  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
159 
160  if (clusters3D.end() != std::find(clusters3D.begin(), clusters3D.end(), pCluster3D))
161  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
162 
163  clusters3D.push_back(pCluster3D);
164  }
165  }
166 }
167 
168 //------------------------------------------------------------------------------------------------------------------------------------------
169 
170 void EventSlicingTool::GetClusterSliceList(const ClusterList &trackClusters3D, const ClusterList &showerClusters3D, ClusterSliceList &clusterSliceList) const
171 {
172  const float layerPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
173 
174  ThreeDSlidingFitResultMap trackFitResults;
175 
176  for (const Cluster *const pCluster3D : trackClusters3D)
177  {
178  try
179  {
180  trackFitResults.insert(
181  ThreeDSlidingFitResultMap::value_type(pCluster3D, ThreeDSlidingFitResult(pCluster3D, m_halfWindowLayers, layerPitch)));
182  }
183  catch (StatusCodeException &)
184  {
185  std::cout << "EventSlicingTool: ThreeDSlidingFitResult failure for track cluster." << std::endl;
186  }
187  }
188 
189  ThreeDSlidingConeFitResultMap showerConeFitResults;
190 
191  for (const Cluster *const pCluster3D : showerClusters3D)
192  {
193  try
194  {
195  showerConeFitResults.insert(
196  ThreeDSlidingConeFitResultMap::value_type(pCluster3D, ThreeDSlidingConeFitResult(pCluster3D, m_halfWindowLayers, layerPitch)));
197  }
198  catch (StatusCodeException &)
199  {
200  std::cout << "EventSlicingTool: ThreeDSlidingConeFitResult failure for shower cluster." << std::endl;
201  }
202  }
203 
204  ClusterVector sortedClusters3D(trackClusters3D.begin(), trackClusters3D.end());
205  sortedClusters3D.insert(sortedClusters3D.end(), showerClusters3D.begin(), showerClusters3D.end());
206  std::sort(sortedClusters3D.begin(), sortedClusters3D.end(), LArClusterHelper::SortByNHits);
207 
208  ClusterSet usedClusters;
209 
210  for (const Cluster *const pCluster3D : sortedClusters3D)
211  {
212  if (usedClusters.count(pCluster3D))
213  continue;
214 
215  if (pCluster3D->GetNCaloHits() < m_min3DHitsToSeedNewSlice)
216  continue;
217 
218  clusterSliceList.push_back(ClusterVector(1, pCluster3D));
219  usedClusters.insert(pCluster3D);
220 
221  ClusterVector &clusterSlice(clusterSliceList.back());
222  this->CollectAssociatedClusters(pCluster3D, sortedClusters3D, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
223  }
224 }
225 
226 //------------------------------------------------------------------------------------------------------------------------------------------
227 
228 void EventSlicingTool::CollectAssociatedClusters(const Cluster *const pClusterInSlice, const ClusterVector &candidateClusters,
229  const ThreeDSlidingFitResultMap &trackFitResults, const ThreeDSlidingConeFitResultMap &showerConeFitResults,
230  ClusterVector &clusterSlice, ClusterSet &usedClusters) const
231 {
232  ClusterVector addedClusters;
233 
234  for (const Cluster *const pCandidateCluster : candidateClusters)
235  {
236  if (usedClusters.count(pCandidateCluster) || (pClusterInSlice == pCandidateCluster))
237  continue;
238 
239  if ((m_usePointingAssociation && this->PassPointing(pClusterInSlice, pCandidateCluster, trackFitResults)) ||
240  (m_useProximityAssociation && this->PassProximity(pClusterInSlice, pCandidateCluster)) ||
241  (m_useShowerConeAssociation && (this->PassShowerCone(pClusterInSlice, pCandidateCluster, showerConeFitResults) ||
242  this->PassShowerCone(pCandidateCluster, pClusterInSlice, showerConeFitResults))))
243  {
244  addedClusters.push_back(pCandidateCluster);
245  (void)usedClusters.insert(pCandidateCluster);
246  }
247  }
248 
249  clusterSlice.insert(clusterSlice.end(), addedClusters.begin(), addedClusters.end());
250 
251  for (const Cluster *const pAddedCluster : addedClusters)
252  this->CollectAssociatedClusters(pAddedCluster, candidateClusters, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
253 }
254 
255 //------------------------------------------------------------------------------------------------------------------------------------------
256 
258  const Cluster *const pClusterInSlice, const Cluster *const pCandidateCluster, const ThreeDSlidingFitResultMap &trackFitResults) const
259 {
260  ThreeDSlidingFitResultMap::const_iterator inSliceIter = trackFitResults.find(pClusterInSlice);
261  ThreeDSlidingFitResultMap::const_iterator candidateIter = trackFitResults.find(pCandidateCluster);
262 
263  if ((trackFitResults.end() == inSliceIter) || (trackFitResults.end() == candidateIter))
264  return false;
265 
266  const LArPointingCluster inSlicePointingCluster(inSliceIter->second);
267  const LArPointingCluster candidatePointingCluster(candidateIter->second);
268 
269  if (this->CheckClosestApproach(inSlicePointingCluster, candidatePointingCluster) ||
270  this->IsEmission(inSlicePointingCluster, candidatePointingCluster) || this->IsNode(inSlicePointingCluster, candidatePointingCluster))
271  {
272  return true;
273  }
274 
275  return false;
276 }
277 
278 //------------------------------------------------------------------------------------------------------------------------------------------
279 
280 bool EventSlicingTool::PassProximity(const Cluster *const pClusterInSlice, const Cluster *const pCandidateCluster) const
281 {
282  for (const auto &orderedList1 : pClusterInSlice->GetOrderedCaloHitList())
283  {
284  for (const CaloHit *const pCaloHit1 : *(orderedList1.second))
285  {
286  const CartesianVector &positionVector1(pCaloHit1->GetPositionVector());
287 
288  for (const auto &orderedList2 : pCandidateCluster->GetOrderedCaloHitList())
289  {
290  for (const CaloHit *const pCaloHit2 : *(orderedList2.second))
291  {
292  if ((positionVector1 - pCaloHit2->GetPositionVector()).GetMagnitudeSquared() < m_maxHitSeparationSquared)
293  return true;
294  }
295  }
296  }
297  }
298 
299  return false;
300 }
301 
302 //------------------------------------------------------------------------------------------------------------------------------------------
303 
305  const Cluster *const pConeCluster, const Cluster *const pNearbyCluster, const ThreeDSlidingConeFitResultMap &showerConeFitResults) const
306 {
307  ThreeDSlidingConeFitResultMap::const_iterator fitIter = showerConeFitResults.find(pConeCluster);
308 
309  if (showerConeFitResults.end() == fitIter)
310  return false;
311 
312  float clusterLength(0.f);
313  SimpleConeList simpleConeList;
314 
315  try
316  {
317  const ThreeDSlidingConeFitResult &slidingConeFitResult3D(fitIter->second);
318  const ThreeDSlidingFitResult &slidingFitResult3D(slidingConeFitResult3D.GetSlidingFitResult());
319  slidingConeFitResult3D.GetSimpleConeList(m_nConeFitLayers, m_nConeFits, CONE_BOTH_DIRECTIONS, simpleConeList);
320  clusterLength = (slidingFitResult3D.GetGlobalMaxLayerPosition() - slidingFitResult3D.GetGlobalMinLayerPosition()).GetMagnitude();
321  }
322  catch (const StatusCodeException &)
323  {
324  return false;
325  }
326 
327  for (const SimpleCone &simpleCone : simpleConeList)
328  {
329  const float coneLength(std::min(m_coneLengthMultiplier * clusterLength, m_maxConeLength));
330 
331  if (simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength, m_coneTanHalfAngle1) < m_coneBoundedFraction1)
332  continue;
333 
334  if (simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength, m_coneTanHalfAngle2) < m_coneBoundedFraction2)
335  continue;
336 
337  return true;
338  }
339 
340  return false;
341 }
342 
343 //------------------------------------------------------------------------------------------------------------------------------------------
344 
346 {
347  return (this->CheckClosestApproach(cluster1.GetInnerVertex(), cluster2.GetInnerVertex()) ||
348  this->CheckClosestApproach(cluster1.GetOuterVertex(), cluster2.GetInnerVertex()) ||
349  this->CheckClosestApproach(cluster1.GetInnerVertex(), cluster2.GetOuterVertex()) ||
350  this->CheckClosestApproach(cluster1.GetOuterVertex(), cluster2.GetOuterVertex()));
351 }
352 
353 //------------------------------------------------------------------------------------------------------------------------------------------
354 
356 {
357  CartesianVector intersectionPoint(0.f, 0.f, 0.f);
358  float displacement1(std::numeric_limits<float>::max()), displacement2(std::numeric_limits<float>::max());
359 
360  try
361  {
362  LArPointingClusterHelper::GetIntersection(vertex1, vertex2, intersectionPoint, displacement1, displacement2);
363  }
364  catch (const StatusCodeException &)
365  {
366  return false;
367  }
368 
369  const CartesianVector approach1(vertex1.GetPosition() + vertex1.GetDirection() * displacement1);
370  const CartesianVector approach2(vertex2.GetPosition() + vertex2.GetDirection() * displacement2);
371  const float closestApproach((approach1 - approach2).GetMagnitude());
372 
373  return ((closestApproach < m_maxClosestApproach) && (std::fabs(displacement1) < m_maxInterceptDistance) &&
374  (std::fabs(displacement2) < m_maxInterceptDistance));
375 }
376 
377 //------------------------------------------------------------------------------------------------------------------------------------------
378 
379 bool EventSlicingTool::IsNode(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
380 {
397 }
398 
399 //------------------------------------------------------------------------------------------------------------------------------------------
400 
401 bool EventSlicingTool::IsEmission(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
402 {
419 }
420 
421 //------------------------------------------------------------------------------------------------------------------------------------------
422 
423 void EventSlicingTool::CreateSlices(const ClusterSliceList &clusterSliceList, SliceList &sliceList, ClusterToSliceIndexMap &clusterToSliceIndexMap) const
424 {
425  unsigned int index(0);
426 
427  for (const ClusterVector &clusterList : clusterSliceList)
428  {
429  for (const Cluster *const pCluster3D : clusterList)
430  {
431  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster3D))
432  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
433 
434  if (!clusterToSliceIndexMap.insert(ClusterToSliceIndexMap::value_type(pCluster3D, index)).second)
435  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
436  }
437 
438  sliceList.push_back(Slice());
439  ++index;
440  }
441 }
442 
443 //------------------------------------------------------------------------------------------------------------------------------------------
444 
445 void EventSlicingTool::CopyPfoHitsToSlices(const ClusterToSliceIndexMap &clusterToSliceIndexMap, const ClusterToPfoMap &clusterToPfoMap,
446  SliceList &sliceList, ClusterSet &assignedClusters) const
447 {
448  ClusterList clusterList;
449  for (const auto &mapEntry : clusterToSliceIndexMap)
450  clusterList.push_back(mapEntry.first);
451  clusterList.sort(LArClusterHelper::SortByNHits);
452 
453  for (const Cluster *const pCluster3D : clusterList)
454  {
455  const unsigned int index(clusterToSliceIndexMap.at(pCluster3D));
456 
457  const Pfo *const pPfo(clusterToPfoMap.at(pCluster3D));
458  Slice &slice(sliceList.at(index));
459 
460  ClusterList clusters2D;
461  LArPfoHelper::GetTwoDClusterList(pPfo, clusters2D);
462 
463  for (const Cluster *const pCluster2D : clusters2D)
464  {
465  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster2D));
466 
467  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
468  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
469 
470  CaloHitList &targetList((TPC_VIEW_U == hitType) ? slice.m_caloHitListU : (TPC_VIEW_V == hitType) ? slice.m_caloHitListV : slice.m_caloHitListW);
471 
472  pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
473  targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
474 
475  if (!assignedClusters.insert(pCluster2D).second)
476  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
477  }
478  }
479 }
480 
481 //------------------------------------------------------------------------------------------------------------------------------------------
482 
483 void EventSlicingTool::GetRemainingClusters(const Algorithm *const pAlgorithm, const HitTypeToNameMap &clusterListNames,
484  const ClusterSet &assignedClusters, ClusterList &remainingClusters) const
485 {
486  this->GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_U), assignedClusters, remainingClusters);
487  this->GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_V), assignedClusters, remainingClusters);
488  this->GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_W), assignedClusters, remainingClusters);
489 }
490 
491 //------------------------------------------------------------------------------------------------------------------------------------------
492 
493 void EventSlicingTool::GetRemainingClusters(const Algorithm *const pAlgorithm, const std::string &clusterListName,
494  const ClusterSet &assignedClusters, ClusterList &remainingClusters) const
495 {
496  const ClusterList *pClusterList(nullptr);
497  PANDORA_THROW_RESULT_IF_AND_IF(
498  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*pAlgorithm, clusterListName, pClusterList));
499 
500  if (!pClusterList || pClusterList->empty())
501  {
502  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
503  std::cout << "EventSlicingTool: unable to find cluster list " << clusterListName << std::endl;
504 
505  return;
506  }
507 
508  for (const Cluster *const pCluster2D : *pClusterList)
509  {
510  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster2D));
511 
512  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
513  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
514 
515  if (assignedClusters.count(pCluster2D))
516  continue;
517 
518  if (remainingClusters.end() != std::find(remainingClusters.begin(), remainingClusters.end(), pCluster2D))
519  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
520 
521  remainingClusters.push_back(pCluster2D);
522  }
523 }
524 
525 //------------------------------------------------------------------------------------------------------------------------------------------
526 
528  const ClusterList &remainingClusters, const ClusterToSliceIndexMap &clusterToSliceIndexMap, SliceList &sliceList) const
529 {
530  PointToSliceIndexMap pointToSliceIndexMap;
531 
532  try
533  {
534  PointList pointsU, pointsV, pointsW;
535  this->GetKDTreeEntries2D(sliceList, pointsU, pointsV, pointsW, pointToSliceIndexMap);
536 
538  this->GetKDTreeEntries3D(clusterToSliceIndexMap, pointsU, pointsV, pointsW, pointToSliceIndexMap);
539 
540  pointsU.sort(EventSlicingTool::SortPoints);
541  pointsV.sort(EventSlicingTool::SortPoints);
542  pointsW.sort(EventSlicingTool::SortPoints);
543 
544  PointKDNode2DList kDNode2DListU, kDNode2DListV, kDNode2DListW;
545  KDTreeBox boundingRegionU = fill_and_bound_2d_kd_tree(pointsU, kDNode2DListU);
546  KDTreeBox boundingRegionV = fill_and_bound_2d_kd_tree(pointsV, kDNode2DListV);
547  KDTreeBox boundingRegionW = fill_and_bound_2d_kd_tree(pointsW, kDNode2DListW);
548 
549  PointKDTree2D kdTreeU, kdTreeV, kdTreeW;
550  kdTreeU.build(kDNode2DListU, boundingRegionU);
551  kdTreeV.build(kDNode2DListV, boundingRegionV);
552  kdTreeW.build(kDNode2DListW, boundingRegionW);
553 
554  ClusterVector sortedRemainingClusters(remainingClusters.begin(), remainingClusters.end());
555  std::sort(sortedRemainingClusters.begin(), sortedRemainingClusters.end(), LArClusterHelper::SortByNHits);
556 
557  for (const Cluster *const pCluster2D : sortedRemainingClusters)
558  {
559  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster2D));
560 
561  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
562  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
563 
564  PointKDTree2D &kdTree((TPC_VIEW_U == hitType) ? kdTreeU : (TPC_VIEW_V == hitType) ? kdTreeV : kdTreeW);
565  const PointKDNode2D *pBestResultPoint(this->MatchClusterToSlice(pCluster2D, kdTree));
566 
567  if (!pBestResultPoint)
568  continue;
569 
570  Slice &slice(sliceList.at(pointToSliceIndexMap.at(pBestResultPoint->data)));
571  CaloHitList &targetList((TPC_VIEW_U == hitType) ? slice.m_caloHitListU : (TPC_VIEW_V == hitType) ? slice.m_caloHitListV : slice.m_caloHitListW);
572 
573  pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
574  targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
575  }
576  }
577  catch (...)
578  {
579  std::cout << "EventSlicingTool::AssignRemainingHitsToSlices - exception " << std::endl;
580  for (const auto &pointMap : pointToSliceIndexMap)
581  delete pointMap.first;
582  throw;
583  }
584 
585  for (const auto &pointMap : pointToSliceIndexMap)
586  delete pointMap.first;
587 }
588 
589 //------------------------------------------------------------------------------------------------------------------------------------------
590 
592  const SliceList &sliceList, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
593 {
594  unsigned int sliceIndex(0);
595 
596  for (const Slice &slice : sliceList)
597  {
598  for (const CaloHit *const pCaloHit : slice.m_caloHitListU)
599  {
600  const CartesianVector *const pPoint(new CartesianVector(pCaloHit->GetPositionVector()));
601  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
602  pointsU.push_back(pPoint);
603  }
604 
605  for (const CaloHit *const pCaloHit : slice.m_caloHitListV)
606  {
607  const CartesianVector *const pPoint(new CartesianVector(pCaloHit->GetPositionVector()));
608  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
609  pointsV.push_back(pPoint);
610  }
611 
612  for (const CaloHit *const pCaloHit : slice.m_caloHitListW)
613  {
614  const CartesianVector *const pPoint(new CartesianVector(pCaloHit->GetPositionVector()));
615  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
616  pointsW.push_back(pPoint);
617  }
618 
619  ++sliceIndex;
620  }
621 }
622 
623 //------------------------------------------------------------------------------------------------------------------------------------------
624 
625 void EventSlicingTool::GetKDTreeEntries3D(const ClusterToSliceIndexMap &clusterToSliceIndexMap, PointList &pointsU, PointList &pointsV,
626  PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
627 {
628  ClusterList clusterList;
629  for (const auto &mapEntry : clusterToSliceIndexMap)
630  clusterList.push_back(mapEntry.first);
631  clusterList.sort(LArClusterHelper::SortByNHits);
632 
633  for (const Cluster *const pCluster3D : clusterList)
634  {
635  const unsigned int sliceIndex(clusterToSliceIndexMap.at(pCluster3D));
636 
637  CaloHitList caloHitList;
638  pCluster3D->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
639 
640  for (const CaloHit *const pCaloHit3D : caloHitList)
641  {
642  if (TPC_3D != pCaloHit3D->GetHitType())
643  throw StatusCodeException(STATUS_CODE_FAILURE);
644 
645  const CartesianVector &position3D(pCaloHit3D->GetPositionVector());
646 
647  const CartesianVector *const pProjectionU(
648  new CartesianVector(LArGeometryHelper::ProjectPosition(this->GetPandora(), position3D, TPC_VIEW_U)));
649  const CartesianVector *const pProjectionV(
650  new CartesianVector(LArGeometryHelper::ProjectPosition(this->GetPandora(), position3D, TPC_VIEW_V)));
651  const CartesianVector *const pProjectionW(
652  new CartesianVector(LArGeometryHelper::ProjectPosition(this->GetPandora(), position3D, TPC_VIEW_W)));
653 
654  pointsU.push_back(pProjectionU);
655  pointsV.push_back(pProjectionV);
656  pointsW.push_back(pProjectionW);
657 
658  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionU, sliceIndex));
659  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionV, sliceIndex));
660  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionW, sliceIndex));
661  }
662  }
663 }
664 
665 //------------------------------------------------------------------------------------------------------------------------------------------
666 
667 const EventSlicingTool::PointKDNode2D *EventSlicingTool::MatchClusterToSlice(const Cluster *const pCluster2D, PointKDTree2D &kdTree) const
668 {
669  PointList clusterPointList;
670  const PointKDNode2D *pBestResultPoint(nullptr);
671 
672  try
673  {
674  clusterPointList.push_back(new CartesianVector(pCluster2D->GetCentroid(pCluster2D->GetInnerPseudoLayer())));
675  clusterPointList.push_back(new CartesianVector(pCluster2D->GetCentroid(pCluster2D->GetOuterPseudoLayer())));
676  clusterPointList.push_back(new CartesianVector(
677  (pCluster2D->GetCentroid(pCluster2D->GetInnerPseudoLayer()) + pCluster2D->GetCentroid(pCluster2D->GetOuterPseudoLayer())) * 0.5f));
678 
679  float bestDistance(std::numeric_limits<float>::max());
680 
681  for (const CartesianVector *const pClusterPoint : clusterPointList)
682  {
683  const PointKDNode2D *pResultPoint(nullptr);
684  float resultDistance(std::numeric_limits<float>::max());
685  const PointKDNode2D targetPoint(pClusterPoint, pClusterPoint->GetX(), pClusterPoint->GetZ());
686  kdTree.findNearestNeighbour(targetPoint, pResultPoint, resultDistance);
687 
688  if (pResultPoint && (resultDistance < bestDistance))
689  {
690  pBestResultPoint = pResultPoint;
691  bestDistance = resultDistance;
692  }
693  }
694  }
695  catch (...)
696  {
697  std::cout << "EventSlicingTool::MatchClusterToSlice - exception " << std::endl;
698  for (const CartesianVector *const pPoint : clusterPointList)
699  delete pPoint;
700  throw;
701  }
702 
703  for (const CartesianVector *const pPoint : clusterPointList)
704  delete pPoint;
705 
706  return pBestResultPoint;
707 }
708 
709 //------------------------------------------------------------------------------------------------------------------------------------------
710 
711 bool EventSlicingTool::SortPoints(const CartesianVector *const pLhs, const CartesianVector *const pRhs)
712 {
713  const CartesianVector deltaPosition(*pRhs - *pLhs);
714 
715  if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
716  return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
717 
718  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
719  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
720 
721  return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
722 }
723 
724 //------------------------------------------------------------------------------------------------------------------------------------------
725 
726 StatusCode EventSlicingTool::ReadSettings(const TiXmlHandle xmlHandle)
727 {
728  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "TrackPfoListName", m_trackPfoListName));
729 
730  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "ShowerPfoListName", m_showerPfoListName));
731 
732  PANDORA_RETURN_RESULT_IF_AND_IF(
733  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinHitsPer3DCluster", m_minHitsPer3DCluster));
734 
735  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
736  XmlHelper::ReadValue(xmlHandle, "Min3DHitsToSeedNewSlice", m_min3DHitsToSeedNewSlice));
737 
738  PANDORA_RETURN_RESULT_IF_AND_IF(
739  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
740 
741  PANDORA_RETURN_RESULT_IF_AND_IF(
742  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UsePointingAssociation", m_usePointingAssociation));
743 
744  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
745  XmlHelper::ReadValue(xmlHandle, "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
746 
747  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
748  XmlHelper::ReadValue(xmlHandle, "MaxVertexLongitudinalDistance", m_maxVertexLongitudinalDistance));
749 
750  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
751  XmlHelper::ReadValue(xmlHandle, "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
752 
753  PANDORA_RETURN_RESULT_IF_AND_IF(
754  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VertexAngularAllowance", m_vertexAngularAllowance));
755 
756  PANDORA_RETURN_RESULT_IF_AND_IF(
757  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClosestApproach", m_maxClosestApproach));
758 
759  PANDORA_RETURN_RESULT_IF_AND_IF(
760  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxInterceptDistance", m_maxInterceptDistance));
761 
762  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
763  XmlHelper::ReadValue(xmlHandle, "UseProximityAssociation", m_useProximityAssociation));
764 
765  float maxHitSeparation = std::sqrt(m_maxHitSeparationSquared);
766  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxHitSeparation", maxHitSeparation));
767  m_maxHitSeparationSquared = maxHitSeparation * maxHitSeparation;
768 
769  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
770  XmlHelper::ReadValue(xmlHandle, "UseShowerConeAssociation", m_useShowerConeAssociation));
771 
772  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NConeFitLayers", m_nConeFitLayers));
773 
774  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NConeFits", m_nConeFits));
775 
776  PANDORA_RETURN_RESULT_IF_AND_IF(
777  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeLengthMultiplier", m_coneLengthMultiplier));
778 
779  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxConeLength", m_maxConeLength));
780 
781  PANDORA_RETURN_RESULT_IF_AND_IF(
782  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeTanHalfAngle1", m_coneTanHalfAngle1));
783 
784  PANDORA_RETURN_RESULT_IF_AND_IF(
785  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeBoundedFraction1", m_coneBoundedFraction1));
786 
787  PANDORA_RETURN_RESULT_IF_AND_IF(
788  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeTanHalfAngle2", m_coneTanHalfAngle2));
789 
790  PANDORA_RETURN_RESULT_IF_AND_IF(
791  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ConeBoundedFraction2", m_coneBoundedFraction2));
792 
793  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
794  XmlHelper::ReadValue(xmlHandle, "Use3DProjectionsInHitPickUp", m_use3DProjectionsInHitPickUp));
795 
796  return STATUS_CODE_SUCCESS;
797 }
798 
799 } // namespace lar_content
void GetThreeDClusters(const pandora::Algorithm *const pAlgorithm, const std::string &pfoListName, pandora::ClusterList &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
Get the 3D clusters from a specified list of pfos, storing the 3D clusters in the provided list and p...
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
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, then pulse-height.
void GetClusterSliceList(const pandora::ClusterList &trackClusters3D, const pandora::ClusterList &showerClusters3D, ClusterSliceList &clusterSliceList) const
Divide the provided lists of 3D track and shower clusters into slices.
unsigned int m_min3DHitsToSeedNewSlice
The minimum number of hits in a 3D cluster to seed a new slice.
void CopyPfoHitsToSlices(const ClusterToSliceIndexMap &clusterToSliceIndexMap, const ClusterToPfoMap &clusterToPfoMap, SlicingAlgorithm::SliceList &sliceList, pandora::ClusterSet &assignedClusters) const
Use 3D clusters in the cluster slice list, find their parent pfos and assign all hits in all 2D clust...
Header file for the kd tree linker algo template class.
Header file for the pfo helper class.
float m_maxHitSeparationSquared
Proximity association: max distance allowed between the closest pair of hits.
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
float m_coneTanHalfAngle2
The cone tan half angle to use when calculating bounded cluster fractions 2.
SlicingAlgorithm::Slice Slice
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
float m_maxVertexTransverseDistance
Pointing association check: max transverse distance cut.
static bool IsEmission(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
Whether pointing vertex is emitted from a given position.
void AssignRemainingHitsToSlices(const pandora::ClusterList &remainingClusters, const ClusterToSliceIndexMap &clusterToSliceIndexMap, SlicingAlgorithm::SliceList &sliceList) const
Use the list of remaining 2D clusters to assign all remaining 2D hits to existing slices in the slice...
float m_coneBoundedFraction2
The minimum cluster bounded fraction for association 2.
std::string m_showerPfoListName
The name of the input shower pfo list.
static void GetIntersection(const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex, pandora::CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
Get intersection of two vertices.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
Class that implements the KDTree partition of 2D space and a closest point search algorithm...
Box structure used to define 2D field. It&#39;s used in KDTree building step to divide the detector space...
void GetRemainingClusters(const pandora::Algorithm *const pAlgorithm, const SlicingAlgorithm::HitTypeToNameMap &clusterListNames, const pandora::ClusterSet &assignedClusters, pandora::ClusterList &remainingClusters) const
Get the list of 2D clusters with hits yets to be assigned to slices.
std::vector< SimpleCone > SimpleConeList
SlicingAlgorithm::SliceList SliceList
bool PassShowerCone(const pandora::Cluster *const pConeCluster, const pandora::Cluster *const pNearbyCluster, const ThreeDSlidingConeFitResultMap &showerConeFitResults) const
Compare the provided clusters to assess whether they are associated via cone fits to the shower clust...
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
bool PassPointing(const pandora::Cluster *const pClusterInSlice, const pandora::Cluster *const pCandidateCluster, const ThreeDSlidingFitResultMap &trackFitResults) const
Compare the provided clusters to assess whether they are associated via pointing (checks association ...
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
unsigned int m_minHitsPer3DCluster
The minimum number of hits in a 3D cluster to warrant consideration in slicing.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
float m_coneTanHalfAngle1
The cone tan half angle to use when calculating bounded cluster fractions 1.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void CollectAssociatedClusters(const pandora::Cluster *const pClusterInSlice, const pandora::ClusterVector &candidateClusters, const ThreeDSlidingFitResultMap &trackFitResults, const ThreeDSlidingConeFitResultMap &showerConeFitResults, pandora::ClusterVector &clusterSlice, pandora::ClusterSet &usedClusters) const
Collect all clusters associated with a provided cluster.
const PointKDNode2D * MatchClusterToSlice(const pandora::Cluster *const pCluster2D, PointKDTree2D &kdTree) const
Use the provided kd tree to efficiently identify the most appropriate slice for the provided 2D clust...
Header file for the lar three dimensional sliding cone fit result class.
void GetSimpleConeList(const unsigned int nLayersForConeFit, const unsigned int nCones, const ConeSelection coneSelection, SimpleConeList &simpleConeList) const
Get the list of simple cones fitted to the three dimensional cluster.
float m_maxVertexLongitudinalDistance
Pointing association check: max longitudinal distance cut.
void findNearestNeighbour(const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeInfoT< DATA, DIM > *&result, float &distance)
findNearestNeighbour
Data stored in each KDTree node. The dim1/dim2 fields are usually the duplication of some PFRecHit va...
std::unordered_map< const pandora::CartesianVector *, unsigned int > PointToSliceIndexMap
std::string m_trackPfoListName
The name of the input track pfo list.
Header file for the geometry helper class.
bool m_useProximityAssociation
Whether to use proximity association.
float m_maxClosestApproach
Pointing association: max distance of closest approach between straight line fits.
std::unordered_map< const pandora::Cluster *, ThreeDSlidingFitResult > ThreeDSlidingFitResultMap
bool IsNode(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check whether a pair of pointing clusters are nodally associated.
static bool SortPoints(const pandora::CartesianVector *const pLhs, const pandora::CartesianVector *const pRhs)
Sort points (use Z, followed by X, followed by Y)
Header file for the cluster helper class.
bool m_usePointingAssociation
Whether to use pointing association.
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
const Vertex & GetOuterVertex() const
Get the outer vertex.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM >> &eltList, const KDTreeBoxT< DIM > &region)
Build the KD tree from the &quot;eltList&quot; in the space define by &quot;region&quot;.
const Vertex & GetInnerVertex() const
Get the inner vertex.
Header file for the event slicing tool class.
bool PassProximity(const pandora::Cluster *const pClusterInSlice, const pandora::Cluster *const pCandidateCluster) const
Compare the provided clusters to assess whether they are associated via pointing. ...
j template void())
Definition: json.hpp:3108
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
pandora::CaloHitList m_caloHitListU
The u calo hit list.
std::vector< pandora::ClusterVector > ClusterSliceList
Header file for the lar three dimensional sliding fit result class.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
void CopyAllHitsToSingleSlice(const pandora::Algorithm *const pAlgorithm, const SlicingAlgorithm::HitTypeToNameMap &caloHitListNames, SlicingAlgorithm::SliceList &sliceList) const
Copy all the input hits in an event into a single slice.
std::unordered_map< const pandora::Cluster *, ThreeDSlidingConeFitResult > ThreeDSlidingConeFitResultMap
std::list< const pandora::CartesianVector * > PointList
SlicingAlgorithm::HitTypeToNameMap HitTypeToNameMap
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
Definition: reco_sbnd.fcl:182
bool CheckClosestApproach(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check closest approach metrics for a pair of pointing clusters.
std::vector< PointKDNode2D > PointKDNode2DList
std::unordered_map< const pandora::Cluster *, unsigned int > ClusterToSliceIndexMap
pandora::CaloHitList m_caloHitListW
The w calo hit list.
float m_maxInterceptDistance
Pointing association: max distance from cluster vertex to point of closest approach.
void RunSlicing(const pandora::Algorithm *const pAlgorithm, const SlicingAlgorithm::HitTypeToNameMap &caloHitListNames, const SlicingAlgorithm::HitTypeToNameMap &clusterListNames, SlicingAlgorithm::SliceList &sliceList)
Run the slicing tool.
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
float m_minVertexLongitudinalDistance
Pointing association check: min longitudinal distance cut.
bool IsEmission(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check whether a pair of pointing clusters are consistent with an emission.
bool m_use3DProjectionsInHitPickUp
Whether to include 3D cluster projections when assigning remaining clusters to slices.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
bool m_useShowerConeAssociation
Whether to use shower cone association.
float m_vertexAngularAllowance
Pointing association check: pointing angular allowance in degrees.
pandora::CaloHitList m_caloHitListV
The v calo hit list.
void GetKDTreeEntries2D(const SlicingAlgorithm::SliceList &sliceList, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
Use projections of 3D hits already assigned to slices to populate kd trees to aid assignment of remai...
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
void GetKDTreeEntries3D(const ClusterToSliceIndexMap &clusterToSliceIndexMap, PointList &pointsU, PointList &pointsV, PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
Use 2D hits already assigned to slices to populate kd trees to aid assignment of remaining clusters...
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
void CreateSlices(const ClusterSliceList &clusterSliceList, SlicingAlgorithm::SliceList &sliceList, ClusterToSliceIndexMap &clusterToSliceIndexMap) const
Create new slices for each of the groupings of 3D clusters in the provided cluster slice list...
BEGIN_PROLOG could also be cout
float m_coneBoundedFraction1
The minimum cluster bounded fraction for association 1.
static bool IsNode(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxTransverseDistance)
Whether pointing vertex is adjacent to a given position.
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.