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