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 bool particlesMade(
false);
56 ClusterList deletedClusters, modifiedClusters, clustersToRemoveFromTensor, clustersToAddToTensor;
57 ClusterSet badClusters;
66 const Cluster *pFragmentCluster(
nullptr);
67 this->
ProcessTensorElement(pAlgorithm, overlapResult, modifiedClusters, deletedClusters, badClusters, pFragmentCluster);
69 if (!pFragmentCluster)
70 throw StatusCodeException(STATUS_CODE_FAILURE);
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());
77 if (!(pClusterU->IsAvailable() && pClusterV->IsAvailable() && pClusterW->IsAvailable()))
78 throw StatusCodeException(STATUS_CODE_FAILURE);
80 clustersToRemoveFromTensor.push_back(pClusterU);
81 clustersToRemoveFromTensor.push_back(pClusterV);
82 clustersToRemoveFromTensor.push_back(pClusterW);
89 protoParticleVector.push_back(protoParticle);
93 clustersToRemoveFromTensor.insert(clustersToRemoveFromTensor.end(), modifiedClusters.begin(), modifiedClusters.end());
94 clustersToRemoveFromTensor.insert(clustersToRemoveFromTensor.end(), deletedClusters.begin(), deletedClusters.end());
96 this->
RebuildClusters(pAlgorithm, modifiedClusters, clustersToAddToTensor);
97 this->
UpdateTensor(pAlgorithm, overlapTensor, clustersToRemoveFromTensor, clustersToAddToTensor);
111 unsigned int nU(0), nV(0), nW(0);
115 HitType fragmentHitType(HIT_CUSTOM);
119 const HitType thisHitType(eIter->GetOverlapResult().GetFragmentHitType());
121 if (!((TPC_VIEW_U == thisHitType) || (TPC_VIEW_V == thisHitType) || (TPC_VIEW_W == thisHitType)))
122 throw StatusCodeException(STATUS_CODE_FAILURE);
124 if (thisHitType != fragmentHitType && HIT_CUSTOM != fragmentHitType)
127 fragmentHitType = thisHitType;
137 CaloHitList allMatchedHits;
141 const CaloHitList &fragmentHits(eIter->GetOverlapResult().GetFragmentCaloHitList());
145 if (allMatchedHits.end() != std::find(allMatchedHits.begin(), allMatchedHits.end(), *hIter))
148 allMatchedHits.push_back(*hIter);
176 const CaloHitList &fragmentHits1(eIter1->GetOverlapResult().GetFragmentCaloHitList());
177 const float nCaloHits1(static_cast<float>(eIter1->GetClusterU()->GetNCaloHits() + eIter1->GetClusterV()->GetNCaloHits() +
178 eIter1->GetClusterW()->GetNCaloHits()));
180 bool isClearElement(
true);
184 const CaloHitList &fragmentHits2(eIter2->GetOverlapResult().GetFragmentCaloHitList());
185 const float nCaloHits2(static_cast<float>(eIter2->GetClusterU()->GetNCaloHits() + eIter2->GetClusterV()->GetNCaloHits() +
186 eIter2->GetClusterW()->GetNCaloHits()));
188 const bool commonClusterU(eIter1->GetClusterU() == eIter2->GetClusterU());
189 const bool commonClusterV(eIter1->GetClusterV() == eIter2->GetClusterV());
190 const bool commonClusterW(eIter1->GetClusterW() == eIter2->GetClusterW());
192 if (commonClusterU && commonClusterV && commonClusterW)
195 if (eIter1->GetOverlapResult().GetFragmentHitType() != eIter2->GetOverlapResult().GetFragmentHitType())
196 throw StatusCodeException(STATUS_CODE_FAILURE);
198 bool isAmbiguousElement(commonClusterU || commonClusterV || commonClusterW);
200 if (!isAmbiguousElement)
204 if (fragmentHits1.end() != std::find(fragmentHits1.begin(), fragmentHits1.end(), *hIter2))
206 isAmbiguousElement =
true;
212 if (isAmbiguousElement && nCaloHits2 > 0.25
f * nCaloHits1)
214 isClearElement =
false;
233 iteratorList.push_back(eIter1);
240 ClusterList &modifiedClusters, ClusterList &deletedClusters, ClusterSet &badClusters,
const Cluster *&pFragmentCluster)
const 242 pFragmentCluster =
nullptr;
245 const std::string currentListName((TPC_VIEW_U == fragmentHitType) ? pAlgorithm->
GetClusterListNameU() :
248 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*pAlgorithm, currentListName));
254 for (
const Cluster *
const pCluster : clusterList)
256 if (deletedClusters.end() != std::find(deletedClusters.begin(), deletedClusters.end(), pCluster))
259 if (!pCluster->IsAvailable())
260 throw StatusCodeException(STATUS_CODE_FAILURE);
262 CaloHitList clusterHitList;
263 pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterHitList);
265 CaloHitList daughterHits, separateHits;
266 for (
const CaloHit *
const pCaloHit : clusterHitList)
268 if (caloHitSet.count(pCaloHit))
270 daughterHits.push_back(pCaloHit);
274 separateHits.push_back(pCaloHit);
278 if (daughterHits.empty())
279 throw StatusCodeException(STATUS_CODE_FAILURE);
281 this->
Recluster(pAlgorithm, pCluster, daughterHits, separateHits, deletedClusters, badClusters, pFragmentCluster);
283 if (badClusters.count(pFragmentCluster))
284 throw StatusCodeException(STATUS_CODE_FAILURE);
288 ClusterList::iterator modifiedIter(std::find(modifiedClusters.begin(), modifiedClusters.end(), pCluster));
289 if (deletedClusters.end() != std::find(deletedClusters.begin(), deletedClusters.end(), pCluster))
291 if (modifiedClusters.end() != modifiedIter)
292 modifiedClusters.erase(modifiedIter);
294 else if (modifiedClusters.end() == modifiedIter)
296 modifiedClusters.push_back(pCluster);
300 if (!pFragmentCluster)
301 throw StatusCodeException(STATUS_CODE_FAILURE);
307 const CaloHitList &separateHits, ClusterList &deletedClusters, ClusterSet &badClusters,
const Cluster *&pFragmentCluster)
const 309 if (separateHits.empty())
311 if (!pFragmentCluster)
313 pFragmentCluster = pCluster;
318 if (!badClusters.insert(pCluster).second)
319 throw StatusCodeException(STATUS_CODE_FAILURE);
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));
327 for (
const CaloHit *
const pCaloHit : daughterHits)
328 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*pAlgorithm, pCluster, pCaloHit));
330 if (!pFragmentCluster)
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));
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));
343 (void) badClusters.erase(pFragmentCluster);
347 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*pAlgorithm, pFragmentCluster, &daughterHits));
356 ClusterList rebuildList;
358 for (
const Cluster *
const pCluster : modifiedClusters)
360 if (pCluster->IsAvailable())
361 rebuildList.push_back(pCluster);
364 if (!rebuildList.empty())
371 const ClusterList &clustersToRemoveFromTensor,
const ClusterList &clustersToAddToTensor)
const 373 for (
ClusterList::const_iterator iter = clustersToRemoveFromTensor.begin(), iterEnd = clustersToRemoveFromTensor.end(); iter != iterEnd; ++iter)
376 ClusterList newKeyClusters;
382 ClusterList affectedKeyClusters;
395 ClusterList &affectedKeyClusters)
const 409 if (clustersToRemoveFromTensor.end() == std::find(clustersToRemoveFromTensor.begin(), clustersToRemoveFromTensor.end(), *fIter))
412 if ((TPC_VIEW_U != fragmentHitType) && (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterU->first)))
413 affectedKeyClusters.push_back(tIterU->first);
415 if ((TPC_VIEW_V != fragmentHitType) && (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterV->first)))
416 affectedKeyClusters.push_back(tIterV->first);
418 if ((TPC_VIEW_W != fragmentHitType) && (affectedKeyClusters.end() == std::find(affectedKeyClusters.begin(), affectedKeyClusters.end(), tIterW->first)))
419 affectedKeyClusters.push_back(tIterW->first);
434 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
437 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
440 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
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.
const_iterator begin() const
Returns an iterator referring to the first element in the overlap tensor.
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.
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...
std::vector< Element > ElementList
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.
virtual void SelectInputClusters(const pandora::ClusterList *const pInputClusterList, pandora::ClusterList &selectedClusterList) const
Select a subset of input clusters for processing in this algorithm.
ThreeDTrackFragmentsAlgorithm class.
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.
TheTensor::const_iterator const_iterator
void RebuildClusters(const pandora::ClusterList &rebuildList, pandora::ClusterList &newClusters) const
Rebuild clusters after fragmentation.