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