ConnectedRemnantsTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/ShowerFragments/ConnectedRemnantsTool.cc
3  *
4  * @brief Implementation of the clear remnants tool class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 ConnectedRemnantsTool::ConnectedRemnantsTool() : m_maxClusterSeparation(10.f)
21 {
22 }
23 
24 //------------------------------------------------------------------------------------------------------------------------------------------
25 
26 bool ConnectedRemnantsTool::Run(ThreeViewRemnantsAlgorithm *const pAlgorithm, TensorType &overlapTensor)
27 {
28  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
29  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
30 
31  ProtoParticleVector protoParticleVector;
32  ClusterMergeMap clusterMergeMap;
33  this->FindConnectedShowers(overlapTensor, protoParticleVector, clusterMergeMap);
34 
35  const bool particlesMade(pAlgorithm->CreateThreeDParticles(protoParticleVector));
36  const bool mergesMade(pAlgorithm->MakeClusterMerges(clusterMergeMap));
37 
38  return (particlesMade || mergesMade);
39 }
40 
41 //------------------------------------------------------------------------------------------------------------------------------------------
42 
44  const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector, ClusterMergeMap &clusterMergeMap) const
45 {
46  ClusterSet usedClusters;
47  ClusterVector sortedKeyClusters;
48  overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
49 
50  for (const Cluster *const pKeyCluster : sortedKeyClusters)
51  {
52  if (!pKeyCluster->IsAvailable())
53  continue;
54 
55  TensorType::ElementList connectedElements;
56  overlapTensor.GetConnectedElements(pKeyCluster, true, connectedElements);
57 
58  ClusterVector clusterVectorU, clusterVectorV, clusterVectorW;
59  this->GetClusters(connectedElements, usedClusters, clusterVectorU, clusterVectorV, clusterVectorW);
60 
61  if (clusterVectorU.empty() || clusterVectorV.empty() || clusterVectorW.empty())
62  continue;
63 
64  usedClusters.insert(clusterVectorU.begin(), clusterVectorU.end());
65  usedClusters.insert(clusterVectorV.begin(), clusterVectorV.end());
66  usedClusters.insert(clusterVectorW.begin(), clusterVectorW.end());
67 
68  if (!(this->IsConnected(clusterVectorU) && this->IsConnected(clusterVectorV) && this->IsConnected(clusterVectorW)))
69  continue;
70 
71  const Cluster *const pClusterU = clusterVectorU.front();
72  const Cluster *const pClusterV = clusterVectorV.front();
73  const Cluster *const pClusterW = clusterVectorW.front();
74 
75  ProtoParticle protoParticle;
76  protoParticle.m_clusterList.push_back(pClusterU);
77  protoParticle.m_clusterList.push_back(pClusterV);
78  protoParticle.m_clusterList.push_back(pClusterW);
79  protoParticleVector.push_back(protoParticle);
80 
81  this->FillMergeMap(pClusterU, clusterVectorU, clusterMergeMap);
82  this->FillMergeMap(pClusterV, clusterVectorV, clusterMergeMap);
83  this->FillMergeMap(pClusterW, clusterVectorW, clusterMergeMap);
84  }
85 }
86 
87 //------------------------------------------------------------------------------------------------------------------------------------------
88 
89 void ConnectedRemnantsTool::GetClusters(const TensorType::ElementList &elementList, const ClusterSet &usedClusters,
90  ClusterVector &clusterVectorU, ClusterVector &clusterVectorV, ClusterVector &clusterVectorW) const
91 {
92  for (const TensorType::Element &element : elementList)
93  {
94  if (usedClusters.count(element.GetClusterU()) || usedClusters.count(element.GetClusterV()) || usedClusters.count(element.GetClusterW()))
95  continue;
96 
97  clusterVectorU.push_back(element.GetClusterU());
98  clusterVectorV.push_back(element.GetClusterV());
99  clusterVectorW.push_back(element.GetClusterW());
100  }
101 }
102 
103 //------------------------------------------------------------------------------------------------------------------------------------------
104 
105 void ConnectedRemnantsTool::FillMergeMap(const Cluster *const pFirstCluster, const ClusterVector &clusterVector, ClusterMergeMap &clusterMergeMap) const
106 {
107  if (clusterVector.empty())
108  throw StatusCodeException(STATUS_CODE_FAILURE);
109 
110  for (const Cluster *const pSecondCluster : clusterVector)
111  {
112  if (pFirstCluster == pSecondCluster)
113  continue;
114 
115  ClusterList &clusterList(clusterMergeMap[pFirstCluster]);
116 
117  if (clusterList.end() == std::find(clusterList.begin(), clusterList.end(), pSecondCluster))
118  clusterList.push_back(pSecondCluster);
119  }
120 }
121 
122 //------------------------------------------------------------------------------------------------------------------------------------------
123 
124 bool ConnectedRemnantsTool::IsConnected(const ClusterVector &clusterVector) const
125 {
126  for (const Cluster *const pCluster1 : clusterVector)
127  {
128  for (const Cluster *const pCluster2 : clusterVector)
129  {
130  if (pCluster1 == pCluster2)
131  continue;
132 
134  return false;
135  }
136  }
137 
138  return true;
139 }
140 
141 //------------------------------------------------------------------------------------------------------------------------------------------
142 
143 StatusCode ConnectedRemnantsTool::ReadSettings(const TiXmlHandle xmlHandle)
144 {
145  PANDORA_RETURN_RESULT_IF_AND_IF(
146  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterSeparation", m_maxClusterSeparation));
147 
148  return STATUS_CODE_SUCCESS;
149 }
150 
151 } // namespace lar_content
std::vector< ProtoParticle > ProtoParticleVector
void FindConnectedShowers(const TensorType &overlapTensor, ProtoParticleVector &protoParticleVector, ClusterMergeMap &clusterMergeMap) const
Identify candidate particles.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
void FillMergeMap(const pandora::Cluster *const pCluster, const pandora::ClusterVector &clusterVector, ClusterMergeMap &clusterMergeMap) const
Fill map of clusters to be merged.
std::vector< Element > ElementList
Header file for the cluster helper class.
pandora::ClusterList m_clusterList
List of 2D clusters in a 3D proto particle.
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.
void GetClusters(const TensorType::ElementList &connectedElements, const pandora::ClusterSet &usedClusters, pandora::ClusterVector &clusterVectorU, pandora::ClusterVector &clusterVectorV, pandora::ClusterVector &clusterVectorW) const
Separate connected clusters into cluster lists by view.
bool IsConnected(const pandora::ClusterVector &clusterVector) const
Check whether all clusters in a list are spatially connected.
bool Run(ThreeViewRemnantsAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
Header file for the connected remnants tool class.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
QTextStream & endl(QTextStream &s)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.