LArSoft  v07_13_02
Liquid Argon Software toolkit - http://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 
74 void TwoDSlidingFitMultiSplitAlgorithm::BuildSlidingFitResultMap(const ClusterVector &clusterVector, const unsigned int halfWindowLayers,
75  TwoDSlidingFitResultMap &slidingFitResultMap) const
76 {
77  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
78 
79  for (ClusterVector::const_iterator iter = clusterVector.begin(), iterEnd = clusterVector.end(); iter != iterEnd; ++iter)
80  {
81  if (slidingFitResultMap.end() == slidingFitResultMap.find(*iter))
82  {
83  try
84  {
85  const TwoDSlidingFitResult slidingFitResult(*iter, halfWindowLayers, slidingFitPitch);
86 
87  if (!slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(*iter, slidingFitResult)).second)
88  throw StatusCodeException(STATUS_CODE_FAILURE);
89  }
90  catch (StatusCodeException &statusCodeException)
91  {
92  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
93  throw statusCodeException;
94  }
95  }
96  }
97 }
98 
99 //------------------------------------------------------------------------------------------------------------------------------------------
100 
102  const ClusterPositionMap &clusterSplittingMap) const
103 {
104  ClusterList clusterList;
105  for (const auto &mapEntry : clusterSplittingMap) 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 
133  const CartesianPointVector &splitPositionVector) const
134 {
135  const Cluster *const pCluster = slidingFitResult.GetCluster();
136 
137  // Get split positions for this cluster
138  FloatVector displacementVector;
139 
140  for (CartesianPointVector::const_iterator pIter = splitPositionVector.begin(), pIterEnd = splitPositionVector.end();
141  pIter != pIterEnd; ++pIter)
142  {
143  const CartesianVector &splitPosition = *pIter;
144 
145  float rL(0.f), rT(0.f);
146  slidingFitResult.GetLocalPosition(splitPosition, rL, rT);
147  displacementVector.push_back(rL);
148  }
149 
150  const float bigL(2.f * slidingFitResult.GetL(slidingFitResult.GetMaxLayer()));
151  displacementVector.push_back(-bigL);
152  displacementVector.push_back(+bigL);
153 
154  std::sort(displacementVector.begin(), displacementVector.end());
155 
156  // Begin cluster fragmentation operations
157  const ClusterList clusterList(1, pCluster);
158  std::string clusterListToSave, clusterListToDelete;
159 
160  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::InitializeFragmentation(*this, clusterList,
161  clusterListToDelete, clusterListToSave));
162 
163  CaloHitList oldCaloHitList;
164  pCluster->GetOrderedCaloHitList().FillCaloHitList(oldCaloHitList);
165 
166  bool foundPreviousL(false);
167  float prevL(0.f);
168 
169  for (FloatVector::const_iterator fIter = displacementVector.begin(), fIterEnd = displacementVector.end(); fIter != fIterEnd; ++fIter)
170  {
171  const float nextL(*fIter);
172 
173  if (foundPreviousL)
174  {
175  // Select hits for new cluster
176  CaloHitList newCaloHitList;
177 
178  for (CaloHitList::const_iterator hIter = oldCaloHitList.begin(), hIterEnd = oldCaloHitList.end(); hIter != hIterEnd; ++hIter)
179  {
180  const CaloHit *const pCaloHit = *hIter;
181 
182  float rL(0.f), rT(0.f);
183  slidingFitResult.GetLocalPosition(pCaloHit->GetPositionVector(), rL, rT);
184 
185  if (rL >= prevL && rL < nextL)
186  newCaloHitList.push_back(pCaloHit);
187  }
188 
189  if (newCaloHitList.empty())
190  continue;
191 
192  // Create new cluster
193  PandoraContentApi::Cluster::Parameters newParameters;
194  newParameters.m_caloHitList = newCaloHitList;
195 
196  const Cluster *pNewCluster(NULL);
197  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*this, newParameters, pNewCluster));
198  }
199 
200  prevL = nextL;
201  foundPreviousL = true;
202  }
203 
204  // End cluster fragmentation operations
205  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*this, clusterListToSave, clusterListToDelete));
206 
207  return STATUS_CODE_SUCCESS;
208 }
209 
210 //------------------------------------------------------------------------------------------------------------------------------------------
211 
212 StatusCode TwoDSlidingFitMultiSplitAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
213 {
214  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
215  "InputClusterListName", m_inputClusterList));
216 
217  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
218  "SlidingFitHalfWindow", m_slidingFitHalfWindow));
219 
220  return STATUS_CODE_SUCCESS;
221 }
222 
223 } // 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.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
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...
intermediate_table::const_iterator const_iterator
Header file for the cluster helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::vector< art::Ptr< recob::Cluster > > ClusterVector
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.
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.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > ClusterPositionMap