9 #include "Pandora/AlgorithmHeaders.h" 20 ClearTrackFragmentsTool::ClearTrackFragmentsTool() :
21 m_minMatchedSamplingPointFraction(0.5
f),
30 if (PandoraContentApi::GetSettings(*pAlgorithm)->ShouldDisplayAlgorithmInfo())
31 std::cout <<
"----> Running Algorithm Tool: " << this->GetInstanceName() <<
", " << this->GetType() << std::endl;
43 for (
const Cluster *
const pKeyCluster : sortedKeyClusters)
45 if (!pKeyCluster->IsAvailable())
55 if (iteratorList.empty())
63 const HitType fragmentHitType(overlapResult.GetFragmentHitType());
64 const Cluster *pClusterU(iter->GetClusterU()), *pClusterV(iter->GetClusterV()), *pClusterW(iter->GetClusterW());
70 const Cluster *pFragmentCluster(
nullptr);
73 if (!pFragmentCluster)
74 throw StatusCodeException(STATUS_CODE_FAILURE);
76 if (TPC_VIEW_U == fragmentHitType)
77 pClusterU = pFragmentCluster;
78 if (TPC_VIEW_V == fragmentHitType)
79 pClusterV = pFragmentCluster;
80 if (TPC_VIEW_W == fragmentHitType)
81 pClusterW = pFragmentCluster;
83 if (!(pClusterU->IsAvailable() && pClusterV->IsAvailable() && pClusterW->IsAvailable()))
84 throw StatusCodeException(STATUS_CODE_FAILURE);
87 ClusterList fragmentClusterList, affectedKeyClusters;
88 fragmentClusterList.push_back(pClusterU);
89 fragmentClusterList.push_back(pClusterV);
90 fragmentClusterList.push_back(pClusterW);
93 for (
const Cluster *
const pCluster : affectedKeyClusters)
102 protoParticleVector.push_back(protoParticle);
114 unsigned int nU(0), nV(0), nW(0);
118 HitType fragmentHitType(HIT_CUSTOM);
122 const HitType thisHitType(eIter->GetOverlapResult().GetFragmentHitType());
124 if (!((TPC_VIEW_U == thisHitType) || (TPC_VIEW_V == thisHitType) || (TPC_VIEW_W == thisHitType)))
125 throw StatusCodeException(STATUS_CODE_FAILURE);
127 if (thisHitType != fragmentHitType && HIT_CUSTOM != fragmentHitType)
130 fragmentHitType = thisHitType;
156 const CaloHitList &fragmentHits1(eIter1->GetOverlapResult().GetFragmentCaloHitList());
157 const float nCaloHits1(static_cast<float>(
158 eIter1->GetClusterU()->GetNCaloHits() + eIter1->GetClusterV()->GetNCaloHits() + eIter1->GetClusterW()->GetNCaloHits()));
160 bool isClearElement(
true);
164 const CaloHitList &fragmentHits2(eIter2->GetOverlapResult().GetFragmentCaloHitList());
165 const float nCaloHits2(static_cast<float>(
166 eIter2->GetClusterU()->GetNCaloHits() + eIter2->GetClusterV()->GetNCaloHits() + eIter2->GetClusterW()->GetNCaloHits()));
168 const bool commonClusterU(eIter1->GetClusterU() == eIter2->GetClusterU());
169 const bool commonClusterV(eIter1->GetClusterV() == eIter2->GetClusterV());
170 const bool commonClusterW(eIter1->GetClusterW() == eIter2->GetClusterW());
172 if (commonClusterU && commonClusterV && commonClusterW)
175 if (eIter1->GetOverlapResult().GetFragmentHitType() != eIter2->GetOverlapResult().GetFragmentHitType())
176 throw StatusCodeException(STATUS_CODE_FAILURE);
178 bool isAmbiguousElement(commonClusterU || commonClusterV || commonClusterW);
180 if (!isAmbiguousElement)
184 if (fragmentHits1.end() != std::find(fragmentHits1.begin(), fragmentHits1.end(), *hIter2))
186 isAmbiguousElement =
true;
192 if (isAmbiguousElement && nCaloHits2 > 0.25
f * nCaloHits1)
194 isClearElement =
false;
200 iteratorList.push_back(eIter1);
209 pFragmentCluster =
nullptr;
214 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
221 ClusterList affectedKeyClusters;
224 for (
const Cluster *
const pCluster : affectedKeyClusters)
227 for (
const Cluster *
const pCluster : fragmentClusterList)
230 ClusterList clustersToRebuild;
231 ClusterSet badClusters, deletedClusters;
233 for (
const Cluster *
const pCluster : fragmentClusterList)
235 if (deletedClusters.count(pCluster))
238 if (!pCluster->IsAvailable())
239 throw StatusCodeException(STATUS_CODE_FAILURE);
241 CaloHitList clusterHitList;
242 pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterHitList);
244 CaloHitList daughterHits, separateHits;
245 for (
const CaloHit *
const pCaloHit : clusterHitList)
247 if (caloHitSet.count(pCaloHit))
249 daughterHits.push_back(pCaloHit);
253 separateHits.push_back(pCaloHit);
257 if (daughterHits.empty())
258 throw StatusCodeException(STATUS_CODE_FAILURE);
260 this->
Recluster(pAlgorithm, pCluster, daughterHits, separateHits, deletedClusters, badClusters, pFragmentCluster);
263 if (badClusters.count(pFragmentCluster) || deletedClusters.count(pFragmentCluster))
264 throw StatusCodeException(STATUS_CODE_FAILURE);
269 ClusterList::iterator rebuildIter(std::find(clustersToRebuild.begin(), clustersToRebuild.end(), pCluster));
270 if (deletedClusters.count(pCluster))
272 if (clustersToRebuild.end() != rebuildIter)
273 clustersToRebuild.erase(rebuildIter);
275 else if ((clustersToRebuild.end() == rebuildIter) && (pCluster != pFragmentCluster))
277 clustersToRebuild.push_back(pCluster);
281 if (!pFragmentCluster)
282 throw StatusCodeException(STATUS_CODE_FAILURE);
285 ClusterList clustersToAddToTensor;
286 this->
RebuildClusters(pAlgorithm, clustersToRebuild, clustersToAddToTensor);
289 ClusterList newKeyClusters;
292 for (
const Cluster *
const pCluster : newKeyClusters)
295 for (
const Cluster *
const pCluster : affectedKeyClusters)
302 const CaloHitList &separateHits, ClusterSet &deletedClusters, ClusterSet &badClusters,
const Cluster *&pFragmentCluster)
const 304 if (separateHits.empty())
306 if (!pFragmentCluster)
308 pFragmentCluster = pCluster;
313 if (!badClusters.insert(pCluster).second)
314 throw StatusCodeException(STATUS_CODE_FAILURE);
316 (void)deletedClusters.insert(pCluster);
317 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*pAlgorithm, pFragmentCluster, pCluster));
322 for (
const CaloHit *
const pCaloHit : daughterHits)
323 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*pAlgorithm, pCluster, pCaloHit));
325 if (!pFragmentCluster)
327 const ClusterList *pTemporaryList(
nullptr);
328 std::string temporaryListName, currentListName;
329 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Cluster>(*pAlgorithm, currentListName));
330 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
331 PandoraContentApi::CreateTemporaryListAndSetCurrent<ClusterList>(*pAlgorithm, pTemporaryList, temporaryListName));
333 PandoraContentApi::Cluster::Parameters hitParameters;
334 hitParameters.m_caloHitList = daughterHits;
335 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*pAlgorithm, hitParameters, pFragmentCluster));
336 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Cluster>(*pAlgorithm, temporaryListName, currentListName));
337 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
339 (void)badClusters.erase(pFragmentCluster);
343 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*pAlgorithm, pFragmentCluster, &daughterHits));
353 ClusterList rebuildList;
355 for (
const Cluster *
const pCluster : modifiedClusters)
357 if (pCluster->IsAvailable())
358 rebuildList.push_back(pCluster);
361 if (!rebuildList.empty())
368 const TensorType &overlapTensor,
const ClusterList &clustersToRemoveFromTensor, ClusterList &affectedKeyClusters)
const 382 if (clustersToRemoveFromTensor.end() == std::find(clustersToRemoveFromTensor.begin(), clustersToRemoveFromTensor.end(), *fIter))
385 if ((TPC_VIEW_U != fragmentHitType) &&
386 (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterU->first)))
387 affectedKeyClusters.push_back(tIterU->first);
389 if ((TPC_VIEW_V != fragmentHitType) &&
390 (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterV->first)))
391 affectedKeyClusters.push_back(tIterV->first);
393 if ((TPC_VIEW_W != fragmentHitType) &&
394 (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterW->first)))
395 affectedKeyClusters.push_back(tIterW->first);
410 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
413 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinMatchedHits",
m_minMatchedHits));
415 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