TwoDSlidingFitConsolidationAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArClusterSplitting/TwoDSlidingFitConsolidationAlgorithm.cc
3  *
4  * @brief Implementation of the 2D sliding fit consolidation algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
15 
16 using namespace pandora;
17 
18 namespace lar_content
19 {
20 
21 TwoDSlidingFitConsolidationAlgorithm::TwoDSlidingFitConsolidationAlgorithm() :
22  m_minTrackLength(7.5f),
23  m_maxClusterLength(15.f),
24  m_halfWindowLayers(25)
25 {
26 }
27 
28 //------------------------------------------------------------------------------------------------------------------------------------------
29 
31 {
32  const ClusterList *pClusterList = NULL;
33  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
34 
35  // Select tracks and showers for re-clustering (Note: samples not mutually exclusive)
36  ClusterVector trackClusters, showerClusters;
37  this->SortInputClusters(pClusterList, trackClusters, showerClusters);
38 
39  // Build sliding linear fits from track clusters
40  TwoDSlidingFitResultList slidingFitResultList;
41  this->BuildSlidingLinearFits(trackClusters, slidingFitResultList);
42 
43  // Recluster the hits
44  ClusterToHitMap clustersToExpand, clustersToContract;
45  this->GetReclusteredHits(slidingFitResultList, showerClusters, clustersToExpand, clustersToContract);
46 
47  // Consolidate and re-build clusters
48  ClusterSet unavailableClusters;
49  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RemoveHitsFromClusters(clustersToContract, unavailableClusters));
50  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->AddHitsToClusters(clustersToExpand, unavailableClusters));
51  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->RebuildClusters(clustersToContract, unavailableClusters));
52 
53  return STATUS_CODE_SUCCESS;
54 }
55 
56 //------------------------------------------------------------------------------------------------------------------------------------------
57 
59  const ClusterList *const pClusterList, ClusterVector &trackClusters, ClusterVector &showerClusters) const
60 {
61  for (ClusterList::const_iterator iter = pClusterList->begin(), iterEnd = pClusterList->end(); iter != iterEnd; ++iter)
62  {
63  const Cluster *const pCluster = *iter;
64 
65  const float thisLengthSquared(LArClusterHelper::GetLengthSquared(pCluster));
66 
67  if (thisLengthSquared < m_maxClusterLength * m_maxClusterLength)
68  showerClusters.push_back(pCluster);
69 
70  if (thisLengthSquared > m_minTrackLength * m_minTrackLength)
71  trackClusters.push_back(pCluster);
72  }
73 
74  std::sort(trackClusters.begin(), trackClusters.end(), LArClusterHelper::SortByNHits);
75  std::sort(showerClusters.begin(), showerClusters.end(), LArClusterHelper::SortByNHits);
76 }
77 
78 //------------------------------------------------------------------------------------------------------------------------------------------
79 
81 {
82  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
83 
84  for (ClusterVector::const_iterator iter = trackClusters.begin(), iterEnd = trackClusters.end(); iter != iterEnd; ++iter)
85  {
86  try
87  {
88  const TwoDSlidingFitResult slidingFitResult(*iter, m_halfWindowLayers, slidingFitPitch);
89  slidingFitResultList.push_back(slidingFitResult);
90  }
91  catch (StatusCodeException &statusCodeException)
92  {
93  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
94  throw statusCodeException;
95  }
96  }
97 }
98 
99 //------------------------------------------------------------------------------------------------------------------------------------------
100 
101 StatusCode TwoDSlidingFitConsolidationAlgorithm::RemoveHitsFromClusters(const ClusterToHitMap &clustersToContract, ClusterSet &unavailableClusters) const
102 {
103  ClusterList clusterList;
104  for (const auto &mapEntry : clustersToContract)
105  clusterList.push_back(mapEntry.first);
106  clusterList.sort(LArClusterHelper::SortByNHits);
107 
108  for (const Cluster *const pCluster : clusterList)
109  {
110  const CaloHitList &caloHitListToRemove(clustersToContract.at(pCluster));
111 
112  if (caloHitListToRemove.empty())
113  continue;
114 
115  if (unavailableClusters.count(pCluster))
116  continue;
117 
118  CaloHitList caloHitList, caloHitListToKeep;
119  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
120 
121  for (const CaloHit *const pCaloHit : caloHitList)
122  {
123  if (caloHitListToRemove.end() == std::find(caloHitListToRemove.begin(), caloHitListToRemove.end(), pCaloHit))
124  caloHitListToKeep.push_back(pCaloHit);
125  }
126 
127  if (caloHitListToKeep.empty())
128  {
129  // ATTN clustersToContract and unavailable clusters now contain dangling pointers
130  unavailableClusters.insert(pCluster);
131  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete<Cluster>(*this, pCluster));
132  continue;
133  }
134 
135  for (const CaloHit *const pCaloHit : caloHitListToRemove)
136  {
137  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*this, pCluster, pCaloHit));
138  }
139  }
140 
141  return STATUS_CODE_SUCCESS;
142 }
143 
144 //------------------------------------------------------------------------------------------------------------------------------------------
145 
146 StatusCode TwoDSlidingFitConsolidationAlgorithm::AddHitsToClusters(const ClusterToHitMap &clustersToExpand, ClusterSet &unavailableClusters) const
147 {
148  ClusterList clusterList;
149 
150  for (const auto &mapEntry : clustersToExpand)
151  {
152  if (!unavailableClusters.count(mapEntry.first))
153  clusterList.push_back(mapEntry.first);
154  }
155 
156  clusterList.sort(LArClusterHelper::SortByNHits);
157 
158  for (const Cluster *const pCluster : clusterList)
159  {
160  const CaloHitList &caloHitList(clustersToExpand.at(pCluster));
161 
162  if (caloHitList.empty())
163  continue;
164 
165  if (unavailableClusters.count(pCluster))
166  continue;
167 
168  unavailableClusters.insert(pCluster);
169 
170  for (const CaloHit *const pCaloHit : caloHitList)
171  {
172  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pCluster, pCaloHit));
173  }
174  }
175 
176  return STATUS_CODE_SUCCESS;
177 }
178 
179 //------------------------------------------------------------------------------------------------------------------------------------------
180 
181 StatusCode TwoDSlidingFitConsolidationAlgorithm::RebuildClusters(const ClusterToHitMap &clustersToRebuild, const ClusterSet &unavailableClusters) const
182 {
183  if (clustersToRebuild.empty())
184  return STATUS_CODE_SUCCESS;
185 
186  ClusterVector sortedClusters;
187  for (const auto &mapEntry : clustersToRebuild)
188  {
189  if (!unavailableClusters.count(mapEntry.first))
190  sortedClusters.push_back(mapEntry.first);
191  }
192 
193  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
194 
195  for (const Cluster *const pCluster : sortedClusters)
196  {
197  const CaloHitList &caloHitList(clustersToRebuild.at(pCluster));
198  const Cluster *const pClusterToDelete(pCluster);
199 
200  if (caloHitList.empty())
201  continue;
202 
203  std::string currentClusterListName;
204  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, currentClusterListName));
205  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete<Cluster>(*this, pClusterToDelete));
206 
207  const ClusterList *pClusterList = NULL;
208  std::string newClusterListName;
209  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
210  PandoraContentApi::RunClusteringAlgorithm(*this, m_reclusteringAlgorithmName, pClusterList, newClusterListName));
211 
212  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, newClusterListName, currentClusterListName));
213  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, currentClusterListName));
214  }
215 
216  return STATUS_CODE_SUCCESS;
217 }
218 
219 //------------------------------------------------------------------------------------------------------------------------------------------
220 
221 StatusCode TwoDSlidingFitConsolidationAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
222 {
223  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithm(*this, xmlHandle, "ClusterRebuilding", m_reclusteringAlgorithmName));
224 
225  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinTrackLength", m_minTrackLength));
226 
227  PANDORA_RETURN_RESULT_IF_AND_IF(
228  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterLength", m_maxClusterLength));
229 
230  PANDORA_RETURN_RESULT_IF_AND_IF(
231  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
232 
233  return STATUS_CODE_SUCCESS;
234 }
235 
236 } // namespace lar_content
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.
unsigned int m_halfWindowLayers
Size of layer window for sliding fit results.
std::unordered_map< const pandora::Cluster *, pandora::CaloHitList > ClusterToHitMap
std::string string
Definition: nybbler.cc:12
float m_maxClusterLength
Maximum length of shower clusters to use in re-building.
float m_minTrackLength
Minimum length of track clusters to consolidate.
intermediate_table::const_iterator const_iterator
Header file for the 2D sliding fit consolidation algorithm class.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
Header file for the geometry helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void BuildSlidingLinearFits(const pandora::ClusterVector &trackClusters, TwoDSlidingFitResultList &slidingFitResultList) const
Apply sliding linear fits to track clusters.
Header file for the cluster helper class.
std::vector< TwoDSlidingFitResult > TwoDSlidingFitResultList
std::string m_reclusteringAlgorithmName
Name of daughter algorithm to use for cluster re-building.
void SortInputClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &trackClusters, pandora::ClusterVector &showerClusters) const
Sort input cluster list into track-like clusters and shower-like clusters.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
virtual void GetReclusteredHits(const TwoDSlidingFitResultList &slidingFitResultList, const pandora::ClusterVector &showerClusters, ClusterToHitMap &caloHitsToAdd, ClusterToHitMap &caloHitsToRemove) const =0
Get the list of hits to be added or removed from clusters.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
pandora::StatusCode AddHitsToClusters(const ClusterToHitMap &clustersToRebuild, pandora::ClusterSet &unavailableClusters) const
Add hits to clusters.
pandora::StatusCode RemoveHitsFromClusters(const ClusterToHitMap &clustersToRebuild, pandora::ClusterSet &unavailableClusters) const
Remove hits from clusters.
pandora::StatusCode RebuildClusters(const ClusterToHitMap &clustersAtStart, const pandora::ClusterSet &unavailableClusters) const
Re-build clusters.