TwoDSlidingFitMultiSplitAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArTwoDReco/LArClusterSplitting/TwoDSlidingFitMultiSplitAlgorithm.cc
3  *
4  * @brief Implementation of the 2D sliding fit multi-splitting 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 TwoDSlidingFitMultiSplitAlgorithm::TwoDSlidingFitMultiSplitAlgorithm() : m_slidingFitHalfWindow(15), m_inputClusterList("")
22 {
23 }
24 
25 //------------------------------------------------------------------------------------------------------------------------------------------
26 
28 {
29  std::string originalListName;
30  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*this, originalListName));
31 
32  if (!m_inputClusterList.empty())
33  {
34  const StatusCode statusCode(PandoraContentApi::ReplaceCurrentList<Cluster>(*this, m_inputClusterList));
35 
36  if (STATUS_CODE_NOT_FOUND == statusCode)
37  {
38  std::cout << "TwoDSlidingFitMultiSplitAlgorithm: cluster list not found " << m_inputClusterList << std::endl;
39  return STATUS_CODE_SUCCESS;
40  }
41 
42  if (STATUS_CODE_SUCCESS != statusCode)
43  return statusCode;
44  }
45 
46  const ClusterList *pClusterList = NULL;
47  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
48 
49  // Get ordered list of candidate clusters
50  ClusterVector clusterVector;
51  this->GetListOfCleanClusters(pClusterList, clusterVector);
52 
53  // Build a set of sliding fit results for clean clusters
54  TwoDSlidingFitResultMap slidingFitResultMap;
55  this->BuildSlidingFitResultMap(clusterVector, m_slidingFitHalfWindow, slidingFitResultMap);
56 
57  // Find best split positions for each cluster
58  ClusterPositionMap clusterSplittingMap;
59  this->FindBestSplitPositions(slidingFitResultMap, clusterSplittingMap);
60 
61  // Perform splits
62  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->SplitClusters(slidingFitResultMap, clusterSplittingMap));
63 
64  if (!m_inputClusterList.empty())
65  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*this, originalListName));
66 
67  return STATUS_CODE_SUCCESS;
68 }
69 
70 //------------------------------------------------------------------------------------------------------------------------------------------
71 
73  const ClusterVector &clusterVector, const unsigned int halfWindowLayers, TwoDSlidingFitResultMap &slidingFitResultMap) const
74 {
75  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
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 TwoDSlidingFitResult slidingFitResult(*iter, halfWindowLayers, slidingFitPitch);
84 
85  if (!slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(*iter, slidingFitResult)).second)
86  throw StatusCodeException(STATUS_CODE_FAILURE);
87  }
88  catch (StatusCodeException &statusCodeException)
89  {
90  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
91  throw statusCodeException;
92  }
93  }
94  }
95 }
96 
97 //------------------------------------------------------------------------------------------------------------------------------------------
98 
100  const TwoDSlidingFitResultMap &slidingFitResultMap, const ClusterPositionMap &clusterSplittingMap) const
101 {
102  ClusterList clusterList;
103  for (const auto &mapEntry : clusterSplittingMap)
104  clusterList.push_back(mapEntry.first);
105  clusterList.sort(LArClusterHelper::SortByNHits);
106 
107  for (const Cluster *const pCluster : clusterList)
108  {
109  const CartesianPointVector &splitPositionVector(clusterSplittingMap.at(pCluster));
110 
111  if (splitPositionVector.empty())
112  continue;
113 
114  TwoDSlidingFitResultMap::const_iterator sIter = slidingFitResultMap.find(pCluster);
115  if (slidingFitResultMap.end() == sIter)
116  throw StatusCodeException(STATUS_CODE_FAILURE);
117 
118  const TwoDSlidingFitResult &slidingFitResult = sIter->second;
119 
120  StatusCode statusCode(this->SplitCluster(slidingFitResult, splitPositionVector));
121 
122  if (STATUS_CODE_SUCCESS != statusCode)
123  return statusCode;
124  }
125 
126  return STATUS_CODE_SUCCESS;
127 }
128 
129 //------------------------------------------------------------------------------------------------------------------------------------------
130 
131 StatusCode TwoDSlidingFitMultiSplitAlgorithm::SplitCluster(const TwoDSlidingFitResult &slidingFitResult, const CartesianPointVector &splitPositionVector) const
132 {
133  const Cluster *const pCluster = slidingFitResult.GetCluster();
134 
135  // Get split positions for this cluster
136  FloatVector displacementVector;
137 
138  for (CartesianPointVector::const_iterator pIter = splitPositionVector.begin(), pIterEnd = splitPositionVector.end(); pIter != pIterEnd; ++pIter)
139  {
140  const CartesianVector &splitPosition = *pIter;
141 
142  float rL(0.f), rT(0.f);
143  slidingFitResult.GetLocalPosition(splitPosition, rL, rT);
144  displacementVector.push_back(rL);
145  }
146 
147  const float bigL(2.f * slidingFitResult.GetL(slidingFitResult.GetMaxLayer()));
148  displacementVector.push_back(-bigL);
149  displacementVector.push_back(+bigL);
150 
151  std::sort(displacementVector.begin(), displacementVector.end());
152 
153  // Begin cluster fragmentation operations
154  const ClusterList clusterList(1, pCluster);
155  std::string clusterListToSave, clusterListToDelete;
156 
157  PANDORA_RETURN_RESULT_IF(
158  STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, clusterList, clusterListToDelete, clusterListToSave));
159 
160  CaloHitList oldCaloHitList;
161  pCluster->GetOrderedCaloHitList().FillCaloHitList(oldCaloHitList);
162 
163  bool foundPreviousL(false);
164  float prevL(0.f);
165 
166  for (FloatVector::const_iterator fIter = displacementVector.begin(), fIterEnd = displacementVector.end(); fIter != fIterEnd; ++fIter)
167  {
168  const float nextL(*fIter);
169 
170  if (foundPreviousL)
171  {
172  // Select hits for new cluster
173  CaloHitList newCaloHitList;
174 
175  for (CaloHitList::const_iterator hIter = oldCaloHitList.begin(), hIterEnd = oldCaloHitList.end(); hIter != hIterEnd; ++hIter)
176  {
177  const CaloHit *const pCaloHit = *hIter;
178 
179  float rL(0.f), rT(0.f);
180  slidingFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), rL, rT);
181 
182  if (rL >= prevL && rL < nextL)
183  newCaloHitList.push_back(pCaloHit);
184  }
185 
186  if (newCaloHitList.empty())
187  continue;
188 
189  // Create new cluster
190  PandoraContentApi::Cluster::Parameters newParameters;
191  newParameters.m_caloHitList = newCaloHitList;
192 
193  const Cluster *pNewCluster(NULL);
194  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, newParameters, pNewCluster));
195  }
196 
197  prevL = nextL;
198  foundPreviousL = true;
199  }
200 
201  // End cluster fragmentation operations
202  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, clusterListToSave, clusterListToDelete));
203 
204  return STATUS_CODE_SUCCESS;
205 }
206 
207 //------------------------------------------------------------------------------------------------------------------------------------------
208 
209 StatusCode TwoDSlidingFitMultiSplitAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
210 {
211  PANDORA_RETURN_RESULT_IF_AND_IF(
212  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListName", m_inputClusterList));
213 
214  PANDORA_RETURN_RESULT_IF_AND_IF(
215  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_slidingFitHalfWindow));
216 
217  return STATUS_CODE_SUCCESS;
218 }
219 
220 } // 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.
std::string string
Definition: nybbler.cc:12
intermediate_table::const_iterator const_iterator
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
pandora::StatusCode SplitClusters(const TwoDSlidingFitResultMap &slidingFitResultMap, const ClusterPositionMap &clusterSplittingMap) const
Split clusters.
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)
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.
Dft::FloatVector FloatVector
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.
QTextStream & endl(QTextStream &s)