9 #include "Pandora/AlgorithmHeaders.h" 20 ClearTrackFragmentsTool::ClearTrackFragmentsTool() : m_minMatchedSamplingPointFraction(0.5
f), m_minMatchedHits(5)
28 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
29 std::cout <<
"----> Running Algorithm Tool: " << this->GetInstanceName() <<
", " << this->GetType() <<
std::endl;
41 for (
const Cluster *
const pKeyCluster : sortedKeyClusters)
43 if (!pKeyCluster->IsAvailable())
53 if (iteratorList.empty())
61 const HitType fragmentHitType(overlapResult.GetFragmentHitType());
62 const Cluster *pClusterU(iter->GetClusterU()), *pClusterV(iter->GetClusterV()), *pClusterW(iter->GetClusterW());
68 const Cluster *pFragmentCluster(
nullptr);
71 if (!pFragmentCluster)
72 throw StatusCodeException(STATUS_CODE_FAILURE);
74 if (TPC_VIEW_U == fragmentHitType)
75 pClusterU = pFragmentCluster;
76 if (TPC_VIEW_V == fragmentHitType)
77 pClusterV = pFragmentCluster;
78 if (TPC_VIEW_W == fragmentHitType)
79 pClusterW = pFragmentCluster;
81 if (!(pClusterU->IsAvailable() && pClusterV->IsAvailable() && pClusterW->IsAvailable()))
82 throw StatusCodeException(STATUS_CODE_FAILURE);
85 ClusterList fragmentClusterList, affectedKeyClusters;
86 fragmentClusterList.push_back(pClusterU);
87 fragmentClusterList.push_back(pClusterV);
88 fragmentClusterList.push_back(pClusterW);
91 for (
const Cluster *
const pCluster : affectedKeyClusters)
100 protoParticleVector.push_back(protoParticle);
112 unsigned int nU(0), nV(0), nW(0);
116 HitType fragmentHitType(HIT_CUSTOM);
120 const HitType thisHitType(eIter->GetOverlapResult().GetFragmentHitType());
122 if (!((TPC_VIEW_U == thisHitType) || (TPC_VIEW_V == thisHitType) || (TPC_VIEW_W == thisHitType)))
123 throw StatusCodeException(STATUS_CODE_FAILURE);
125 if (thisHitType != fragmentHitType && HIT_CUSTOM != fragmentHitType)
128 fragmentHitType = thisHitType;
154 const CaloHitList &fragmentHits1(eIter1->GetOverlapResult().GetFragmentCaloHitList());
155 const float nCaloHits1(static_cast<float>(
156 eIter1->GetClusterU()->GetNCaloHits() + eIter1->GetClusterV()->GetNCaloHits() + eIter1->GetClusterW()->GetNCaloHits()));
158 bool isClearElement(
true);
162 const CaloHitList &fragmentHits2(eIter2->GetOverlapResult().GetFragmentCaloHitList());
163 const float nCaloHits2(static_cast<float>(
164 eIter2->GetClusterU()->GetNCaloHits() + eIter2->GetClusterV()->GetNCaloHits() + eIter2->GetClusterW()->GetNCaloHits()));
166 const bool commonClusterU(eIter1->GetClusterU() == eIter2->GetClusterU());
167 const bool commonClusterV(eIter1->GetClusterV() == eIter2->GetClusterV());
168 const bool commonClusterW(eIter1->GetClusterW() == eIter2->GetClusterW());
170 if (commonClusterU && commonClusterV && commonClusterW)
173 if (eIter1->GetOverlapResult().GetFragmentHitType() != eIter2->GetOverlapResult().GetFragmentHitType())
174 throw StatusCodeException(STATUS_CODE_FAILURE);
176 bool isAmbiguousElement(commonClusterU || commonClusterV || commonClusterW);
178 if (!isAmbiguousElement)
182 if (fragmentHits1.end() != std::find(fragmentHits1.begin(), fragmentHits1.end(), *hIter2))
184 isAmbiguousElement =
true;
190 if (isAmbiguousElement && nCaloHits2 > 0.25
f * nCaloHits1)
192 isClearElement =
false;
198 iteratorList.push_back(eIter1);
207 pFragmentCluster =
nullptr;
212 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
219 ClusterList affectedKeyClusters;
222 for (
const Cluster *
const pCluster : affectedKeyClusters)
225 for (
const Cluster *
const pCluster : fragmentClusterList)
228 ClusterList clustersToRebuild;
229 ClusterSet badClusters, deletedClusters;
231 for (
const Cluster *
const pCluster : fragmentClusterList)
233 if (deletedClusters.count(pCluster))
236 if (!pCluster->IsAvailable())
237 throw StatusCodeException(STATUS_CODE_FAILURE);
239 CaloHitList clusterHitList;
240 pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterHitList);
242 CaloHitList daughterHits, separateHits;
243 for (
const CaloHit *
const pCaloHit : clusterHitList)
245 if (caloHitSet.count(pCaloHit))
247 daughterHits.push_back(pCaloHit);
251 separateHits.push_back(pCaloHit);
255 if (daughterHits.empty())
256 throw StatusCodeException(STATUS_CODE_FAILURE);
258 this->
Recluster(pAlgorithm, pCluster, daughterHits, separateHits, deletedClusters, badClusters, pFragmentCluster);
261 if (badClusters.count(pFragmentCluster) || deletedClusters.count(pFragmentCluster))
262 throw StatusCodeException(STATUS_CODE_FAILURE);
267 ClusterList::iterator rebuildIter(std::find(clustersToRebuild.begin(), clustersToRebuild.end(), pCluster));
268 if (deletedClusters.count(pCluster))
270 if (clustersToRebuild.end() != rebuildIter)
271 clustersToRebuild.erase(rebuildIter);
273 else if ((clustersToRebuild.end() == rebuildIter) && (pCluster != pFragmentCluster))
275 clustersToRebuild.push_back(pCluster);
279 if (!pFragmentCluster)
280 throw StatusCodeException(STATUS_CODE_FAILURE);
283 ClusterList clustersToAddToTensor;
284 this->
RebuildClusters(pAlgorithm, clustersToRebuild, clustersToAddToTensor);
287 ClusterList newKeyClusters;
290 for (
const Cluster *
const pCluster : newKeyClusters)
293 for (
const Cluster *
const pCluster : affectedKeyClusters)
300 const CaloHitList &separateHits, ClusterSet &deletedClusters, ClusterSet &badClusters,
const Cluster *&pFragmentCluster)
const 302 if (separateHits.empty())
304 if (!pFragmentCluster)
306 pFragmentCluster = pCluster;
311 if (!badClusters.insert(pCluster).second)
312 throw StatusCodeException(STATUS_CODE_FAILURE);
314 (void)deletedClusters.insert(pCluster);
315 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*pAlgorithm, pFragmentCluster, pCluster));
320 for (
const CaloHit *
const pCaloHit : daughterHits)
321 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*pAlgorithm, pCluster, pCaloHit));
323 if (!pFragmentCluster)
325 const ClusterList *pTemporaryList(
nullptr);
327 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*pAlgorithm, currentListName));
328 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
329 PandoraContentApi::CreateTemporaryListAndSetCurrent<ClusterList>(*pAlgorithm, pTemporaryList, temporaryListName));
331 PandoraContentApi::Cluster::Parameters hitParameters;
332 hitParameters.m_caloHitList = daughterHits;
333 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*pAlgorithm, hitParameters, pFragmentCluster));
334 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*pAlgorithm, temporaryListName, currentListName));
335 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
337 (void)badClusters.erase(pFragmentCluster);
341 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*pAlgorithm, pFragmentCluster, &daughterHits));
351 ClusterList rebuildList;
353 for (
const Cluster *
const pCluster : modifiedClusters)
355 if (pCluster->IsAvailable())
356 rebuildList.push_back(pCluster);
359 if (!rebuildList.empty())
366 const TensorType &overlapTensor,
const ClusterList &clustersToRemoveFromTensor, ClusterList &affectedKeyClusters)
const 380 if (clustersToRemoveFromTensor.end() == std::find(clustersToRemoveFromTensor.begin(), clustersToRemoveFromTensor.end(), *fIter))
383 if ((TPC_VIEW_U != fragmentHitType) &&
384 (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterU->first)))
385 affectedKeyClusters.push_back(tIterU->first);
387 if ((TPC_VIEW_V != fragmentHitType) &&
388 (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterV->first)))
389 affectedKeyClusters.push_back(tIterV->first);
391 if ((TPC_VIEW_W != fragmentHitType) &&
392 (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterW->first)))
393 affectedKeyClusters.push_back(tIterW->first);
408 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
411 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedHits",
m_minMatchedHits));
413 return STATUS_CODE_SUCCESS;
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
FragmentOverlapResult class.
void RebuildClusters(const pandora::ClusterList &rebuildList, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.
unsigned int m_minMatchedHits
The minimum number of matched calo hits.
virtual void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
const_iterator begin() const
Returns an iterator referring to the first element in the overlap tensor.
void RebuildClusters(ThreeViewTrackFragmentsAlgorithm *const pAlgorithm, const pandora::ClusterList &modifiedClusters, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.
void GetConnectedElements(const pandora::Cluster *const pCluster, const bool ignoreUnavailable, ElementList &elementList) const
Get a list of elements connected to a specified cluster.
bool Run(ThreeViewTrackFragmentsAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
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.
void Recluster(ThreeViewTrackFragmentsAlgorithm *const pAlgorithm, const pandora::Cluster *const pCluster, const pandora::CaloHitList &daughterHits, const pandora::CaloHitList &separateHits, pandora::ClusterSet &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 UpdateForNewCluster(const pandora::Cluster *const pNewCluster)
Update to reflect addition of a new cluster to the problem space.
pandora::HitType GetFragmentHitType() const
Get the fragment hit type.
const pandora::CaloHitList & GetFragmentCaloHitList() const
Get the list of fragment-associated hits.
void ProcessTensorElement(ThreeViewTrackFragmentsAlgorithm *const pAlgorithm, const TensorType &overlapTensor, const TensorType::OverlapResult &overlapResult, const pandora::Cluster *&pFragmentCluster) const
Process a tensor element, reclustering the fragments as required.
std::vector< Element > ElementList
bool FindTrackFragments(ThreeViewTrackFragmentsAlgorithm *const pAlgorithm, const TensorType &overlapTensor) const
Find suitable matching track fragments in the overlap tensor to use for 3D particle creation...
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.
pandora::ClusterList m_clusterList
List of 2D 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) ...
ThreeViewTrackFragmentsAlgorithm class.
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...
virtual void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
const std::string & GetClusterListName(const pandora::HitType hitType) const
Get the cluster list name corresponding to a specified hit type.
virtual bool CreateThreeDParticles(const ProtoParticleVector &protoParticleVector)
Create particles using findings from recent algorithm processing.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
const pandora::ClusterList & GetFragmentClusterList() const
Get the list of fragment-associated clusters.
TheTensor::const_iterator const_iterator
QTextStream & endl(QTextStream &s)