LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
ClearTrackFragmentsTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 ClearTrackFragmentsTool::ClearTrackFragmentsTool() :
21  m_minMatchedSamplingPointFraction(0.5f),
22  m_minMatchedHits(5)
23 {
24 }
25 
26 //------------------------------------------------------------------------------------------------------------------------------------------
27 
29 {
30  if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
31  std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
32 
33  return this->FindTrackFragments(pAlgorithm, overlapTensor);
34 }
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 
39 {
40  ClusterVector sortedKeyClusters;
41  overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
42 
43  for (const Cluster *const pKeyCluster : sortedKeyClusters)
44  {
45  if (!pKeyCluster->IsAvailable())
46  continue;
47 
48  TensorType::ElementList elementList;
49  if (!this->GetAndCheckElementList(overlapTensor, pKeyCluster, elementList))
50  continue;
51 
52  IteratorList iteratorList;
53  this->SelectClearElements(elementList, iteratorList);
54 
55  bool particlesMade(false);
56  ClusterList deletedClusters, modifiedClusters, clustersToRemoveFromTensor, clustersToAddToTensor;
57  ClusterSet badClusters;
58 
59  for (IteratorList::const_iterator iIter = iteratorList.begin(), iIterEnd = iteratorList.end(); iIter != iIterEnd; ++iIter)
60  {
61  const TensorType::OverlapResult &overlapResult((*iIter)->GetOverlapResult());
62 
63  if (!this->CheckOverlapResult(overlapResult))
64  continue;
65 
66  const Cluster *pFragmentCluster(nullptr);
67  this->ProcessTensorElement(pAlgorithm, overlapResult, modifiedClusters, deletedClusters, badClusters, pFragmentCluster);
68 
69  if (!pFragmentCluster)
70  throw StatusCodeException(STATUS_CODE_FAILURE);
71 
72  const HitType fragmentHitType(overlapResult.GetFragmentHitType());
73  const Cluster *const pClusterU((TPC_VIEW_U == fragmentHitType) ? pFragmentCluster : (*iIter)->GetClusterU());
74  const Cluster *const pClusterV((TPC_VIEW_V == fragmentHitType) ? pFragmentCluster : (*iIter)->GetClusterV());
75  const Cluster *const pClusterW((TPC_VIEW_W == fragmentHitType) ? pFragmentCluster : (*iIter)->GetClusterW());
76 
77  if (!(pClusterU->IsAvailable() && pClusterV->IsAvailable() && pClusterW->IsAvailable()))
78  throw StatusCodeException(STATUS_CODE_FAILURE);
79 
80  clustersToRemoveFromTensor.push_back(pClusterU);
81  clustersToRemoveFromTensor.push_back(pClusterV);
82  clustersToRemoveFromTensor.push_back(pClusterW);
83 
84  ProtoParticle protoParticle;
85  ProtoParticleVector protoParticleVector;
86  protoParticle.m_clusterListU.push_back(pClusterU);
87  protoParticle.m_clusterListV.push_back(pClusterV);
88  protoParticle.m_clusterListW.push_back(pClusterW);
89  protoParticleVector.push_back(protoParticle);
90  particlesMade |= pAlgorithm->CreateThreeDParticles(protoParticleVector);
91  }
92 
93  clustersToRemoveFromTensor.insert(clustersToRemoveFromTensor.end(), modifiedClusters.begin(), modifiedClusters.end());
94  clustersToRemoveFromTensor.insert(clustersToRemoveFromTensor.end(), deletedClusters.begin(), deletedClusters.end());
95 
96  this->RebuildClusters(pAlgorithm, modifiedClusters, clustersToAddToTensor);
97  this->UpdateTensor(pAlgorithm, overlapTensor, clustersToRemoveFromTensor, clustersToAddToTensor);
98 
99  if (particlesMade)
100  return true;
101  }
102 
103  return false;
104 }
105 
106 //------------------------------------------------------------------------------------------------------------------------------------------
107 
108 bool ClearTrackFragmentsTool::GetAndCheckElementList(const TensorType &overlapTensor, const Cluster *const pCluster, TensorType::ElementList &elementList) const
109 {
110  // Get list of connected elements from tensor
111  unsigned int nU(0), nV(0), nW(0);
112  overlapTensor.GetConnectedElements(pCluster, true, elementList, nU, nV, nW);
113 
114  // Only allow one fragment hit type
115  HitType fragmentHitType(HIT_CUSTOM);
116 
117  for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
118  {
119  const HitType thisHitType(eIter->GetOverlapResult().GetFragmentHitType());
120 
121  if (!((TPC_VIEW_U == thisHitType) || (TPC_VIEW_V == thisHitType) || (TPC_VIEW_W == thisHitType)))
122  throw StatusCodeException(STATUS_CODE_FAILURE);
123 
124  if (thisHitType != fragmentHitType && HIT_CUSTOM != fragmentHitType)
125  return false;
126 
127  fragmentHitType = thisHitType;
128  }
129 
130  return true;
131 }
132 
133 //------------------------------------------------------------------------------------------------------------------------------------------
134 
136 {
137  CaloHitList allMatchedHits;
138 
139  for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
140  {
141  const CaloHitList &fragmentHits(eIter->GetOverlapResult().GetFragmentCaloHitList());
142 
143  for (CaloHitList::const_iterator hIter = fragmentHits.begin(), hIterEnd = fragmentHits.end(); hIter != hIterEnd; ++hIter)
144  {
145  if (allMatchedHits.end() != std::find(allMatchedHits.begin(), allMatchedHits.end(), *hIter))
146  return false;
147 
148  allMatchedHits.push_back(*hIter);
149  }
150  }
151 
152  return true;
153 }
154 
155 //------------------------------------------------------------------------------------------------------------------------------------------
156 
158 {
159  // ATTN This method is currently mirrored in ThreeDTrackFragmentsAlgorithm algorithm
160 
162  return false;
163 
164  if (overlapResult.GetFragmentCaloHitList().size() < m_minMatchedHits)
165  return false;
166 
167  return true;
168 }
169 
170 //------------------------------------------------------------------------------------------------------------------------------------------
171 
173 {
174  for (TensorType::ElementList::const_iterator eIter1 = elementList.begin(), eIterEnd1 = elementList.end(); eIter1 != eIterEnd1; ++eIter1)
175  {
176  const CaloHitList &fragmentHits1(eIter1->GetOverlapResult().GetFragmentCaloHitList());
177  const float nCaloHits1(static_cast<float>(eIter1->GetClusterU()->GetNCaloHits() + eIter1->GetClusterV()->GetNCaloHits() +
178  eIter1->GetClusterW()->GetNCaloHits()));
179 
180  bool isClearElement(true);
181 
182  for (TensorType::ElementList::const_iterator eIter2 = elementList.begin(), eIterEnd2 = elementList.end(); eIter2 != eIterEnd2; ++eIter2)
183  {
184  const CaloHitList &fragmentHits2(eIter2->GetOverlapResult().GetFragmentCaloHitList());
185  const float nCaloHits2(static_cast<float>(eIter2->GetClusterU()->GetNCaloHits() + eIter2->GetClusterV()->GetNCaloHits() +
186  eIter2->GetClusterW()->GetNCaloHits()));
187 
188  const bool commonClusterU(eIter1->GetClusterU() == eIter2->GetClusterU());
189  const bool commonClusterV(eIter1->GetClusterV() == eIter2->GetClusterV());
190  const bool commonClusterW(eIter1->GetClusterW() == eIter2->GetClusterW());
191 
192  if (commonClusterU && commonClusterV && commonClusterW)
193  continue;
194 
195  if (eIter1->GetOverlapResult().GetFragmentHitType() != eIter2->GetOverlapResult().GetFragmentHitType())
196  throw StatusCodeException(STATUS_CODE_FAILURE);
197 
198  bool isAmbiguousElement(commonClusterU || commonClusterV || commonClusterW);
199 
200  if (!isAmbiguousElement)
201  {
202  for (CaloHitList::const_iterator hIter2 = fragmentHits2.begin(), hIterEnd2 = fragmentHits2.end(); hIter2 != hIterEnd2; ++hIter2)
203  {
204  if (fragmentHits1.end() != std::find(fragmentHits1.begin(), fragmentHits1.end(), *hIter2))
205  {
206  isAmbiguousElement = true;
207  break;
208  }
209  }
210  }
211 
212  if (isAmbiguousElement && nCaloHits2 > 0.25f * nCaloHits1)
213  {
214  isClearElement = false;
215  break;
216  }
217  }
218 
219 // --- DEBUG BEGIN ---
220 // if(isClearElement)
221 // {
222 // std::cout << " pU=" << eIter1->GetClusterU() << " pV=" << eIter1->GetClusterV() << " pW=" << eIter1->GetClusterW() << " (" << eIter1->GetClusterU()->IsAvailable() << "," << eIter1->GetClusterV()->IsAvailable() << "," << eIter1->GetClusterW()->IsAvailable() << ")" << std::endl;
223 // const ClusterList &clusterList(eIter1->GetOverlapResult().GetFragmentClusterList());
224 // for (ClusterList::const_iterator cIter = clusterList.begin(), cIterEnd = clusterList.end(); cIter != cIterEnd; ++cIter)
225 // {
226 // Cluster *const pCluster = *cIter;
227 // std::cout << " Fragment: " << pCluster << " " << pCluster->IsAvailable() << std::endl;
228 // }
229 // }
230 // --- DEBUG END ---
231 
232  if (isClearElement)
233  iteratorList.push_back(eIter1);
234  }
235 }
236 
237 //------------------------------------------------------------------------------------------------------------------------------------------
238 
240  ClusterList &modifiedClusters, ClusterList &deletedClusters, ClusterSet &badClusters, const Cluster *&pFragmentCluster) const
241 {
242  pFragmentCluster = nullptr;
243 
244  const HitType fragmentHitType(overlapResult.GetFragmentHitType());
245  const std::string currentListName((TPC_VIEW_U == fragmentHitType) ? pAlgorithm->GetClusterListNameU() :
246  (TPC_VIEW_V == fragmentHitType) ? pAlgorithm->GetClusterListNameV() : pAlgorithm->GetClusterListNameW());
247 
248  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
249 
250  ClusterList clusterList(overlapResult.GetFragmentClusterList());
251  clusterList.sort(LArClusterHelper::SortByNHits);
252  const CaloHitSet caloHitSet(overlapResult.GetFragmentCaloHitList().begin(), overlapResult.GetFragmentCaloHitList().end());
253 
254  for (const Cluster *const pCluster : clusterList)
255  {
256  if (deletedClusters.end() != std::find(deletedClusters.begin(), deletedClusters.end(), pCluster))
257  continue;
258 
259  if (!pCluster->IsAvailable())
260  throw StatusCodeException(STATUS_CODE_FAILURE);
261 
262  CaloHitList clusterHitList;
263  pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterHitList);
264 
265  CaloHitList daughterHits, separateHits;
266  for (const CaloHit *const pCaloHit : clusterHitList)
267  {
268  if (caloHitSet.count(pCaloHit))
269  {
270  daughterHits.push_back(pCaloHit);
271  }
272  else
273  {
274  separateHits.push_back(pCaloHit);
275  }
276  }
277 
278  if (daughterHits.empty())
279  throw StatusCodeException(STATUS_CODE_FAILURE);
280 
281  this->Recluster(pAlgorithm, pCluster, daughterHits, separateHits, deletedClusters, badClusters, pFragmentCluster);
282 
283  if (badClusters.count(pFragmentCluster))
284  throw StatusCodeException(STATUS_CODE_FAILURE);
285 
286  // ATTN Keep track of modified clusters; does not include those for which address has been deleted at any time
287  // Note distinction between list of all deletions and the up-to-date list of bad clusters
288  ClusterList::iterator modifiedIter(std::find(modifiedClusters.begin(), modifiedClusters.end(), pCluster));
289  if (deletedClusters.end() != std::find(deletedClusters.begin(), deletedClusters.end(), pCluster))
290  {
291  if (modifiedClusters.end() != modifiedIter)
292  modifiedClusters.erase(modifiedIter);
293  }
294  else if (modifiedClusters.end() == modifiedIter)
295  {
296  modifiedClusters.push_back(pCluster);
297  }
298  }
299 
300  if (!pFragmentCluster)
301  throw StatusCodeException(STATUS_CODE_FAILURE);
302 }
303 
304 //------------------------------------------------------------------------------------------------------------------------------------------
305 
306 void ClearTrackFragmentsTool::Recluster(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const Cluster *const pCluster, const CaloHitList &daughterHits,
307  const CaloHitList &separateHits, ClusterList &deletedClusters, ClusterSet &badClusters, const Cluster *&pFragmentCluster) const
308 {
309  if (separateHits.empty())
310  {
311  if (!pFragmentCluster)
312  {
313  pFragmentCluster = pCluster;
314  }
315  else
316  {
317  // ATTN Addresses can be re-used by new allocations, so can't just use list of all cluster deletions; keep track of "bad" clusters
318  if (!badClusters.insert(pCluster).second)
319  throw StatusCodeException(STATUS_CODE_FAILURE);
320 
321  if (deletedClusters.end() == std::find(deletedClusters.begin(), deletedClusters.end(), pCluster)) deletedClusters.push_back(pCluster);
322  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*pAlgorithm, pFragmentCluster, pCluster));
323  }
324  }
325  else
326  {
327  for (const CaloHit *const pCaloHit : daughterHits)
328  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*pAlgorithm, pCluster, pCaloHit));
329 
330  if (!pFragmentCluster)
331  {
332  const ClusterList *pTemporaryList(nullptr);
333  std::string temporaryListName, currentListName;
334  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*pAlgorithm, currentListName));
335  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent<ClusterList>(*pAlgorithm, pTemporaryList, temporaryListName));
336 
337  PandoraContentApi::Cluster::Parameters hitParameters;
338  hitParameters.m_caloHitList = daughterHits;
339  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*pAlgorithm, hitParameters, pFragmentCluster));
340  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*pAlgorithm, temporaryListName, currentListName));
341  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
342 
343  (void) badClusters.erase(pFragmentCluster);
344  }
345  else
346  {
347  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*pAlgorithm, pFragmentCluster, &daughterHits));
348  }
349  }
350 }
351 
352 //------------------------------------------------------------------------------------------------------------------------------------------
353 
354 void ClearTrackFragmentsTool::RebuildClusters(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const ClusterList &modifiedClusters, ClusterList &newClusters) const
355 {
356  ClusterList rebuildList;
357 
358  for (const Cluster *const pCluster : modifiedClusters)
359  {
360  if (pCluster->IsAvailable())
361  rebuildList.push_back(pCluster);
362  }
363 
364  if (!rebuildList.empty())
365  pAlgorithm->RebuildClusters(rebuildList, newClusters);
366 }
367 
368 //------------------------------------------------------------------------------------------------------------------------------------------
369 
371  const ClusterList &clustersToRemoveFromTensor, const ClusterList &clustersToAddToTensor) const
372 {
373  for (ClusterList::const_iterator iter = clustersToRemoveFromTensor.begin(), iterEnd = clustersToRemoveFromTensor.end(); iter != iterEnd; ++iter)
374  pAlgorithm->UpdateUponDeletion(*iter);
375 
376  ClusterList newKeyClusters;
377  pAlgorithm->SelectInputClusters(&clustersToAddToTensor, newKeyClusters);
378 
379  for (ClusterList::const_iterator iter = newKeyClusters.begin(), iterEnd = newKeyClusters.end(); iter != iterEnd; ++iter)
380  pAlgorithm->UpdateForNewCluster(*iter);
381 
382  ClusterList affectedKeyClusters;
383  this->GetAffectedKeyClusters(overlapTensor, clustersToRemoveFromTensor, affectedKeyClusters);
384 
385  for (ClusterList::const_iterator iter = affectedKeyClusters.begin(), iterEnd = affectedKeyClusters.end(); iter != iterEnd; ++iter)
386  pAlgorithm->UpdateUponDeletion(*iter);
387 
388  for (ClusterList::const_iterator iter = affectedKeyClusters.begin(), iterEnd = affectedKeyClusters.end(); iter != iterEnd; ++iter)
389  pAlgorithm->UpdateForNewCluster(*iter);
390 }
391 
392 //------------------------------------------------------------------------------------------------------------------------------------------
393 
394 void ClearTrackFragmentsTool::GetAffectedKeyClusters(const TensorType &overlapTensor, const ClusterList &clustersToRemoveFromTensor,
395  ClusterList &affectedKeyClusters) const
396 {
397  for (TensorType::const_iterator tIterU = overlapTensor.begin(), tIterUEnd = overlapTensor.end(); tIterU != tIterUEnd; ++tIterU)
398  {
399  for (TensorType::OverlapMatrix::const_iterator tIterV = tIterU->second.begin(), tIterVEnd = tIterU->second.end(); tIterV != tIterVEnd; ++tIterV)
400  {
401  for (TensorType::OverlapList::const_iterator tIterW = tIterV->second.begin(), tIterWEnd = tIterV->second.end(); tIterW != tIterWEnd; ++tIterW)
402  {
403  const TensorType::OverlapResult &overlapResult(tIterW->second);
404  const HitType fragmentHitType(overlapResult.GetFragmentHitType());
405  const ClusterList &fragmentClusters(overlapResult.GetFragmentClusterList());
406 
407  for (ClusterList::const_iterator fIter = fragmentClusters.begin(), fIterEnd = fragmentClusters.end(); fIter != fIterEnd; ++fIter)
408  {
409  if (clustersToRemoveFromTensor.end() == std::find(clustersToRemoveFromTensor.begin(), clustersToRemoveFromTensor.end(), *fIter))
410  continue;
411 
412  if ((TPC_VIEW_U != fragmentHitType) && (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterU->first)))
413  affectedKeyClusters.push_back(tIterU->first);
414 
415  if ((TPC_VIEW_V != fragmentHitType) && (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterV->first)))
416  affectedKeyClusters.push_back(tIterV->first);
417 
418  if ((TPC_VIEW_W != fragmentHitType) && (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterW->first)))
419  affectedKeyClusters.push_back(tIterW->first);
420 
421  break;
422  }
423  }
424  }
425  }
426 
427  affectedKeyClusters.sort(LArClusterHelper::SortByNHits);
428 }
429 
430 //------------------------------------------------------------------------------------------------------------------------------------------
431 
432 StatusCode ClearTrackFragmentsTool::ReadSettings(const TiXmlHandle xmlHandle)
433 {
434  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
435  "MinMatchedSamplingPointFraction", m_minMatchedSamplingPointFraction));
436 
437  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
438  "MinMatchedHits", m_minMatchedHits));
439 
440  return STATUS_CODE_SUCCESS;
441 }
442 
443 } // 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.
std::vector< ProtoParticle > ProtoParticleVector
virtual void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
FragmentOverlapResult class.
unsigned int m_minMatchedHits
The minimum number of matched calo hits.
const std::string & GetClusterListNameU() const
Get the name of the u cluster list.
void RebuildClusters(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const pandora::ClusterList &modifiedClusters, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.
Header file for the clear track fragments tool class.
const_iterator begin() const
Returns an iterator referring to the first element in the overlap tensor.
intermediate_table::iterator iterator
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
bool CheckForHitAmbiguities(const TensorType::ElementList &elementList) const
Check the list of hits, stored in tensor elements, for ambiguities.
const std::string & GetClusterListNameV() const
Get the name of the v cluster list.
bool Run(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
void UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
float m_minMatchedSamplingPointFraction
The minimum fraction of matched sampling points.
const_iterator end() const
Returns an iterator referring to the past-the-end element in the overlap tensor.
TFile f
Definition: plotHisto.C:6
pandora::ClusterList m_clusterListW
List of 2D W clusters in a 3D proto particle.
const std::string & GetClusterListNameW() const
Get the name of the w cluster list.
pandora::HitType GetFragmentHitType() const
Get the fragment hit type.
const pandora::CaloHitList & GetFragmentCaloHitList() const
Get the list of fragment-associated hits.
void Recluster(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const pandora::Cluster *const pCluster, const pandora::CaloHitList &daughterHits, const pandora::CaloHitList &separateHits, pandora::ClusterList &deletedClusters, pandora::ClusterSet &badClusters, const pandora::Cluster *&pFragmentCluster) const
Rearrange the hits in a cluster from the fragment list, using the Pandora fragmentation mechanism...
void ProcessTensorElement(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const TensorType::OverlapResult &overlapResult, pandora::ClusterList &modifiedClusters, pandora::ClusterList &deletedClusters, pandora::ClusterSet &badClusters, const pandora::Cluster *&pFragmentCluster) const
Process a tensor element, reclustering the fragments as required.
intermediate_table::const_iterator const_iterator
virtual void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
Header file for the cluster helper class.
std::vector< TensorType::ElementList::const_iterator > IteratorList
float GetMatchedFraction() const
Get the fraction of sampling points resulting in a match.
void UpdateTensor(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const TensorType &overlapTensor, const pandora::ClusterList &clustersToRemoveFromTensor, const pandora::ClusterList &clustersToAddToTensor) const
Update the tensor following the fragmentation operations performed by this tool.
pandora::ClusterList m_clusterListV
List of 2D V clusters in a 3D proto particle.
pandora::ClusterList m_clusterListU
List of 2D U clusters in a 3D proto particle.
void GetSortedKeyClusters(pandora::ClusterVector &sortedKeyClusters) const
Get a sorted vector of key clusters (U clusters with current implementation)
void SelectClearElements(const TensorType::ElementList &elementList, IteratorList &iteratorList) const
Select a list of clear track-like elements from a set of connected tensor elements.
bool GetAndCheckElementList(const TensorType &overlapTensor, const pandora::Cluster *const pCluster, TensorType::ElementList &elementList) const
Get the list of elements connected to a given cluster and check its suitability (no ambiguities) ...
bool FindTrackFragments(ThreeDTrackFragmentsAlgorithm *const pAlgorithm, const TensorType &overlapTensor) const
Find suitable matching track fragments in the overlap tensor to use for 3D particle creation...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void GetAffectedKeyClusters(const TensorType &overlapTensor, const pandora::ClusterList &clustersToRemoveFromTensor, pandora::ClusterList &affectedKeyClusters) const
Get a list of the tensor key clusters for which tensor elements have been impacted by fragmentation o...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
bool CheckOverlapResult(const TensorType::OverlapResult &overlapResult) const
Check whether the overlap result passes matched sampling point and number of matched hit checks...
const pandora::ClusterList & GetFragmentClusterList() const
Get the list of fragment-associated clusters.
void RebuildClusters(const pandora::ClusterList &rebuildList, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.