SplitShowersTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArShowerMatching/SplitShowersTool.cc
3  *
4  * @brief Implementation of the split showers tool class.
5  *
6  * $Log: $
7  */
8 
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(ThreeViewShowersAlgorithm *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(ThreeViewShowersAlgorithm *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 
150  ClusterSet &usedClusters, 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 
186  (!this->CheckClusterProximities(pAlgorithm, clusterListU) || !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(ThreeViewShowersAlgorithm * /*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(ThreeViewShowersAlgorithm *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(
250  ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : NULL);
251 
252  if (NULL == pVertex)
253  return true;
254 
255  unsigned int nVertexAssociations(0);
256 
257  for (ClusterList::const_iterator iter = clusterList.begin(), iterEnd = clusterList.end(); iter != iterEnd; ++iter)
258  {
259  try
260  {
261  const HitType hitType(LArClusterHelper::GetClusterHitType(*iter));
262  const CartesianVector vertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
263  const LArPointingCluster pointingCluster(pAlgorithm->GetCachedSlidingFitResult(*iter).GetShowerFitResult());
264 
265  if (LArPointingClusterHelper::IsNode(vertex2D, pointingCluster.GetInnerVertex(), m_minVertexLongitudinalDistance, m_maxVertexTransverseDistance) ||
267  LArPointingClusterHelper::IsEmission(vertex2D, pointingCluster.GetInnerVertex(), m_minVertexLongitudinalDistance,
269  LArPointingClusterHelper::IsEmission(vertex2D, pointingCluster.GetOuterVertex(), m_minVertexLongitudinalDistance,
271  {
272  ++nVertexAssociations;
273  }
274  }
275  catch (StatusCodeException &)
276  {
277  }
278  }
279 
280  if (nVertexAssociations > m_maxVertexAssociations)
281  return false;
282 
283  return true;
284 }
285 
286 //------------------------------------------------------------------------------------------------------------------------------------------
287 
288 bool SplitShowersTool::CheckClusterSplitPositions(ThreeViewShowersAlgorithm *const pAlgorithm, const ClusterList &clusterListU,
289  const ClusterList &clusterListV, const ClusterList &clusterListW) const
290 {
291  const unsigned int nClustersU(clusterListU.size()), nClustersV(clusterListV.size()), nClustersW(clusterListW.size());
292  const unsigned int nClustersProduct(nClustersU * nClustersV * nClustersW);
293 
294  if (2 == nClustersProduct)
295  return true;
296 
297  const ClusterList &clusterList1((1 == nClustersU) ? clusterListV : clusterListU);
298  const ClusterList &clusterList2((1 == nClustersU) ? clusterListW : (1 == nClustersV) ? clusterListW : clusterListV);
299 
300  if ((2 != clusterList1.size()) || (2 != clusterList2.size()))
301  throw StatusCodeException(STATUS_CODE_FAILURE);
302 
303  float splitXPosition1(0.f), overlapX1(0.f);
304  this->GetSplitXDetails(pAlgorithm, *(clusterList1.begin()), *(++(clusterList1.begin())), splitXPosition1, overlapX1);
305 
306  float splitXPosition2(0.f), overlapX2(0.f);
307  this->GetSplitXDetails(pAlgorithm, *(clusterList2.begin()), *(++(clusterList2.begin())), splitXPosition2, overlapX2);
308 
309  if ((std::fabs(splitXPosition1 - splitXPosition2) < m_vetoMergeXDifference) && (overlapX1 < m_vetoMergeXOverlap) && (overlapX2 < m_vetoMergeXOverlap))
310  return false;
311 
312  return true;
313 }
314 
315 //------------------------------------------------------------------------------------------------------------------------------------------
316 
317 void SplitShowersTool::GetSplitXDetails(ThreeViewShowersAlgorithm *const pAlgorithm, const Cluster *const pClusterA,
318  const Cluster *const pClusterB, float &splitXPosition, float &overlapX) const
319 {
320  const TwoDSlidingFitResult &fitResultA(pAlgorithm->GetCachedSlidingFitResult(pClusterA).GetShowerFitResult());
321  const TwoDSlidingFitResult &fitResultB(pAlgorithm->GetCachedSlidingFitResult(pClusterB).GetShowerFitResult());
322 
323  const float minXA(std::min(fitResultA.GetGlobalMinLayerPosition().GetX(), fitResultA.GetGlobalMaxLayerPosition().GetX()));
324  const float maxXA(std::max(fitResultA.GetGlobalMinLayerPosition().GetX(), fitResultA.GetGlobalMaxLayerPosition().GetX()));
325  const float minXB(std::min(fitResultB.GetGlobalMinLayerPosition().GetX(), fitResultB.GetGlobalMaxLayerPosition().GetX()));
326  const float maxXB(std::max(fitResultB.GetGlobalMinLayerPosition().GetX(), fitResultB.GetGlobalMaxLayerPosition().GetX()));
327 
328  FloatVector floatVector;
329  floatVector.push_back(minXA);
330  floatVector.push_back(maxXA);
331  floatVector.push_back(minXB);
332  floatVector.push_back(maxXB);
333  std::sort(floatVector.begin(), floatVector.end());
334 
335  if (4 != floatVector.size())
336  throw StatusCodeException(STATUS_CODE_FAILURE);
337 
338  splitXPosition = 0.5f * (floatVector.at(1) + floatVector.at(2));
339  overlapX = std::max(0.f, std::min(maxXA, maxXB) - std::max(minXA, minXB));
340 }
341 
342 //------------------------------------------------------------------------------------------------------------------------------------------
343 
344 void SplitShowersTool::SpecifyClusterMerges(ThreeViewShowersAlgorithm *const pAlgorithm, const ClusterList &clusterList, ClusterMergeMap &clusterMergeMap) const
345 {
346  if (1 == clusterList.size())
347  return;
348 
349  if (2 != clusterList.size())
350  throw StatusCodeException(STATUS_CODE_FAILURE);
351 
352  const Cluster *const pClusterA(*(clusterList.begin())), *const pClusterB(*(++(clusterList.begin())));
353  const TwoDSlidingFitResult &fitResultA(pAlgorithm->GetCachedSlidingFitResult(pClusterA).GetShowerFitResult());
354  const TwoDSlidingFitResult &fitResultB(pAlgorithm->GetCachedSlidingFitResult(pClusterB).GetShowerFitResult());
355 
356  const float minXA(std::min(fitResultA.GetGlobalMinLayerPosition().GetX(), fitResultA.GetGlobalMaxLayerPosition().GetX()));
357  const float minXB(std::min(fitResultB.GetGlobalMinLayerPosition().GetX(), fitResultB.GetGlobalMaxLayerPosition().GetX()));
358 
359  const Cluster *const pLowXCluster((minXA < minXB) ? pClusterA : pClusterB);
360  const Cluster *const pHighXCluster((minXA < minXB) ? pClusterB : pClusterA);
361  clusterMergeMap[pLowXCluster].push_back(pHighXCluster);
362 }
363 
364 //------------------------------------------------------------------------------------------------------------------------------------------
365 
366 bool SplitShowersTool::ApplyChanges(ThreeViewShowersAlgorithm *const pAlgorithm, const ClusterMergeMap &clusterMergeMap) const
367 {
368  ClusterMergeMap consolidatedMergeMap;
369 
370  ClusterList clusterList;
371  for (const auto &mapEntry : clusterMergeMap)
372  clusterList.push_back(mapEntry.first);
373  clusterList.sort(LArClusterHelper::SortByNHits);
374 
375  for (const Cluster *const pParentCluster : clusterList)
376  {
377  const ClusterList &daughterClusters(clusterMergeMap.at(pParentCluster));
378 
379  for (const Cluster *const pDaughterCluster : daughterClusters)
380  {
381  if (consolidatedMergeMap.count(pDaughterCluster))
382  throw StatusCodeException(STATUS_CODE_FAILURE);
383  }
384 
385  ClusterList &targetClusterList(consolidatedMergeMap[pParentCluster]);
386  targetClusterList.insert(targetClusterList.end(), daughterClusters.begin(), daughterClusters.end());
387  }
388 
389  return pAlgorithm->MakeClusterMerges(consolidatedMergeMap);
390 }
391 
392 //------------------------------------------------------------------------------------------------------------------------------------------
393 
394 StatusCode SplitShowersTool::ReadSettings(const TiXmlHandle xmlHandle)
395 {
396  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NCommonClusters", m_nCommonClusters));
397 
398  if ((1 != m_nCommonClusters) && (2 != m_nCommonClusters))
399  {
400  std::cout << "SplitShowersTool: NCommonClusters must be set to either 1 or 2 (provided: " << m_nCommonClusters << ") " << std::endl;
401  return STATUS_CODE_INVALID_PARAMETER;
402  }
403 
404  PANDORA_RETURN_RESULT_IF_AND_IF(
405  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinMatchedFraction", m_minMatchedFraction));
406 
407  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
408  XmlHelper::ReadValue(xmlHandle, "MinMatchedSamplingPoints", m_minMatchedSamplingPoints));
409 
410  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
411  XmlHelper::ReadValue(xmlHandle, "CheckClusterProximities", m_checkClusterProximities));
412 
413  PANDORA_RETURN_RESULT_IF_AND_IF(
414  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterSeparation", m_maxClusterSeparation));
415 
416  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
417  XmlHelper::ReadValue(xmlHandle, "CheckClusterVertexRelations", m_checkClusterVertexRelations));
418 
419  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
420  XmlHelper::ReadValue(xmlHandle, "MinVertexLongitudinalDistance", m_minVertexLongitudinalDistance));
421 
422  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
423  XmlHelper::ReadValue(xmlHandle, "MaxVertexLongitudinalDistance", m_maxVertexLongitudinalDistance));
424 
425  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
426  XmlHelper::ReadValue(xmlHandle, "MaxVertexTransverseDistance", m_maxVertexTransverseDistance));
427 
428  PANDORA_RETURN_RESULT_IF_AND_IF(
429  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VertexAngularAllowance", m_vertexAngularAllowance));
430 
431  PANDORA_RETURN_RESULT_IF_AND_IF(
432  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxVertexAssociations", m_maxVertexAssociations));
433 
434  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
435  XmlHelper::ReadValue(xmlHandle, "CheckClusterSplitPositions", m_checkClusterSplitPositions));
436 
437  PANDORA_RETURN_RESULT_IF_AND_IF(
438  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VetoMergeXDifference", m_vetoMergeXDifference));
439 
440  PANDORA_RETURN_RESULT_IF_AND_IF(
441  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VetoMergeXOverlap", m_vetoMergeXOverlap));
442 
443  return STATUS_CODE_SUCCESS;
444 }
445 
446 } // namespace lar_content
bool CheckClusterVertexRelations(ThreeViewShowersAlgorithm *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 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.
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.
enum cvn::HType HitType
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.
void GetSplitXDetails(ThreeViewShowersAlgorithm *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...
intermediate_table::const_iterator const_iterator
LArPointingCluster class.
bool CheckClusterProximities(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList) const
Check the clusters in a provided cluster list are in suitable proximity for merging.
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.
unsigned int m_nCommonClusters
The number of common clusters.
Header file for the split showers tool class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the geometry helper class.
std::vector< TensorType::ElementList::const_iterator > IteratorList
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 FindShowerMerges(ThreeViewShowersAlgorithm *const pAlgorithm, const IteratorList &iteratorList, pandora::ClusterSet &usedClusters, ClusterMergeMap &clusterMergeMap) const
Get cluster merges specific elements of the tensor.
bool CheckClusterSplitPositions(ThreeViewShowersAlgorithm *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 int max(int a, int b)
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(ThreeViewShowersAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ClusterMergeMap &clusterMergeMap) const
Find split showers, using information from the overlap tensor.
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.
float m_maxClusterSeparation
The maximum separation for clusters to be merged.
bool Run(ThreeViewShowersAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
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...
void SpecifyClusterMerges(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList, ClusterMergeMap &clusterMergeMap) const
Populate the cluster merge map, based on the information contained in the provided cluster list...
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
bool m_checkClusterSplitPositions
Whether to check the cluster split positions, if there are splits in multiple views.
float m_vetoMergeXDifference
The x distance between split positions in two views below which may refuse a merge.
bool ApplyChanges(ThreeViewShowersAlgorithm *const pAlgorithm, const ClusterMergeMap &clusterMergeMap) const
Apply the changes cached in a cluster merge map and update the tensor accordingly.
float m_minMatchedFraction
The min matched sampling point fraction for use as a key tensor element.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
float m_vertexAngularAllowance
Vertex association check: pointing angular allowance in degrees.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
Dft::FloatVector FloatVector
std::vector< art::Ptr< recob::Cluster > > ClusterVector
const TwoDSlidingShowerFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding shower fit result from the algorithm cache.
std::list< Vertex > VertexList
Definition: DCEL.h:182
bool m_checkClusterVertexRelations
Whether to check the consistency of the clusters with the event vertex.
QTextStream & endl(QTextStream &s)
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...
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.