LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
TwoDSlidingFitConsolidationAlgorithm.cc
Go to the documentation of this file.
1 
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  for (ClusterVector::const_iterator iter = trackClusters.begin(), iterEnd = trackClusters.end(); iter != iterEnd; ++iter)
83  {
84  try
85  {
86  const float slidingFitPitch(LArGeometryHelper::GetWirePitch(this->GetPandora(), LArClusterHelper::GetClusterHitType(*iter)));
87  const TwoDSlidingFitResult slidingFitResult(*iter, m_halfWindowLayers, slidingFitPitch);
88  slidingFitResultList.push_back(slidingFitResult);
89  }
90  catch (StatusCodeException &statusCodeException)
91  {
92  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
93  throw statusCodeException;
94  }
95  }
96 }
97 
98 //------------------------------------------------------------------------------------------------------------------------------------------
99 
100 StatusCode TwoDSlidingFitConsolidationAlgorithm::RemoveHitsFromClusters(const ClusterToHitMap &clustersToContract, ClusterSet &unavailableClusters) const
101 {
102  ClusterList clusterList;
103  for (const auto &mapEntry : clustersToContract)
104  clusterList.push_back(mapEntry.first);
105  clusterList.sort(LArClusterHelper::SortByNHits);
106 
107  for (const Cluster *const pCluster : clusterList)
108  {
109  const CaloHitList &caloHitListToRemove(clustersToContract.at(pCluster));
110 
111  if (caloHitListToRemove.empty())
112  continue;
113 
114  if (unavailableClusters.count(pCluster))
115  continue;
116 
117  CaloHitList caloHitList, caloHitListToKeep;
118  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
119 
120  for (const CaloHit *const pCaloHit : caloHitList)
121  {
122  if (caloHitListToRemove.end() == std::find(caloHitListToRemove.begin(), caloHitListToRemove.end(), pCaloHit))
123  caloHitListToKeep.push_back(pCaloHit);
124  }
125 
126  if (caloHitListToKeep.empty())
127  {
128  // ATTN clustersToContract and unavailable clusters now contain dangling pointers
129  unavailableClusters.insert(pCluster);
130  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete<Cluster>(*this, pCluster));
131  continue;
132  }
133 
134  for (const CaloHit *const pCaloHit : caloHitListToRemove)
135  {
136  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*this, pCluster, pCaloHit));
137  }
138  }
139 
140  return STATUS_CODE_SUCCESS;
141 }
142 
143 //------------------------------------------------------------------------------------------------------------------------------------------
144 
145 StatusCode TwoDSlidingFitConsolidationAlgorithm::AddHitsToClusters(const ClusterToHitMap &clustersToExpand, ClusterSet &unavailableClusters) const
146 {
147  ClusterList clusterList;
148 
149  for (const auto &mapEntry : clustersToExpand)
150  {
151  if (!unavailableClusters.count(mapEntry.first))
152  clusterList.push_back(mapEntry.first);
153  }
154 
155  clusterList.sort(LArClusterHelper::SortByNHits);
156 
157  for (const Cluster *const pCluster : clusterList)
158  {
159  const CaloHitList &caloHitList(clustersToExpand.at(pCluster));
160 
161  if (caloHitList.empty())
162  continue;
163 
164  if (unavailableClusters.count(pCluster))
165  continue;
166 
167  unavailableClusters.insert(pCluster);
168 
169  for (const CaloHit *const pCaloHit : caloHitList)
170  {
171  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pCluster, pCaloHit));
172  }
173  }
174 
175  return STATUS_CODE_SUCCESS;
176 }
177 
178 //------------------------------------------------------------------------------------------------------------------------------------------
179 
180 StatusCode TwoDSlidingFitConsolidationAlgorithm::RebuildClusters(const ClusterToHitMap &clustersToRebuild, const ClusterSet &unavailableClusters) const
181 {
182  if (clustersToRebuild.empty())
183  return STATUS_CODE_SUCCESS;
184 
185  ClusterVector sortedClusters;
186  for (const auto &mapEntry : clustersToRebuild)
187  {
188  if (!unavailableClusters.count(mapEntry.first))
189  sortedClusters.push_back(mapEntry.first);
190  }
191 
192  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
193 
194  for (const Cluster *const pCluster : sortedClusters)
195  {
196  const CaloHitList &caloHitList(clustersToRebuild.at(pCluster));
197  const Cluster *const pClusterToDelete(pCluster);
198 
199  if (caloHitList.empty())
200  continue;
201 
202  std::string currentClusterListName;
203  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, currentClusterListName));
204  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete<Cluster>(*this, pClusterToDelete));
205 
206  const ClusterList *pClusterList = NULL;
207  std::string newClusterListName;
208  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
209  PandoraContentApi::RunClusteringAlgorithm(*this, m_reclusteringAlgorithmName, pClusterList, newClusterListName));
210 
211  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*this, newClusterListName, currentClusterListName));
212  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, currentClusterListName));
213  }
214 
215  return STATUS_CODE_SUCCESS;
216 }
217 
218 //------------------------------------------------------------------------------------------------------------------------------------------
219 
220 StatusCode TwoDSlidingFitConsolidationAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
221 {
222  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithm(*this, xmlHandle, "ClusterRebuilding", m_reclusteringAlgorithmName));
223 
224  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinTrackLength", m_minTrackLength));
225 
226  PANDORA_RETURN_RESULT_IF_AND_IF(
227  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterLength", m_maxClusterLength));
228 
229  PANDORA_RETURN_RESULT_IF_AND_IF(
230  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
231 
232  return STATUS_CODE_SUCCESS;
233 }
234 
235 } // 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
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 pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
TFile f
Definition: plotHisto.C:6
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
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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.