BranchGrowingAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTrackShowerId/BranchGrowingAlgorithm.cc
3  *
4  * @brief Implementation of the branch growing algorithm base 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 void BranchGrowingAlgorithm::FindAssociatedClusters(const Cluster *const pParticleSeed, ClusterVector &candidateClusters,
21  ClusterUsageMap &forwardUsageMap, ClusterUsageMap &backwardUsageMap) const
22 {
23  ClusterVector currentSeedAssociations, newSeedAssociations;
24  currentSeedAssociations.push_back(pParticleSeed);
25 
26  unsigned int associationOrder(1);
27 
28  while (!currentSeedAssociations.empty())
29  {
30  for (ClusterVector::iterator iterI = candidateClusters.begin(), iterIEnd = candidateClusters.end(); iterI != iterIEnd; ++iterI)
31  {
32  const Cluster *const pCandidateCluster = *iterI;
33 
34  if (NULL == pCandidateCluster)
35  continue;
36 
37  for (ClusterVector::iterator iterJ = currentSeedAssociations.begin(), iterJEnd = currentSeedAssociations.end(); iterJ != iterJEnd; ++iterJ)
38  {
39  const Cluster *const pAssociatedCluster = *iterJ;
40 
41  const AssociationType associationType(this->AreClustersAssociated(pAssociatedCluster, pCandidateCluster));
42 
43  if (NONE == associationType)
44  continue;
45 
46  // Check we store best association between this seed and candidate
47  Association association(associationOrder, associationType);
48  const Association &existingAssociation = forwardUsageMap[pParticleSeed][pCandidateCluster];
49 
50  if (association.GetType() > existingAssociation.GetType())
51  {
52  // If not first association, check strength of previous association in chain
53  if (pParticleSeed != pAssociatedCluster)
54  association.SetType(std::min(association.GetType(), backwardUsageMap[pAssociatedCluster][pParticleSeed].GetType()));
55 
56  forwardUsageMap[pParticleSeed][pCandidateCluster] = association;
57  backwardUsageMap[pCandidateCluster][pParticleSeed] = association;
58  }
59 
60  newSeedAssociations.push_back(pCandidateCluster);
61  *iterI = NULL;
62  }
63  }
64 
65  currentSeedAssociations = newSeedAssociations;
66  newSeedAssociations.clear();
67  ++associationOrder;
68  }
69 }
70 
71 //------------------------------------------------------------------------------------------------------------------------------------------
72 
73 void BranchGrowingAlgorithm::IdentifyClusterMerges(
74  const ClusterVector &particleSeedVector, const ClusterUsageMap &backwardUsageMap, SeedAssociationList &seedAssociationList) const
75 {
76  ClusterVector sortedCandidates;
77  for (const auto &mapEntry : backwardUsageMap)
78  sortedCandidates.push_back(mapEntry.first);
79  std::sort(sortedCandidates.begin(), sortedCandidates.end(), LArClusterHelper::SortByNHits);
80 
81  for (const Cluster *const pCluster : sortedCandidates)
82  {
83  const ClusterAssociationMap &particleSeedUsageMap(backwardUsageMap.at(pCluster));
84 
85  if (particleSeedUsageMap.empty())
86  throw StatusCodeException(STATUS_CODE_FAILURE);
87 
88  ClusterVector sortedSeeds;
89  for (const auto &mapEntry : particleSeedUsageMap)
90  sortedSeeds.push_back(mapEntry.first);
91  std::sort(sortedSeeds.begin(), sortedSeeds.end(), LArClusterHelper::SortByNHits);
92 
93  const Cluster *pBestParticleSeed = NULL;
94  AssociationType bestType(NONE);
95  unsigned int bestOrder(std::numeric_limits<unsigned int>::max());
96 
97  for (const Cluster *const pParticleSeed : sortedSeeds)
98  {
99  const Association &association(particleSeedUsageMap.at(pParticleSeed));
100 
101  if ((association.GetType() > bestType) || ((association.GetType() == bestType) && (association.GetOrder() < bestOrder)))
102  {
103  // Break-out condition for single order associations
104  if ((SINGLE_ORDER == association.GetType()) && (association.GetOrder() > 1))
105  continue;
106 
107  // Type is primary consideration; order breaks ties
108  pBestParticleSeed = pParticleSeed;
109  bestType = association.GetType();
110  bestOrder = association.GetOrder();
111  }
112  else if ((association.GetType() == bestType) && (association.GetOrder() == bestOrder))
113  {
114  // Remove ambiguous cluster from algorithm
115  pBestParticleSeed = NULL;
116  }
117  }
118 
119  if (NULL == pBestParticleSeed)
120  continue;
121 
122  seedAssociationList[pBestParticleSeed].push_back(pCluster);
123  }
124 
125  // Now deal with seeds that have no associations
126  for (ClusterVector::const_iterator iter = particleSeedVector.begin(), iterEnd = particleSeedVector.end(); iter != iterEnd; ++iter)
127  {
128  const Cluster *const pParticleSeed = *iter;
129 
130  if (seedAssociationList.end() == seedAssociationList.find(pParticleSeed))
131  seedAssociationList[pParticleSeed] = ClusterVector();
132  }
133 }
134 
135 //------------------------------------------------------------------------------------------------------------------------------------------
136 
137 StatusCode BranchGrowingAlgorithm::ReadSettings(const TiXmlHandle /*xmlHandle*/)
138 {
139  return STATUS_CODE_SUCCESS;
140 }
141 
142 } // namespace lar_content
intermediate_table::iterator iterator
void SetType(const AssociationType associationType)
Set association type.
AssociationType GetType() const
Get association type.
intermediate_table::const_iterator const_iterator
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterUsageMap
std::unordered_map< const pandora::Cluster *, Association > ClusterAssociationMap
std::unordered_map< const pandora::Cluster *, pandora::ClusterVector > SeedAssociationList
Header file for the cluster helper class.
static int max(int a, int b)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::vector< art::Ptr< recob::Cluster > > ClusterVector
Header file for the branch growing algorithm base class.