LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
SplitShowersTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
14 
16 
18 
19 using namespace pandora;
20 
21 namespace lar_content
22 {
23 
24 SplitShowersTool::SplitShowersTool() :
25  m_nCommonClusters(2),
26  m_minMatchedFraction(0.25f),
27  m_minMatchedSamplingPoints(40),
28  m_checkClusterProximities(true),
29  m_maxClusterSeparation(25.f),
30  m_checkClusterVertexRelations(true),
31  m_minVertexLongitudinalDistance(-2.5f),
32  m_maxVertexLongitudinalDistance(20.f),
33  m_maxVertexTransverseDistance(1.5f),
34  m_vertexAngularAllowance(3.f),
35  m_maxVertexAssociations(1),
36  m_checkClusterSplitPositions(false),
37  m_vetoMergeXDifference(2.f),
38  m_vetoMergeXOverlap(2.f)
39 {
40 }
41 
42 //------------------------------------------------------------------------------------------------------------------------------------------
43 
44 bool SplitShowersTool::Run(ThreeDShowersAlgorithm *const pAlgorithm, TensorType &overlapTensor)
45 {
46  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
47  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
48 
49  ClusterMergeMap clusterMergeMap;
50  this->FindSplitShowers(pAlgorithm, overlapTensor, clusterMergeMap);
51 
52  return this->ApplyChanges(pAlgorithm, clusterMergeMap);
53 }
54 
55 //------------------------------------------------------------------------------------------------------------------------------------------
56 
57 void SplitShowersTool::FindSplitShowers(ThreeDShowersAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ClusterMergeMap &clusterMergeMap) const
58 {
59  ClusterSet usedClusters;
60  ClusterVector sortedKeyClusters;
61  overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
62 
63  for (const Cluster *const pKeyCluster : sortedKeyClusters)
64  {
65  if (!pKeyCluster->IsAvailable())
66  continue;
67 
68  unsigned int nU(0), nV(0), nW(0);
69  TensorType::ElementList elementList;
70  overlapTensor.GetConnectedElements(pKeyCluster, true, elementList, nU, nV, nW);
71 
72  if (nU * nV * nW < 2)
73  continue;
74 
75  for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
76  {
77  if (!this->PassesElementCuts(eIter, usedClusters))
78  continue;
79 
80  IteratorList iteratorList;
81  this->SelectTensorElements(eIter, elementList, usedClusters, iteratorList);
82 
83  if (iteratorList.size() < 2)
84  continue;
85 
86  this->FindShowerMerges(pAlgorithm, iteratorList, usedClusters, clusterMergeMap);
87  }
88  }
89 }
90 
91 //------------------------------------------------------------------------------------------------------------------------------------------
92 
93 bool SplitShowersTool::PassesElementCuts(TensorType::ElementList::const_iterator eIter, const ClusterSet &usedClusters) const
94 {
95  if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
96  return false;
97 
98  if (eIter->GetOverlapResult().GetMatchedFraction() < m_minMatchedFraction)
99  return false;
100 
101  if (eIter->GetOverlapResult().GetNMatchedSamplingPoints() < m_minMatchedSamplingPoints)
102  return false;
103 
104  return true;
105 }
106 
107 //------------------------------------------------------------------------------------------------------------------------------------------
108 
110  const ClusterSet &usedClusters, IteratorList &iteratorList) const
111 {
112  iteratorList.push_back(eIter);
113 
114  for (TensorType::ElementList::const_iterator eIter2 = elementList.begin(); eIter2 != elementList.end(); ++eIter2)
115  {
116  if (eIter == eIter2)
117  continue;
118 
119  if (!this->PassesElementCuts(eIter2, usedClusters))
120  continue;
121 
122  for (IteratorList::const_iterator iIter = iteratorList.begin(); iIter != iteratorList.end(); ++iIter)
123  {
124  if ((*iIter) == eIter2)
125  continue;
126 
127  unsigned int nMatchedClusters(0);
128 
129  if ((*iIter)->GetClusterU() == eIter2->GetClusterU())
130  ++nMatchedClusters;
131 
132  if ((*iIter)->GetClusterV() == eIter2->GetClusterV())
133  ++nMatchedClusters;
134 
135  if ((*iIter)->GetClusterW() == eIter2->GetClusterW())
136  ++nMatchedClusters;
137 
138  if (m_nCommonClusters == nMatchedClusters)
139  {
140  iteratorList.push_back(eIter2);
141  return;
142  }
143  }
144  }
145 }
146 
147 //------------------------------------------------------------------------------------------------------------------------------------------
148 
149 void SplitShowersTool::FindShowerMerges(ThreeDShowersAlgorithm *const pAlgorithm, const IteratorList &iteratorList, ClusterSet &usedClusters,
150  ClusterMergeMap &clusterMergeMap) const
151 {
152  for (IteratorList::const_iterator iIter1 = iteratorList.begin(), iIter1End = iteratorList.end(); iIter1 != iIter1End; ++iIter1)
153  {
154  for (IteratorList::const_iterator iIter2 = iIter1; iIter2 != iIter1End; ++iIter2)
155  {
156  try
157  {
158  if (iIter1 == iIter2)
159  continue;
160 
161  const TensorType::Element &element1(*(*iIter1));
162  const TensorType::Element &element2(*(*iIter2));
163 
164  ClusterList clusterListU(1, element1.GetClusterU());
165  if (element1.GetClusterU() != element2.GetClusterU())
166  clusterListU.push_back(element2.GetClusterU());
167 
168  ClusterList clusterListV(1, element1.GetClusterV());
169  if (element1.GetClusterV() != element2.GetClusterV())
170  clusterListV.push_back(element2.GetClusterV());
171 
172  ClusterList clusterListW(1, element1.GetClusterW());
173  if (element1.GetClusterW() != element2.GetClusterW())
174  clusterListW.push_back(element2.GetClusterW());
175 
176  const unsigned int nClustersU(clusterListU.size()), nClustersV(clusterListV.size()), nClustersW(clusterListW.size());
177  const unsigned int nClustersProduct(nClustersU * nClustersV * nClustersW);
178 
179  if (((1 == m_nCommonClusters) && (4 != nClustersProduct)) || ((2 == m_nCommonClusters) && (2 != nClustersProduct)))
180  throw StatusCodeException(STATUS_CODE_FAILURE);
181 
182  if ((1 == m_nCommonClusters) && !((2 == nClustersU) || (2 == nClustersV) || (2 == nClustersW)))
183  throw StatusCodeException(STATUS_CODE_FAILURE);
184 
185  if (m_checkClusterProximities && (!this->CheckClusterProximities(pAlgorithm, clusterListU) ||
186  !this->CheckClusterProximities(pAlgorithm, clusterListV) ||
187  !this->CheckClusterProximities(pAlgorithm, clusterListW)))
188  {
189  continue;
190  }
191 
192  if (m_checkClusterVertexRelations && (!this->CheckClusterVertexRelations(pAlgorithm, clusterListU) ||
193  !this->CheckClusterVertexRelations(pAlgorithm, clusterListV) ||
194  !this->CheckClusterVertexRelations(pAlgorithm, clusterListW)))
195  {
196  continue;
197  }
198 
199  if (m_checkClusterSplitPositions && !this->CheckClusterSplitPositions(pAlgorithm, clusterListU, clusterListV, clusterListW))
200  {
201  continue;
202  }
203 
204  this->SpecifyClusterMerges(pAlgorithm, clusterListU, clusterMergeMap);
205  this->SpecifyClusterMerges(pAlgorithm, clusterListV, clusterMergeMap);
206  this->SpecifyClusterMerges(pAlgorithm, clusterListW, clusterMergeMap);
207 
208  usedClusters.insert(clusterListU.begin(), clusterListU.end());
209  usedClusters.insert(clusterListV.begin(), clusterListV.end());
210  usedClusters.insert(clusterListW.begin(), clusterListW.end());
211  }
212  catch (StatusCodeException &)
213  {
214  }
215  }
216  }
217 }
218 
219 //------------------------------------------------------------------------------------------------------------------------------------------
220 
221 bool SplitShowersTool::CheckClusterProximities(ThreeDShowersAlgorithm */*const pAlgorithm*/, const ClusterList &clusterList) const
222 {
223  if (1 == clusterList.size())
224  return true;
225 
226  if (2 != clusterList.size())
227  throw StatusCodeException(STATUS_CODE_FAILURE);
228 
229  const Cluster *const pCluster1(*(clusterList.begin()));
230  const Cluster *const pCluster2(*(++(clusterList.begin())));
231 
232  const float outer12(LArClusterHelper::GetClosestDistance(pCluster1->GetCentroid(pCluster1->GetOuterPseudoLayer()), pCluster2));
233  const float outer21(LArClusterHelper::GetClosestDistance(pCluster2->GetCentroid(pCluster2->GetOuterPseudoLayer()), pCluster1));
234  const float inner12(LArClusterHelper::GetClosestDistance(pCluster1->GetCentroid(pCluster1->GetInnerPseudoLayer()), pCluster2));
235  const float inner21(LArClusterHelper::GetClosestDistance(pCluster2->GetCentroid(pCluster2->GetInnerPseudoLayer()), pCluster1));
236 
237  if ((outer12 > m_maxClusterSeparation) && (outer21 > m_maxClusterSeparation) && (inner12 > m_maxClusterSeparation) && (inner21 > m_maxClusterSeparation))
238  return false;
239 
240  return true;
241 }
242 
243 //------------------------------------------------------------------------------------------------------------------------------------------
244 
245 bool SplitShowersTool::CheckClusterVertexRelations(ThreeDShowersAlgorithm *const pAlgorithm, const ClusterList &clusterList) const
246 {
247  const VertexList *pVertexList(NULL);
248  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*pAlgorithm, pVertexList));
249  const Vertex *const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : NULL);
250 
251  if (NULL == pVertex)
252  return true;
253 
254  unsigned int nVertexAssociations(0);
255 
256  for (ClusterList::const_iterator iter = clusterList.begin(), iterEnd = clusterList.end(); iter != iterEnd; ++iter)
257  {
258  try
259  {
260  const HitType hitType(LArClusterHelper::GetClusterHitType(*iter));
261  const CartesianVector vertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
262  const LArPointingCluster pointingCluster(pAlgorithm->GetCachedSlidingFitResult(*iter).GetShowerFitResult());
263 
264  if (LArPointingClusterHelper::IsNode(vertex2D, pointingCluster.GetInnerVertex(), m_minVertexLongitudinalDistance, m_maxVertexTransverseDistance) ||
268  {
269  ++nVertexAssociations;
270  }
271  }
272  catch (StatusCodeException &) {}
273  }
274 
275  if (nVertexAssociations > m_maxVertexAssociations)
276  return false;
277 
278  return true;
279 }
280 
281 //------------------------------------------------------------------------------------------------------------------------------------------
282 
283 bool SplitShowersTool::CheckClusterSplitPositions(ThreeDShowersAlgorithm *const pAlgorithm, const ClusterList &clusterListU,
284  const ClusterList &clusterListV, const ClusterList &clusterListW) const
285 {
286  const unsigned int nClustersU(clusterListU.size()), nClustersV(clusterListV.size()), nClustersW(clusterListW.size());
287  const unsigned int nClustersProduct(nClustersU * nClustersV * nClustersW);
288 
289  if (2 == nClustersProduct)
290  return true;
291 
292  const ClusterList &clusterList1((1 == nClustersU) ? clusterListV : clusterListU);
293  const ClusterList &clusterList2((1 == nClustersU) ? clusterListW : (1 == nClustersV) ? clusterListW : clusterListV);
294 
295  if ((2 != clusterList1.size()) || (2 != clusterList2.size()))
296  throw StatusCodeException(STATUS_CODE_FAILURE);
297 
298  float splitXPosition1(0.f), overlapX1(0.f);
299  this->GetSplitXDetails(pAlgorithm, *(clusterList1.begin()), *(++(clusterList1.begin())), splitXPosition1, overlapX1);
300 
301  float splitXPosition2(0.f), overlapX2(0.f);
302  this->GetSplitXDetails(pAlgorithm, *(clusterList2.begin()), *(++(clusterList2.begin())), splitXPosition2, overlapX2);
303 
304  if ((std::fabs(splitXPosition1 - splitXPosition2) < m_vetoMergeXDifference) && (overlapX1 < m_vetoMergeXOverlap) && (overlapX2 < m_vetoMergeXOverlap))
305  return false;
306 
307  return true;
308 }
309 
310 //------------------------------------------------------------------------------------------------------------------------------------------
311 
312 void SplitShowersTool::GetSplitXDetails(ThreeDShowersAlgorithm *const pAlgorithm, const Cluster *const pClusterA, const Cluster *const pClusterB,
313  float &splitXPosition, float &overlapX) const
314 {
315  const TwoDSlidingFitResult &fitResultA(pAlgorithm->GetCachedSlidingFitResult(pClusterA).GetShowerFitResult());
316  const TwoDSlidingFitResult &fitResultB(pAlgorithm->GetCachedSlidingFitResult(pClusterB).GetShowerFitResult());
317 
318  const float minXA(std::min(fitResultA.GetGlobalMinLayerPosition().GetX(), fitResultA.GetGlobalMaxLayerPosition().GetX()));
319  const float maxXA(std::max(fitResultA.GetGlobalMinLayerPosition().GetX(), fitResultA.GetGlobalMaxLayerPosition().GetX()));
320  const float minXB(std::min(fitResultB.GetGlobalMinLayerPosition().GetX(), fitResultB.GetGlobalMaxLayerPosition().GetX()));
321  const float maxXB(std::max(fitResultB.GetGlobalMinLayerPosition().GetX(), fitResultB.GetGlobalMaxLayerPosition().GetX()));
322 
323  FloatVector floatVector;
324  floatVector.push_back(minXA);
325  floatVector.push_back(maxXA);
326  floatVector.push_back(minXB);
327  floatVector.push_back(maxXB);
328  std::sort(floatVector.begin(), floatVector.end());
329 
330  if (4 != floatVector.size())
331  throw StatusCodeException(STATUS_CODE_FAILURE);
332 
333  splitXPosition = 0.5f * (floatVector.at(1) + floatVector.at(2));
334  overlapX = std::max(0.f, std::min(maxXA, maxXB) - std::max(minXA, minXB));
335 }
336 
337 //------------------------------------------------------------------------------------------------------------------------------------------
338 
339 void SplitShowersTool::SpecifyClusterMerges(ThreeDShowersAlgorithm *const pAlgorithm, const ClusterList &clusterList, ClusterMergeMap &clusterMergeMap) const
340 {
341  if (1 == clusterList.size())
342  return;
343 
344  if (2 != clusterList.size())
345  throw StatusCodeException(STATUS_CODE_FAILURE);
346 
347  const Cluster *const pClusterA(*(clusterList.begin())), *const pClusterB(*(++(clusterList.begin())));
348  const TwoDSlidingFitResult &fitResultA(pAlgorithm->GetCachedSlidingFitResult(pClusterA).GetShowerFitResult());
349  const TwoDSlidingFitResult &fitResultB(pAlgorithm->GetCachedSlidingFitResult(pClusterB).GetShowerFitResult());
350 
351  const float minXA(std::min(fitResultA.GetGlobalMinLayerPosition().GetX(), fitResultA.GetGlobalMaxLayerPosition().GetX()));
352  const float minXB(std::min(fitResultB.GetGlobalMinLayerPosition().GetX(), fitResultB.GetGlobalMaxLayerPosition().GetX()));
353 
354  const Cluster *const pLowXCluster((minXA < minXB) ? pClusterA : pClusterB);
355  const Cluster *const pHighXCluster((minXA < minXB) ? pClusterB : pClusterA);
356  clusterMergeMap[pLowXCluster].push_back(pHighXCluster);
357 }
358 
359 //------------------------------------------------------------------------------------------------------------------------------------------
360 
361 bool SplitShowersTool::ApplyChanges(ThreeDShowersAlgorithm *const pAlgorithm, const ClusterMergeMap &clusterMergeMap) const
362 {
363  ClusterMergeMap consolidatedMergeMap;
364 
365  ClusterList clusterList;
366  for (const auto &mapEntry : clusterMergeMap) clusterList.push_back(mapEntry.first);
367  clusterList.sort(LArClusterHelper::SortByNHits);
368 
369  for (const Cluster *const pParentCluster : clusterList)
370  {
371  const ClusterList &daughterClusters(clusterMergeMap.at(pParentCluster));
372 
373  for (const Cluster *const pDaughterCluster : daughterClusters)
374  {
375  if (consolidatedMergeMap.count(pDaughterCluster))
376  throw StatusCodeException(STATUS_CODE_FAILURE);
377  }
378 
379  ClusterList &targetClusterList(consolidatedMergeMap[pParentCluster]);
380  targetClusterList.insert(targetClusterList.end(), daughterClusters.begin(), daughterClusters.end());
381  }
382 
383  return pAlgorithm->MakeClusterMerges(consolidatedMergeMap);
384 }
385 
386 //------------------------------------------------------------------------------------------------------------------------------------------
387 
388 StatusCode SplitShowersTool::ReadSettings(const TiXmlHandle xmlHandle)
389 {
390  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
391  "NCommonClusters", m_nCommonClusters));
392 
393  if ((1 != m_nCommonClusters) && (2 != m_nCommonClusters))
394  {
395  std::cout << "SplitShowersTool: NCommonClusters must be set to either 1 or 2 (provided: " << m_nCommonClusters << ") " << std::endl;
396  return STATUS_CODE_INVALID_PARAMETER;
397  }
398 
399  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
400  "MinMatchedFraction", m_minMatchedFraction));
401 
402  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
403  "MinMatchedSamplingPoints", m_minMatchedSamplingPoints));
404 
405  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
406  "CheckClusterProximities", m_checkClusterProximities));
407 
408  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
409  "MaxClusterSeparation", m_maxClusterSeparation));
410 
411  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
412  "CheckClusterVertexRelations", m_checkClusterVertexRelations));
413 
414  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
415  "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
416 
417  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
418  "MaxVertexLongitudinalDistance", m_maxVertexLongitudinalDistance));
419 
420  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
421  "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
422 
423  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
424  "VertexAngularAllowance", m_vertexAngularAllowance));
425 
426  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
427  "MaxVertexAssociations", m_maxVertexAssociations));
428 
429  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
430  "CheckClusterSplitPositions", m_checkClusterSplitPositions));
431 
432  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
433  "VetoMergeXDifference", m_vetoMergeXDifference));
434 
435  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
436  "VetoMergeXOverlap", m_vetoMergeXOverlap));
437 
438  return STATUS_CODE_SUCCESS;
439 }
440 
441 } // namespace lar_content
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.
float m_maxVertexLongitudinalDistance
Vertex association check: max longitudinal distance cut.
Header file for the lar pointing cluster class.
bool CheckClusterProximities(ThreeDShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList) const
Check the clusters in a provided cluster list are in suitable proximity for merging.
bool ApplyChanges(ThreeDShowersAlgorithm *const pAlgorithm, const ClusterMergeMap &clusterMergeMap) const
Apply the changes cached in a cluster merge map and update the tensor accordingly.
bool CheckClusterVertexRelations(ThreeDShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList) const
Check the consistency of the clusters in a provided cluster list with the event vertex, if available.
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.
bool Run(ThreeDShowersAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
const TwoDSlidingFitResult & GetShowerFitResult() const
Get the sliding fit result for the full shower cluster.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
ThreeDShowersAlgorithm class.
unsigned int m_nCommonClusters
The number of common clusters.
Header file for the split showers tool class.
TFile f
Definition: plotHisto.C:6
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the geometry helper class.
void FindShowerMerges(ThreeDShowersAlgorithm *const pAlgorithm, const IteratorList &iteratorList, pandora::ClusterSet &usedClusters, ClusterMergeMap &clusterMergeMap) const
Get cluster merges specific elements of the tensor.
const TwoDSlidingShowerFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding shower fit result from the algorithm cache.
std::vector< TensorType::ElementList::const_iterator > IteratorList
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
bool m_checkClusterProximities
Whether to check the proximities of the candidate split shower clusters.
Header file for the cluster helper class.
float m_vetoMergeXOverlap
The x overlap between candidate cluster sliding fits below which may refuse a merge.
void SpecifyClusterMerges(ThreeDShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList, ClusterMergeMap &clusterMergeMap) const
Populate the cluster merge map, based on the information contained in the provided cluster list...
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for use as a key tensor element.
void FindSplitShowers(ThreeDShowersAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ClusterMergeMap &clusterMergeMap) const
Find split showers, using information from the overlap tensor.
float m_maxClusterSeparation
The maximum separation for clusters to be merged.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void GetSplitXDetails(ThreeDShowersAlgorithm *const pAlgorithm, const pandora::Cluster *const pClusterA, const pandora::Cluster *const pClusterB, float &splitXPosition, float &overlapX) const
Get the x coordinate representing the midpoint between two clusters (hypothesis: clusters represent a...
bool PassesElementCuts(TensorType::ElementList::const_iterator eIter, const pandora::ClusterSet &usedClusters) const
Whether a provided (iterator to a) tensor element passes the selection cuts for undershoots identific...
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
bool m_checkClusterSplitPositions
Whether to check the cluster split positions, if there are splits in multiple views.
Int_t min
Definition: plot.C:26
float m_vetoMergeXDifference
The x distance between split positions in two views below which may refuse a merge.
float m_minMatchedFraction
The min matched sampling point fraction for use as a key tensor element.
float m_vertexAngularAllowance
Vertex association check: pointing angular allowance in degrees.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
std::list< Vertex > VertexList
Definition: DCEL.h:178
bool m_checkClusterVertexRelations
Whether to check the consistency of the clusters with the event vertex.
void SelectTensorElements(TensorType::ElementList::const_iterator eIter, const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select elements representing possible components of interest due to undershoots in clustering...
bool CheckClusterSplitPositions(ThreeDShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterListU, const pandora::ClusterList &clusterListV, const pandora::ClusterList &clusterListW) const
Check the consistency of the split positions in the provided u, v and w cluster lists.
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.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
unsigned int m_maxVertexAssociations
The maximum number of vertex associations for clusters to be merged.
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.