LArSoft  v06_85_00
Liquid Argon Software toolkit - http://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 
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, const HitTypeToNameMap &clusterListNames,
63  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, !=, PandoraContentApi::GetList(*pAlgorithm,
107  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, !=, PandoraContentApi::GetList(*pAlgorithm,
111  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, !=, PandoraContentApi::GetList(*pAlgorithm,
115  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) slice.m_caloHitListU = *pCaloHitListU;
123  if (pCaloHitListV) slice.m_caloHitListV = *pCaloHitListV;
124  if (pCaloHitListW) slice.m_caloHitListW = *pCaloHitListW;
125  }
126 }
127 
128 //------------------------------------------------------------------------------------------------------------------------------------------
129 
130 void EventSlicingTool::GetThreeDClusters(const Algorithm *const pAlgorithm, const std::string &pfoListName, ClusterList &clusters3D,
131  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,
168  ClusterSliceList &clusterSliceList) const
169 {
170  const float layerPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
171 
172  ThreeDSlidingFitResultMap trackFitResults;
173 
174  for (const Cluster *const pCluster3D : trackClusters3D)
175  {
176  try {trackFitResults.insert(ThreeDSlidingFitResultMap::value_type(pCluster3D, ThreeDSlidingFitResult(pCluster3D, m_halfWindowLayers, layerPitch)));}
177  catch (StatusCodeException &) {std::cout << "EventSlicingTool: ThreeDSlidingFitResult failure for track cluster." << std::endl;}
178  }
179 
180  ThreeDSlidingConeFitResultMap showerConeFitResults;
181 
182  for (const Cluster *const pCluster3D : showerClusters3D)
183  {
184  try {showerConeFitResults.insert(ThreeDSlidingConeFitResultMap::value_type(pCluster3D, ThreeDSlidingConeFitResult(pCluster3D, m_halfWindowLayers, layerPitch)));}
185  catch (StatusCodeException &) {std::cout << "EventSlicingTool: ThreeDSlidingConeFitResult failure for shower cluster." << std::endl;}
186  }
187 
188  ClusterVector sortedClusters3D(trackClusters3D.begin(), trackClusters3D.end());
189  sortedClusters3D.insert(sortedClusters3D.end(), showerClusters3D.begin(), showerClusters3D.end());
190  std::sort(sortedClusters3D.begin(), sortedClusters3D.end(), LArClusterHelper::SortByNHits);
191 
192  ClusterSet usedClusters;
193 
194  for (const Cluster *const pCluster3D : sortedClusters3D)
195  {
196  if (usedClusters.count(pCluster3D))
197  continue;
198 
199  if (pCluster3D->GetNCaloHits() < m_min3DHitsToSeedNewSlice)
200  continue;
201 
202  clusterSliceList.push_back(ClusterVector(1, pCluster3D));
203  usedClusters.insert(pCluster3D);
204 
205  ClusterVector &clusterSlice(clusterSliceList.back());
206  this->CollectAssociatedClusters(pCluster3D, sortedClusters3D, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
207  }
208 }
209 
210 //------------------------------------------------------------------------------------------------------------------------------------------
211 
212 void EventSlicingTool::CollectAssociatedClusters(const Cluster *const pClusterInSlice, const ClusterVector &candidateClusters,
213  const ThreeDSlidingFitResultMap &trackFitResults, const ThreeDSlidingConeFitResultMap &showerConeFitResults, ClusterVector &clusterSlice,
214  ClusterSet &usedClusters) const
215 {
216  ClusterVector addedClusters;
217 
218  for (const Cluster *const pCandidateCluster : candidateClusters)
219  {
220  if (usedClusters.count(pCandidateCluster) || (pClusterInSlice == pCandidateCluster))
221  continue;
222 
223  if ((m_usePointingAssociation && this->PassPointing(pClusterInSlice, pCandidateCluster, trackFitResults)) ||
224  (m_useProximityAssociation && this->PassProximity(pClusterInSlice, pCandidateCluster)) ||
225  (m_useShowerConeAssociation && (this->PassShowerCone(pClusterInSlice, pCandidateCluster, showerConeFitResults) || this->PassShowerCone(pCandidateCluster, pClusterInSlice, showerConeFitResults))) )
226  {
227  addedClusters.push_back(pCandidateCluster);
228  (void) usedClusters.insert(pCandidateCluster);
229  }
230  }
231 
232  clusterSlice.insert(clusterSlice.end(), addedClusters.begin(), addedClusters.end());
233 
234  for (const Cluster *const pAddedCluster : addedClusters)
235  this->CollectAssociatedClusters(pAddedCluster, candidateClusters, trackFitResults, showerConeFitResults, clusterSlice, usedClusters);
236 }
237 
238 //------------------------------------------------------------------------------------------------------------------------------------------
239 
240 bool EventSlicingTool::PassPointing(const Cluster *const pClusterInSlice, const Cluster *const pCandidateCluster, const ThreeDSlidingFitResultMap &trackFitResults) const
241 {
242  ThreeDSlidingFitResultMap::const_iterator inSliceIter = trackFitResults.find(pClusterInSlice);
243  ThreeDSlidingFitResultMap::const_iterator candidateIter = trackFitResults.find(pCandidateCluster);
244 
245  if ((trackFitResults.end() == inSliceIter) || (trackFitResults.end() == candidateIter))
246  return false;
247 
248  const LArPointingCluster inSlicePointingCluster(inSliceIter->second);
249  const LArPointingCluster candidatePointingCluster(candidateIter->second);
250 
251  if (this->CheckClosestApproach(inSlicePointingCluster, candidatePointingCluster) ||
252  this->IsEmission(inSlicePointingCluster, candidatePointingCluster) ||
253  this->IsNode(inSlicePointingCluster, candidatePointingCluster))
254  {
255  return true;
256  }
257 
258  return false;
259 }
260 
261 //------------------------------------------------------------------------------------------------------------------------------------------
262 
263 bool EventSlicingTool::PassProximity(const Cluster *const pClusterInSlice, const Cluster *const pCandidateCluster) const
264 {
265  for (const auto &orderedList1 : pClusterInSlice->GetOrderedCaloHitList())
266  {
267  for (const CaloHit *const pCaloHit1 : *(orderedList1.second))
268  {
269  const CartesianVector &positionVector1(pCaloHit1->GetPositionVector());
270 
271  for (const auto &orderedList2 : pCandidateCluster->GetOrderedCaloHitList())
272  {
273  for (const CaloHit *const pCaloHit2 : *(orderedList2.second))
274  {
275  if ((positionVector1 - pCaloHit2->GetPositionVector()).GetMagnitudeSquared() < m_maxHitSeparationSquared)
276  return true;
277  }
278  }
279  }
280  }
281 
282  return false;
283 }
284 
285 //------------------------------------------------------------------------------------------------------------------------------------------
286 
287 bool EventSlicingTool::PassShowerCone(const Cluster *const pConeCluster, const Cluster *const pNearbyCluster, const ThreeDSlidingConeFitResultMap &showerConeFitResults) const
288 {
289  ThreeDSlidingConeFitResultMap::const_iterator fitIter = showerConeFitResults.find(pConeCluster);
290 
291  if (showerConeFitResults.end() == fitIter)
292  return false;
293 
294  float clusterLength(0.f);
295  SimpleConeList simpleConeList;
296 
297  try
298  {
299  const ThreeDSlidingConeFitResult &slidingConeFitResult3D(fitIter->second);
300  const ThreeDSlidingFitResult &slidingFitResult3D(slidingConeFitResult3D.GetSlidingFitResult());
301  slidingConeFitResult3D.GetSimpleConeList(m_nConeFitLayers, m_nConeFits, CONE_BOTH_DIRECTIONS, simpleConeList);
302  clusterLength = (slidingFitResult3D.GetGlobalMaxLayerPosition() - slidingFitResult3D.GetGlobalMinLayerPosition()).GetMagnitude();
303  }
304  catch (const StatusCodeException &)
305  {
306  return false;
307  }
308 
309  for (const SimpleCone &simpleCone : simpleConeList)
310  {
311  const float coneLength(std::min(m_coneLengthMultiplier * clusterLength, m_maxConeLength));
312 
313  if (simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength, m_coneTanHalfAngle1) < m_coneBoundedFraction1)
314  continue;
315 
316  if (simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength, m_coneTanHalfAngle2) < m_coneBoundedFraction2)
317  continue;
318 
319  return true;
320  }
321 
322  return false;
323 }
324 
325 //------------------------------------------------------------------------------------------------------------------------------------------
326 
328 {
329  return (this->CheckClosestApproach(cluster1.GetInnerVertex(), cluster2.GetInnerVertex()) ||
330  this->CheckClosestApproach(cluster1.GetOuterVertex(), cluster2.GetInnerVertex()) ||
331  this->CheckClosestApproach(cluster1.GetInnerVertex(), cluster2.GetOuterVertex()) ||
332  this->CheckClosestApproach(cluster1.GetOuterVertex(), cluster2.GetOuterVertex()));
333 }
334 
335 //------------------------------------------------------------------------------------------------------------------------------------------
336 
338 {
339  CartesianVector intersectionPoint(0.f, 0.f, 0.f);
340  float displacement1(std::numeric_limits<float>::max()), displacement2(std::numeric_limits<float>::max());
341 
342  try
343  {
344  LArPointingClusterHelper::GetIntersection(vertex1, vertex2, intersectionPoint, displacement1, displacement2);
345  }
346  catch (const StatusCodeException &)
347  {
348  return false;
349  }
350 
351  const CartesianVector approach1(vertex1.GetPosition() + vertex1.GetDirection() * displacement1);
352  const CartesianVector approach2(vertex2.GetPosition() + vertex2.GetDirection() * displacement2);
353  const float closestApproach((approach1 - approach2).GetMagnitude());
354 
355  return ((closestApproach < m_maxClosestApproach) && (std::fabs(displacement1) < m_maxInterceptDistance) && (std::fabs(displacement2) < m_maxInterceptDistance));
356 }
357 
358 //------------------------------------------------------------------------------------------------------------------------------------------
359 
360 bool EventSlicingTool::IsNode(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
361 {
370 }
371 
372 //------------------------------------------------------------------------------------------------------------------------------------------
373 
374 bool EventSlicingTool::IsEmission(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
375 {
384 }
385 
386 //------------------------------------------------------------------------------------------------------------------------------------------
387 
388 void EventSlicingTool::CreateSlices(const ClusterSliceList &clusterSliceList, SliceList &sliceList, ClusterToSliceIndexMap &clusterToSliceIndexMap) const
389 {
390  unsigned int index(0);
391 
392  for (const ClusterVector &clusterList : clusterSliceList)
393  {
394  for (const Cluster *const pCluster3D : clusterList)
395  {
396  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster3D))
397  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
398 
399  if (!clusterToSliceIndexMap.insert(ClusterToSliceIndexMap::value_type(pCluster3D, index)).second)
400  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
401  }
402 
403  sliceList.push_back(Slice());
404  ++index;
405  }
406 }
407 
408 //------------------------------------------------------------------------------------------------------------------------------------------
409 
410 void EventSlicingTool::CopyPfoHitsToSlices(const ClusterToSliceIndexMap &clusterToSliceIndexMap, const ClusterToPfoMap &clusterToPfoMap,
411  SliceList &sliceList, ClusterSet &assignedClusters) const
412 {
413  ClusterList clusterList;
414  for (const auto &mapEntry : clusterToSliceIndexMap) clusterList.push_back(mapEntry.first);
415  clusterList.sort(LArClusterHelper::SortByNHits);
416 
417  for (const Cluster *const pCluster3D : clusterList)
418  {
419  const unsigned int index(clusterToSliceIndexMap.at(pCluster3D));
420 
421  const Pfo *const pPfo(clusterToPfoMap.at(pCluster3D));
422  Slice &slice(sliceList.at(index));
423 
424  ClusterList clusters2D;
425  LArPfoHelper::GetTwoDClusterList(pPfo, clusters2D);
426 
427  for (const Cluster *const pCluster2D : clusters2D)
428  {
429  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster2D));
430 
431  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
432  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
433 
434  CaloHitList &targetList((TPC_VIEW_U == hitType) ? slice.m_caloHitListU : (TPC_VIEW_V == hitType) ? slice.m_caloHitListV : slice.m_caloHitListW);
435 
436  pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
437  targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
438 
439  if (!assignedClusters.insert(pCluster2D).second)
440  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
441  }
442  }
443 }
444 
445 //------------------------------------------------------------------------------------------------------------------------------------------
446 
447 void EventSlicingTool::GetRemainingClusters(const Algorithm *const pAlgorithm, const HitTypeToNameMap &clusterListNames,
448  const ClusterSet &assignedClusters, ClusterList &remainingClusters) const
449 {
450  this->GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_U), assignedClusters, remainingClusters);
451  this->GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_V), assignedClusters, remainingClusters);
452  this->GetRemainingClusters(pAlgorithm, clusterListNames.at(TPC_VIEW_W), assignedClusters, remainingClusters);
453 }
454 
455 //------------------------------------------------------------------------------------------------------------------------------------------
456 
457 void EventSlicingTool::GetRemainingClusters(const Algorithm *const pAlgorithm, const std::string &clusterListName,
458  const ClusterSet &assignedClusters, ClusterList &remainingClusters) const
459 {
460  const ClusterList *pClusterList(nullptr);
461  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*pAlgorithm, clusterListName, pClusterList));
462 
463  if (!pClusterList || pClusterList->empty())
464  {
465  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
466  std::cout << "EventSlicingTool: unable to find cluster list " << clusterListName << std::endl;
467 
468  return;
469  }
470 
471  for (const Cluster *const pCluster2D : *pClusterList)
472  {
473  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster2D));
474 
475  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
476  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
477 
478  if (assignedClusters.count(pCluster2D))
479  continue;
480 
481  if (remainingClusters.end() != std::find(remainingClusters.begin(), remainingClusters.end(), pCluster2D))
482  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
483 
484  remainingClusters.push_back(pCluster2D);
485  }
486 }
487 
488 //------------------------------------------------------------------------------------------------------------------------------------------
489 
490 void EventSlicingTool::AssignRemainingHitsToSlices(const ClusterList &remainingClusters, const ClusterToSliceIndexMap &clusterToSliceIndexMap,
491  SliceList &sliceList) const
492 {
493  PointToSliceIndexMap pointToSliceIndexMap;
494 
495  try
496  {
497  PointList pointsU, pointsV, pointsW;
498  this->GetKDTreeEntries2D(sliceList, pointsU, pointsV, pointsW, pointToSliceIndexMap);
499 
501  this->GetKDTreeEntries3D(clusterToSliceIndexMap, pointsU, pointsV, pointsW, pointToSliceIndexMap);
502 
503  pointsU.sort(EventSlicingTool::SortPoints);
504  pointsV.sort(EventSlicingTool::SortPoints);
505  pointsW.sort(EventSlicingTool::SortPoints);
506 
507  PointKDNode2DList kDNode2DListU, kDNode2DListV, kDNode2DListW;
508  KDTreeBox boundingRegionU = fill_and_bound_2d_kd_tree(pointsU, kDNode2DListU);
509  KDTreeBox boundingRegionV = fill_and_bound_2d_kd_tree(pointsV, kDNode2DListV);
510  KDTreeBox boundingRegionW = fill_and_bound_2d_kd_tree(pointsW, kDNode2DListW);
511 
512  PointKDTree2D kdTreeU, kdTreeV, kdTreeW;
513  kdTreeU.build(kDNode2DListU, boundingRegionU);
514  kdTreeV.build(kDNode2DListV, boundingRegionV);
515  kdTreeW.build(kDNode2DListW, boundingRegionW);
516 
517  ClusterVector sortedRemainingClusters(remainingClusters.begin(), remainingClusters.end());
518  std::sort(sortedRemainingClusters.begin(), sortedRemainingClusters.end(), LArClusterHelper::SortByNHits);
519 
520  for (const Cluster *const pCluster2D : sortedRemainingClusters)
521  {
522  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster2D));
523 
524  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
525  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
526 
527  PointKDTree2D &kdTree((TPC_VIEW_U == hitType) ? kdTreeU : (TPC_VIEW_V == hitType) ? kdTreeV : kdTreeW);
528  const PointKDNode2D *pBestResultPoint(this->MatchClusterToSlice(pCluster2D, kdTree));
529 
530  if (!pBestResultPoint)
531  continue;
532 
533  Slice &slice(sliceList.at(pointToSliceIndexMap.at(pBestResultPoint->data)));
534  CaloHitList &targetList((TPC_VIEW_U == hitType) ? slice.m_caloHitListU : (TPC_VIEW_V == hitType) ? slice.m_caloHitListV : slice.m_caloHitListW);
535 
536  pCluster2D->GetOrderedCaloHitList().FillCaloHitList(targetList);
537  targetList.insert(targetList.end(), pCluster2D->GetIsolatedCaloHitList().begin(), pCluster2D->GetIsolatedCaloHitList().end());
538  }
539  }
540  catch (...)
541  {
542  std::cout << "EventSlicingTool::AssignRemainingHitsToSlices - exception " << std::endl;
543  for (const auto &pointMap : pointToSliceIndexMap) delete pointMap.first;
544  throw;
545  }
546 
547  for (const auto &pointMap : pointToSliceIndexMap) delete pointMap.first;
548 }
549 
550 //------------------------------------------------------------------------------------------------------------------------------------------
551 
552 void EventSlicingTool::GetKDTreeEntries2D(const SliceList &sliceList, PointList &pointsU, PointList &pointsV,
553  PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
554 {
555  unsigned int sliceIndex(0);
556 
557  for (const Slice &slice : sliceList)
558  {
559  for (const CaloHit *const pCaloHit : slice.m_caloHitListU)
560  {
561  const CartesianVector *const pPoint(new CartesianVector(pCaloHit->GetPositionVector()));
562  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
563  pointsU.push_back(pPoint);
564  }
565 
566  for (const CaloHit *const pCaloHit : slice.m_caloHitListV)
567  {
568  const CartesianVector *const pPoint(new CartesianVector(pCaloHit->GetPositionVector()));
569  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
570  pointsV.push_back(pPoint);
571  }
572 
573  for (const CaloHit *const pCaloHit : slice.m_caloHitListW)
574  {
575  const CartesianVector *const pPoint(new CartesianVector(pCaloHit->GetPositionVector()));
576  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pPoint, sliceIndex));
577  pointsW.push_back(pPoint);
578  }
579 
580  ++sliceIndex;
581  }
582 }
583 
584 //------------------------------------------------------------------------------------------------------------------------------------------
585 
586 void EventSlicingTool::GetKDTreeEntries3D(const ClusterToSliceIndexMap &clusterToSliceIndexMap, PointList &pointsU, PointList &pointsV,
587  PointList &pointsW, PointToSliceIndexMap &pointToSliceIndexMap) const
588 {
589  ClusterList clusterList;
590  for (const auto &mapEntry : clusterToSliceIndexMap) clusterList.push_back(mapEntry.first);
591  clusterList.sort(LArClusterHelper::SortByNHits);
592 
593  for (const Cluster *const pCluster3D : clusterList)
594  {
595  const unsigned int sliceIndex(clusterToSliceIndexMap.at(pCluster3D));
596 
597  CaloHitList caloHitList;
598  pCluster3D->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
599 
600  for (const CaloHit *const pCaloHit3D : caloHitList)
601  {
602  if (TPC_3D != pCaloHit3D->GetHitType())
603  throw StatusCodeException(STATUS_CODE_FAILURE);
604 
605  const CartesianVector &position3D(pCaloHit3D->GetPositionVector());
606 
607  const CartesianVector *const pProjectionU(new CartesianVector(LArGeometryHelper::ProjectPosition(this->GetPandora(), position3D, TPC_VIEW_U)));
608  const CartesianVector *const pProjectionV(new CartesianVector(LArGeometryHelper::ProjectPosition(this->GetPandora(), position3D, TPC_VIEW_V)));
609  const CartesianVector *const pProjectionW(new CartesianVector(LArGeometryHelper::ProjectPosition(this->GetPandora(), position3D, TPC_VIEW_W)));
610 
611  pointsU.push_back(pProjectionU);
612  pointsV.push_back(pProjectionV);
613  pointsW.push_back(pProjectionW);
614 
615  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionU, sliceIndex));
616  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionV, sliceIndex));
617  pointToSliceIndexMap.insert(PointToSliceIndexMap::value_type(pProjectionW, sliceIndex));
618  }
619  }
620 }
621 
622 //------------------------------------------------------------------------------------------------------------------------------------------
623 
624 const EventSlicingTool::PointKDNode2D *EventSlicingTool::MatchClusterToSlice(const Cluster *const pCluster2D, PointKDTree2D &kdTree) const
625 {
626  PointList clusterPointList;
627  const PointKDNode2D *pBestResultPoint(nullptr);
628 
629  try
630  {
631  clusterPointList.push_back(new CartesianVector(pCluster2D->GetCentroid(pCluster2D->GetInnerPseudoLayer())));
632  clusterPointList.push_back(new CartesianVector(pCluster2D->GetCentroid(pCluster2D->GetOuterPseudoLayer())));
633  clusterPointList.push_back(new CartesianVector((pCluster2D->GetCentroid(pCluster2D->GetInnerPseudoLayer()) + pCluster2D->GetCentroid(pCluster2D->GetOuterPseudoLayer())) * 0.5f));
634 
635  float bestDistance(std::numeric_limits<float>::max());
636 
637  for (const CartesianVector *const pClusterPoint : clusterPointList)
638  {
639  const PointKDNode2D *pResultPoint(nullptr);
640  float resultDistance(std::numeric_limits<float>::max());
641  const PointKDNode2D targetPoint(pClusterPoint, pClusterPoint->GetX(), pClusterPoint->GetZ());
642  kdTree.findNearestNeighbour(targetPoint, pResultPoint, resultDistance);
643 
644  if (pResultPoint && (resultDistance < bestDistance))
645  {
646  pBestResultPoint = pResultPoint;
647  bestDistance = resultDistance;
648  }
649  }
650  }
651  catch (...)
652  {
653  std::cout << "EventSlicingTool::MatchClusterToSlice - exception " << std::endl;
654  for (const CartesianVector *const pPoint : clusterPointList) delete pPoint;
655  throw;
656  }
657 
658  for (const CartesianVector *const pPoint : clusterPointList) delete pPoint;
659 
660  return pBestResultPoint;
661 }
662 
663 //------------------------------------------------------------------------------------------------------------------------------------------
664 
665 bool EventSlicingTool::SortPoints(const CartesianVector *const pLhs, const CartesianVector *const pRhs)
666 {
667  const CartesianVector deltaPosition(*pRhs - *pLhs);
668 
669  if (std::fabs(deltaPosition.GetZ()) > std::numeric_limits<float>::epsilon())
670  return (deltaPosition.GetZ() > std::numeric_limits<float>::epsilon());
671 
672  if (std::fabs(deltaPosition.GetX()) > std::numeric_limits<float>::epsilon())
673  return (deltaPosition.GetX() > std::numeric_limits<float>::epsilon());
674 
675  return (deltaPosition.GetY() > std::numeric_limits<float>::epsilon());
676 }
677 
678 //------------------------------------------------------------------------------------------------------------------------------------------
679 
680 StatusCode EventSlicingTool::ReadSettings(const TiXmlHandle xmlHandle)
681 {
682  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
683  "TrackPfoListName", m_trackPfoListName));
684 
685  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
686  "ShowerPfoListName", m_showerPfoListName));
687 
688  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
689  "MinHitsPer3DCluster", m_minHitsPer3DCluster));
690 
691  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
692  "Min3DHitsToSeedNewSlice", m_min3DHitsToSeedNewSlice));
693 
694  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
695  "SlidingFitHalfWindow", m_halfWindowLayers));
696 
697  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
698  "UsePointingAssociation", m_usePointingAssociation));
699 
700  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
701  "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
702 
703  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
704  "MaxVertexLongitudinalDistance", m_maxVertexLongitudinalDistance));
705 
706  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
707  "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
708 
709  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
710  "VertexAngularAllowance", m_vertexAngularAllowance));
711 
712  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
713  "MaxClosestApproach", m_maxClosestApproach));
714 
715  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
716  "MaxInterceptDistance", m_maxInterceptDistance));
717 
718  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
719  "UseProximityAssociation", m_useProximityAssociation));
720 
721  float maxHitSeparation = std::sqrt(m_maxHitSeparationSquared);
722  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
723  "MaxHitSeparation", maxHitSeparation));
724  m_maxHitSeparationSquared = maxHitSeparation * maxHitSeparation;
725 
726  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
727  "UseShowerConeAssociation", m_useShowerConeAssociation));
728 
729  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
730  "NConeFitLayers", m_nConeFitLayers));
731 
732  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
733  "NConeFits", m_nConeFits));
734 
735  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
736  "ConeLengthMultiplier", m_coneLengthMultiplier));
737 
738  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
739  "MaxConeLength", m_maxConeLength));
740 
741  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
742  "ConeTanHalfAngle1", m_coneTanHalfAngle1));
743 
744  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
745  "ConeBoundedFraction1", m_coneBoundedFraction1));
746 
747  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
748  "ConeTanHalfAngle2", m_coneTanHalfAngle2));
749 
750  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
751  "ConeBoundedFraction2", m_coneBoundedFraction2));
752 
753  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
754  "Use3DProjectionsInHitPickUp", m_use3DProjectionsInHitPickUp));
755 
756  return STATUS_CODE_SUCCESS;
757 }
758 
759 } // 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)
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.
Definition: LArPfoHelper.cc:97
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.
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
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...
TFile f
Definition: plotHisto.C:6
std::string m_trackPfoListName
The name of the input track pfo list.
std::unordered_map< const pandora::Cluster *, ThreeDSlidingConeFitResult > ThreeDSlidingConeFitResultMap
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.
Int_t max
Definition: plot.C:27
std::unordered_map< const pandora::CartesianVector *, unsigned int > PointToSliceIndexMap
intermediate_table::const_iterator const_iterator
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.
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 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.
std::unordered_map< const pandora::Cluster *, ThreeDSlidingFitResult > ThreeDSlidingFitResultMap
std::vector< art::Ptr< recob::Cluster > > ClusterVector
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.
SlicingAlgorithm::HitTypeToNameMap HitTypeToNameMap
bool CheckClosestApproach(const LArPointingCluster &cluster1, const LArPointingCluster &cluster2) const
Check closest approach metrics for a pair of pointing clusters.
Int_t min
Definition: plot.C:26
std::vector< PointKDNode2D > PointKDNode2DList
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.
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.
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
bool m_use3DProjectionsInHitPickUp
Whether to include 3D cluster projections when assigning remaining clusters to slices.
std::list< const pandora::CartesianVector * > PointList
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
bool m_useShowerConeAssociation
Whether to use shower cone association.
std::unordered_map< const pandora::Cluster *, unsigned int > ClusterToSliceIndexMap
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...
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...
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.
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".