LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
TwoDSlidingFitMultiSplitAlgorithm.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 TwoDSlidingFitMultiSplitAlgorithm::TwoDSlidingFitMultiSplitAlgorithm() :
22  m_slidingFitHalfWindow(15),
23  m_inputClusterList("")
24 {
25 }
26 
27 //------------------------------------------------------------------------------------------------------------------------------------------
28 
30 {
31  std::string originalListName;
32  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, originalListName));
33 
34  if (!m_inputClusterList.empty())
35  {
36  const StatusCode statusCode(PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_inputClusterList));
37 
38  if (STATUS_CODE_NOT_FOUND == statusCode)
39  {
40  std::cout << "TwoDSlidingFitMultiSplitAlgorithm: cluster list not found " << m_inputClusterList << std::endl;
41  return STATUS_CODE_SUCCESS;
42  }
43 
44  if (STATUS_CODE_SUCCESS != statusCode)
45  return statusCode;
46  }
47 
48  const ClusterList *pClusterList = NULL;
49  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
50 
51  // Get ordered list of candidate clusters
52  ClusterVector clusterVector;
53  this->GetListOfCleanClusters(pClusterList, clusterVector);
54 
55  // Build a set of sliding fit results for clean clusters
56  TwoDSlidingFitResultMap slidingFitResultMap;
57  this->BuildSlidingFitResultMap(clusterVector, m_slidingFitHalfWindow, slidingFitResultMap);
58 
59  // Find best split positions for each cluster
60  ClusterPositionMap clusterSplittingMap;
61  this->FindBestSplitPositions(slidingFitResultMap, clusterSplittingMap);
62 
63  // Perform splits
64  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->SplitClusters(slidingFitResultMap, clusterSplittingMap));
65 
66  if (!m_inputClusterList.empty())
67  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, originalListName));
68 
69  return STATUS_CODE_SUCCESS;
70 }
71 
72 //------------------------------------------------------------------------------------------------------------------------------------------
73 
75  const ClusterVector &clusterVector, const unsigned int halfWindowLayers, TwoDSlidingFitResultMap &slidingFitResultMap) const
76 {
77  for (ClusterVector::const_iterator iter = clusterVector.begin(), iterEnd = clusterVector.end(); iter != iterEnd; ++iter)
78  {
79  if (slidingFitResultMap.end() == slidingFitResultMap.find(*iter))
80  {
81  try
82  {
83  const float slidingFitPitch(LArGeometryHelper::GetWirePitch(this->GetPandora(), LArClusterHelper::GetClusterHitType(*iter)));
84  const TwoDSlidingFitResult slidingFitResult(*iter, halfWindowLayers, slidingFitPitch);
85 
86  if (!slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(*iter, slidingFitResult)).second)
87  throw StatusCodeException(STATUS_CODE_FAILURE);
88  }
89  catch (StatusCodeException &statusCodeException)
90  {
91  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
92  throw statusCodeException;
93  }
94  }
95  }
96 }
97 
98 //------------------------------------------------------------------------------------------------------------------------------------------
99 
101  const TwoDSlidingFitResultMap &slidingFitResultMap, const ClusterPositionMap &clusterSplittingMap) const
102 {
103  ClusterList clusterList;
104  for (const auto &mapEntry : clusterSplittingMap)
105  clusterList.push_back(mapEntry.first);
106  clusterList.sort(LArClusterHelper::SortByNHits);
107 
108  for (const Cluster *const pCluster : clusterList)
109  {
110  const CartesianPointVector &splitPositionVector(clusterSplittingMap.at(pCluster));
111 
112  if (splitPositionVector.empty())
113  continue;
114 
115  TwoDSlidingFitResultMap::const_iterator sIter = slidingFitResultMap.find(pCluster);
116  if (slidingFitResultMap.end() == sIter)
117  throw StatusCodeException(STATUS_CODE_FAILURE);
118 
119  const TwoDSlidingFitResult &slidingFitResult = sIter->second;
120 
121  StatusCode statusCode(this->SplitCluster(slidingFitResult, splitPositionVector));
122 
123  if (STATUS_CODE_SUCCESS != statusCode)
124  return statusCode;
125  }
126 
127  return STATUS_CODE_SUCCESS;
128 }
129 
130 //------------------------------------------------------------------------------------------------------------------------------------------
131 
132 StatusCode TwoDSlidingFitMultiSplitAlgorithm::SplitCluster(const TwoDSlidingFitResult &slidingFitResult, const CartesianPointVector &splitPositionVector) const
133 {
134  const Cluster *const pCluster = slidingFitResult.GetCluster();
135 
136  // Get split positions for this cluster
137  FloatVector displacementVector;
138 
139  for (CartesianPointVector::const_iterator pIter = splitPositionVector.begin(), pIterEnd = splitPositionVector.end(); pIter != pIterEnd; ++pIter)
140  {
141  const CartesianVector &splitPosition = *pIter;
142 
143  float rL(0.f), rT(0.f);
144  slidingFitResult.GetLocalPosition(splitPosition, rL, rT);
145  displacementVector.push_back(rL);
146  }
147 
148  const float bigL(2.f * slidingFitResult.GetL(slidingFitResult.GetMaxLayer()));
149  displacementVector.push_back(-bigL);
150  displacementVector.push_back(+bigL);
151 
152  std::sort(displacementVector.begin(), displacementVector.end());
153 
154  // Begin cluster fragmentation operations
155  const ClusterList clusterList(1, pCluster);
156  std::string clusterListToSave, clusterListToDelete;
157 
158  PANDORA_RETURN_RESULT_IF(
159  STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, clusterList, clusterListToDelete, clusterListToSave));
160 
161  CaloHitList oldCaloHitList;
162  pCluster->GetOrderedCaloHitList().FillCaloHitList(oldCaloHitList);
163 
164  bool foundPreviousL(false);
165  float prevL(0.f);
166 
167  for (FloatVector::const_iterator fIter = displacementVector.begin(), fIterEnd = displacementVector.end(); fIter != fIterEnd; ++fIter)
168  {
169  const float nextL(*fIter);
170 
171  if (foundPreviousL)
172  {
173  // Select hits for new cluster
174  CaloHitList newCaloHitList;
175 
176  for (CaloHitList::const_iterator hIter = oldCaloHitList.begin(), hIterEnd = oldCaloHitList.end(); hIter != hIterEnd; ++hIter)
177  {
178  const CaloHit *const pCaloHit = *hIter;
179 
180  float rL(0.f), rT(0.f);
181  slidingFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), rL, rT);
182 
183  if (rL >= prevL && rL < nextL)
184  newCaloHitList.push_back(pCaloHit);
185  }
186 
187  if (newCaloHitList.empty())
188  continue;
189 
190  // Create new cluster
191  PandoraContentApi::Cluster::Parameters newParameters;
192  newParameters.m_caloHitList = newCaloHitList;
193 
194  const Cluster *pNewCluster(NULL);
195  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, newParameters, pNewCluster));
196  }
197 
198  prevL = nextL;
199  foundPreviousL = true;
200  }
201 
202  // End cluster fragmentation operations
203  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, clusterListToSave, clusterListToDelete));
204 
205  return STATUS_CODE_SUCCESS;
206 }
207 
208 //------------------------------------------------------------------------------------------------------------------------------------------
209 
210 StatusCode TwoDSlidingFitMultiSplitAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
211 {
212  PANDORA_RETURN_RESULT_IF_AND_IF(
213  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListName", m_inputClusterList));
214 
215  PANDORA_RETURN_RESULT_IF_AND_IF(
216  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_slidingFitHalfWindow));
217 
218  return STATUS_CODE_SUCCESS;
219 }
220 
221 } // 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.
virtual void FindBestSplitPositions(const TwoDSlidingFitResultMap &slidingFitResultMap, ClusterPositionMap &clusterSplittingMap) const =0
Determine best split positions based on sliding fit result.
intermediate_table::const_iterator const_iterator
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
pandora::StatusCode SplitClusters(const TwoDSlidingFitResultMap &slidingFitResultMap, const ClusterPositionMap &clusterSplittingMap) const
Split clusters.
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
void BuildSlidingFitResultMap(const pandora::ClusterVector &clusterVector, const unsigned int halfWindowLayers, TwoDSlidingFitResultMap &slidingFitResultMap) const
Build the map of sliding fit results.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
virtual void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const =0
Populate cluster vector with subset of cluster list, containing clusters judged to be clean...
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > ClusterPositionMap
Header file for the cluster helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
Header file for the 2D sliding fit multi-split algorithm class.
float GetL(const int layer) const
Get longitudinal coordinate for a given sliding linear fit layer number.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
pandora::StatusCode SplitCluster(const TwoDSlidingFitResult &slidingFitResult, const pandora::CartesianPointVector &splitPositionList) const
Split cluster.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.