CosmicRayBaseMatchingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArThreeDReco/LArCosmicRay/CosmicRayBaseMatchingAlgorithm.cc
3  *
4  * @brief Implementation of the cosmic ray splitting algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
15 
16 using namespace pandora;
17 
18 namespace lar_content
19 {
20 
21 StatusCode CosmicRayBaseMatchingAlgorithm::Run()
22 {
23  // Get the available clusters for each view
24  ClusterVector availableClustersU, availableClustersV, availableClustersW;
25  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetAvailableClusters(m_inputClusterListNameU, availableClustersU));
26  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetAvailableClusters(m_inputClusterListNameV, availableClustersV));
27  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetAvailableClusters(m_inputClusterListNameW, availableClustersW));
28 
29  // Select clean clusters in each view
30  ClusterVector cleanClustersU, cleanClustersV, cleanClustersW;
31  this->SelectCleanClusters(availableClustersU, cleanClustersU);
32  this->SelectCleanClusters(availableClustersV, cleanClustersV);
33  this->SelectCleanClusters(availableClustersW, cleanClustersW);
34 
35  // Build associations between pairs of views
36  ClusterAssociationMap matchedClusterUV, matchedClusterVW, matchedClusterWU;
37  this->MatchClusters(cleanClustersU, cleanClustersV, matchedClusterUV);
38  this->MatchClusters(cleanClustersV, cleanClustersW, matchedClusterVW);
39  this->MatchClusters(cleanClustersW, cleanClustersU, matchedClusterWU);
40 
41  // Build particles from associations
42  ParticleList particleList;
43  this->MatchThreeViews(matchedClusterUV, matchedClusterVW, matchedClusterWU, particleList);
44  this->MatchTwoViews(matchedClusterUV, matchedClusterVW, matchedClusterWU, particleList);
45  this->BuildParticles(particleList);
46 
47  return STATUS_CODE_SUCCESS;
48 }
49 
50 //------------------------------------------------------------------------------------------------------------------------------------------
51 
52 StatusCode CosmicRayBaseMatchingAlgorithm::GetAvailableClusters(const std::string inputClusterListName, ClusterVector &clusterVector) const
53 {
54  const ClusterList *pClusterList = NULL;
55  PANDORA_RETURN_RESULT_IF_AND_IF(
56  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, inputClusterListName, pClusterList))
57 
58  if (!pClusterList || pClusterList->empty())
59  {
60  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
61  std::cout << "CosmicRayBaseMatchingAlgorithm: unable to find cluster list " << inputClusterListName << std::endl;
62 
63  return STATUS_CODE_SUCCESS;
64  }
65 
66  for (const Cluster *const pCluster : *pClusterList)
67  {
68  if (!pCluster->IsAvailable())
69  continue;
70 
71  clusterVector.push_back(pCluster);
72  }
73 
74  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
75 
76  return STATUS_CODE_SUCCESS;
77 }
78 
79 //------------------------------------------------------------------------------------------------------------------------------------------
80 
81 void CosmicRayBaseMatchingAlgorithm::MatchClusters(
82  const ClusterVector &clusterVector1, const ClusterVector &clusterVector2, ClusterAssociationMap &matchedClusters12) const
83 {
84  // Check that there are input clusters from both views
85  if (clusterVector1.empty() || clusterVector2.empty())
86  return;
87 
88  const HitType hitType1(LArClusterHelper::GetClusterHitType(*clusterVector1.begin()));
89  const HitType hitType2(LArClusterHelper::GetClusterHitType(*clusterVector2.begin()));
90 
91  if (hitType1 == hitType2)
92  throw StatusCodeException(STATUS_CODE_FAILURE);
93 
94  for (const Cluster *const pCluster1 : clusterVector1)
95  {
96  for (const Cluster *const pCluster2 : clusterVector2)
97  {
98  if (this->MatchClusters(pCluster1, pCluster2))
99  {
100  UIntSet daughterVolumeIntersection;
101  LArGeometryHelper::GetCommonDaughterVolumes(pCluster1, pCluster2, daughterVolumeIntersection);
102 
103  if (!daughterVolumeIntersection.empty())
104  matchedClusters12[pCluster1].push_back(pCluster2);
105  }
106  }
107  }
108 }
109 
110 //------------------------------------------------------------------------------------------------------------------------------------------
111 
112 void CosmicRayBaseMatchingAlgorithm::MatchThreeViews(const ClusterAssociationMap &matchedClusters12,
113  const ClusterAssociationMap &matchedClusters23, const ClusterAssociationMap &matchedClusters31, ParticleList &matchedParticles) const
114 {
115  if (matchedClusters12.empty() || matchedClusters23.empty() || matchedClusters31.empty())
116  return;
117 
118  ParticleList candidateParticles;
119 
120  ClusterList clusterList1;
121  for (const auto &mapEntry : matchedClusters12)
122  clusterList1.push_back(mapEntry.first);
123  clusterList1.sort(LArClusterHelper::SortByNHits);
124 
125  for (const Cluster *const pCluster1 : clusterList1)
126  {
127  const ClusterList &clusterList2(matchedClusters12.at(pCluster1));
128 
129  for (const Cluster *const pCluster2 : clusterList2)
130  {
131  ClusterAssociationMap::const_iterator iter23 = matchedClusters23.find(pCluster2);
132 
133  if (matchedClusters23.end() == iter23)
134  continue;
135 
136  const ClusterList &clusterList3 = iter23->second;
137 
138  for (const Cluster *const pCluster3 : clusterList3)
139  {
140  ClusterAssociationMap::const_iterator iter31 = matchedClusters31.find(pCluster3);
141 
142  if (matchedClusters31.end() == iter31)
143  continue;
144 
145  if (iter31->second.end() == std::find(iter31->second.begin(), iter31->second.end(), pCluster1))
146  continue;
147 
148  const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
149  const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
150  const HitType hitType3(LArClusterHelper::GetClusterHitType(pCluster3));
151 
152  if (!this->CheckMatchedClusters3D(pCluster1, pCluster2, pCluster3))
153  continue;
154 
155  const Cluster *const pClusterU(
156  (TPC_VIEW_U == hitType1) ? pCluster1 : (TPC_VIEW_U == hitType2) ? pCluster2 : (TPC_VIEW_U == hitType3) ? pCluster3 : NULL);
157  const Cluster *const pClusterV(
158  (TPC_VIEW_V == hitType1) ? pCluster1 : (TPC_VIEW_V == hitType2) ? pCluster2 : (TPC_VIEW_V == hitType3) ? pCluster3 : NULL);
159  const Cluster *const pClusterW(
160  (TPC_VIEW_W == hitType1) ? pCluster1 : (TPC_VIEW_W == hitType2) ? pCluster2 : (TPC_VIEW_W == hitType3) ? pCluster3 : NULL);
161 
162  candidateParticles.push_back(Particle(pClusterU, pClusterV, pClusterW));
163  }
164  }
165  }
166 
167  return this->ResolveAmbiguities(candidateParticles, matchedParticles);
168 }
169 
170 //------------------------------------------------------------------------------------------------------------------------------------------
171 
172 void CosmicRayBaseMatchingAlgorithm::MatchTwoViews(const ClusterAssociationMap &matchedClusters12,
173  const ClusterAssociationMap &matchedClusters23, const ClusterAssociationMap &matchedClusters31, ParticleList &matchedParticles) const
174 {
175  ParticleList candidateParticles;
176  this->MatchTwoViews(matchedClusters12, candidateParticles);
177  this->MatchTwoViews(matchedClusters23, candidateParticles);
178  this->MatchTwoViews(matchedClusters31, candidateParticles);
179 
180  return this->ResolveAmbiguities(candidateParticles, matchedParticles);
181 }
182 
183 //------------------------------------------------------------------------------------------------------------------------------------------
184 
185 void CosmicRayBaseMatchingAlgorithm::MatchTwoViews(const ClusterAssociationMap &matchedClusters12, ParticleList &matchedParticles) const
186 {
187  if (matchedClusters12.empty())
188  return;
189 
190  ClusterList clusterList1;
191  for (const auto &mapEntry : matchedClusters12)
192  clusterList1.push_back(mapEntry.first);
193  clusterList1.sort(LArClusterHelper::SortByNHits);
194 
195  for (const Cluster *const pCluster1 : clusterList1)
196  {
197  const ClusterList &clusterList2(matchedClusters12.at(pCluster1));
198 
199  for (const Cluster *const pCluster2 : clusterList2)
200  {
201  const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
202  const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
203 
204  const Cluster *const pClusterU((TPC_VIEW_U == hitType1) ? pCluster1 : (TPC_VIEW_U == hitType2) ? pCluster2 : NULL);
205  const Cluster *const pClusterV((TPC_VIEW_V == hitType1) ? pCluster1 : (TPC_VIEW_V == hitType2) ? pCluster2 : NULL);
206  const Cluster *const pClusterW((TPC_VIEW_W == hitType1) ? pCluster1 : (TPC_VIEW_W == hitType2) ? pCluster2 : NULL);
207 
208  matchedParticles.push_back(Particle(pClusterU, pClusterV, pClusterW));
209  }
210  }
211 }
212 
213 //------------------------------------------------------------------------------------------------------------------------------------------
214 
215 void CosmicRayBaseMatchingAlgorithm::ResolveAmbiguities(const ParticleList &candidateParticles, ParticleList &matchedParticles) const
216 {
217  for (const Particle &particle1 : candidateParticles)
218  {
219  bool isGoodMatch(true);
220 
221  for (const Particle &particle2 : candidateParticles)
222  {
223  const bool commonU(particle1.m_pClusterU == particle2.m_pClusterU);
224  const bool commonV(particle1.m_pClusterV == particle2.m_pClusterV);
225  const bool commonW(particle1.m_pClusterW == particle2.m_pClusterW);
226 
227  const bool ambiguousU(commonU && NULL != particle1.m_pClusterU);
228  const bool ambiguousV(commonV && NULL != particle1.m_pClusterV);
229  const bool ambiguousW(commonW && NULL != particle1.m_pClusterW);
230 
231  if (commonU && commonV && commonW)
232  continue;
233 
234  if (ambiguousU || ambiguousV || ambiguousW)
235  {
236  isGoodMatch = false;
237  break;
238  }
239  }
240 
241  if (isGoodMatch)
242  matchedParticles.push_back(particle1);
243  }
244 }
245 
246 //------------------------------------------------------------------------------------------------------------------------------------------
247 
248 void CosmicRayBaseMatchingAlgorithm::BuildParticles(const ParticleList &particleList)
249 {
250  if (particleList.empty())
251  return;
252 
253  const PfoList *pPfoList = NULL;
254  std::string pfoListName;
255  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
256 
257  for (const Particle &particle : particleList)
258  {
259  const Cluster *const pClusterU = particle.m_pClusterU;
260  const Cluster *const pClusterV = particle.m_pClusterV;
261  const Cluster *const pClusterW = particle.m_pClusterW;
262 
263  const bool isAvailableU((NULL != pClusterU) ? pClusterU->IsAvailable() : true);
264  const bool isAvailableV((NULL != pClusterV) ? pClusterV->IsAvailable() : true);
265  const bool isAvailableW((NULL != pClusterW) ? pClusterW->IsAvailable() : true);
266 
267  if (!(isAvailableU && isAvailableV && isAvailableW))
268  throw StatusCodeException(STATUS_CODE_FAILURE);
269 
270  PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
271  this->SetPfoParameters(particle, pfoParameters);
272 
273  if (pfoParameters.m_clusterList.empty())
274  throw StatusCodeException(STATUS_CODE_FAILURE);
275 
276  const ParticleFlowObject *pPfo(NULL);
277  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, pfoParameters, pPfo));
278  }
279 
280  if (!pPfoList->empty())
281  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Pfo>(*this, m_outputPfoListName));
282 }
283 
284 //------------------------------------------------------------------------------------------------------------------------------------------
285 
286 CosmicRayBaseMatchingAlgorithm::Particle::Particle(const Cluster *const pClusterU, const Cluster *const pClusterV, const Cluster *const pClusterW) :
287  m_pClusterU(pClusterU),
288  m_pClusterV(pClusterV),
289  m_pClusterW(pClusterW)
290 {
291  if (NULL == m_pClusterU && NULL == m_pClusterV && NULL == m_pClusterW)
292  throw StatusCodeException(STATUS_CODE_FAILURE);
293 
294  const HitType hitTypeU(NULL == m_pClusterU ? TPC_VIEW_U : LArClusterHelper::GetClusterHitType(m_pClusterU));
295  const HitType hitTypeV(NULL == m_pClusterV ? TPC_VIEW_V : LArClusterHelper::GetClusterHitType(m_pClusterV));
296  const HitType hitTypeW(NULL == m_pClusterW ? TPC_VIEW_W : LArClusterHelper::GetClusterHitType(m_pClusterW));
297 
298  if (!(TPC_VIEW_U == hitTypeU && TPC_VIEW_V == hitTypeV && TPC_VIEW_W == hitTypeW))
299  throw StatusCodeException(STATUS_CODE_FAILURE);
300 }
301 
302 //------------------------------------------------------------------------------------------------------------------------------------------
303 
304 StatusCode CosmicRayBaseMatchingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
305 {
306  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputPfoListName", m_outputPfoListName));
307  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameU", m_inputClusterListNameU));
308  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameV", m_inputClusterListNameV));
309  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameW", m_inputClusterListNameW));
310 
311  return STATUS_CODE_SUCCESS;
312 }
313 
314 } // namespace lar_content
std::string m_inputClusterListNameV
The name of the view V cluster list.
Header file for the cosmic ray base matching algorithm class.
enum cvn::HType HitType
std::string string
Definition: nybbler.cc:12
intermediate_table::const_iterator const_iterator
const pandora::Cluster * m_pClusterV
Address of cluster in V view.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
Header file for the geometry helper class.
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
Header file for the cluster helper class.
const pandora::Cluster * m_pClusterW
Address of cluster in W view.
std::string m_outputPfoListName
The name of the output PFO list.
const pandora::Cluster * m_pClusterU
Address of cluster in U view.
std::string m_inputClusterListNameU
The name of the view U cluster list.
std::string m_inputClusterListNameW
The name of the view W cluster list.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::vector< art::Ptr< recob::Cluster > > ClusterVector
QTextStream & endl(QTextStream &s)
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterAssociationMap