9 #include "Pandora/AlgorithmHeaders.h" 25 ShowerGrowingAlgorithm::ShowerGrowingAlgorithm() :
26 m_minCaloHitsPerCluster(5),
27 m_nearbyClusterDistance(2.5
f),
28 m_remoteClusterDistance(10.
f),
29 m_directionTanAngle(1.732
f),
30 m_directionApexShift(0.333
f),
31 m_minVertexLongitudinalDistance(-2.5
f),
32 m_maxVertexLongitudinalDistance(20.
f),
33 m_maxVertexTransverseDistance(1.5
f),
34 m_vertexAngularAllowance(3.
f)
52 CartesianVector innerCoordinateLhs(0.
f, 0.
f, 0.
f), outerCoordinateLhs(0.
f, 0.
f, 0.
f);
54 const float dLhs2((outerCoordinateLhs - innerCoordinateLhs).GetMagnitudeSquared());
56 CartesianVector innerCoordinateRhs(0.
f, 0.
f, 0.
f), outerCoordinateRhs(0.
f, 0.
f, 0.
f);
58 const float dRhs2((outerCoordinateRhs - innerCoordinateRhs).GetMagnitudeSquared());
60 return (dLhs2 > dRhs2);
71 const ClusterList *pClusterList =
nullptr;
72 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this, clusterListName, pClusterList));
74 if (!pClusterList || pClusterList->empty())
76 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
77 std::cout <<
"ShowerGrowingAlgorithm: unable to find cluster list " << clusterListName << std::endl;
85 catch (StatusCodeException &statusCodeException)
88 throw statusCodeException;
92 return STATUS_CODE_SUCCESS;
100 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
101 const Vertex *
const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
103 ClusterSet usedClusters;
117 const Cluster *pSeedCluster(
nullptr);
130 const Cluster *&pSeedCluster)
const 132 pSeedCluster =
nullptr;
135 clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
138 for (
const Cluster *
const pCluster : clusterVector)
140 if (!pCluster->IsAvailable())
143 if (MU_MINUS == std::abs(pCluster->GetParticleId()))
149 if (usedClusters.count(pCluster))
152 pSeedCluster = pCluster;
165 clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
167 if (clusterVector.empty())
173 for (
const Cluster *
const pCluster : clusterVector)
175 if (!pCluster->IsAvailable())
178 if (MU_MINUS == std::abs(pCluster->GetParticleId()))
187 seedClusters.push_back(pCluster);
189 catch (StatusCodeException &)
202 if (particleSeedVector.empty())
206 const ClusterList clusterList(*pClusterList);
208 for (
const Cluster *
const pCandidateCluster : clusterList)
210 if (!pCandidateCluster->IsAvailable())
213 if (MU_MINUS == std::abs(pCandidateCluster->GetParticleId()))
219 if (particleSeedVector.end() == std::find(particleSeedVector.begin(), particleSeedVector.end(), pCandidateCluster))
220 candidateClusters.push_back(pCandidateCluster);
226 for (
const Cluster *
const pSeedCluster : particleSeedVector)
237 ClusterSet &usedClusters)
const 239 ClusterList clusterList;
240 for (
const auto &mapEntry : seedAssociationList) clusterList.push_back(mapEntry.first);
243 for (
const Cluster *
const pParentCluster : clusterList)
245 const ClusterVector &branchClusters(seedAssociationList.at(pParentCluster));
248 usedClusters.insert(pParentCluster);
249 usedClusters.insert(branchClusters.begin(), branchClusters.end());
259 for (
const Cluster *
const pBranchCluster : branchClusters)
261 if (pBranchCluster->IsAvailable())
263 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pParentCluster, pBranchCluster, listName, listName));
275 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
276 const Vertex *
const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
285 seedIter =
m_clusterDirectionMap.insert(ClusterDirectionMap::value_type(pClusterSeed, direction)).first;
321 if ((checkSeedForward == checkCandidateForward) && (checkSeedBackward == checkCandidateBackward))
358 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
359 const Vertex *
const pVertex(((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
365 unsigned int nVertexAssociatedSeeds(0), nVertexAssociatedNonSeeds(0);
367 ClusterList clusterList;
368 for (
const auto &mapEntry : seedAssociationList) clusterList.push_back(mapEntry.first);
371 for (
const Cluster *
const pSeedCluster : clusterList)
373 const ClusterVector &associatedClusters(seedAssociationList.at(pSeedCluster));
378 try {pointingClusterSeedList.push_back(
LArPointingCluster(pSeedCluster));}
catch (StatusCodeException &) {}
381 for (
const Cluster *
const pAssociatedCluster : associatedClusters)
383 try {pointingClusterNonSeedList.push_back(
LArPointingCluster(pAssociatedCluster));}
catch (StatusCodeException &) {}
390 const float figureOfMerit(static_cast<float>(nVertexAssociatedSeeds) - static_cast<float>(nVertexAssociatedNonSeeds));
391 return figureOfMerit;
398 unsigned int nConnections(0);
413 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"InputClusterListNames",
m_inputClusterListNames));
415 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
418 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
421 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
424 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
427 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
430 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
433 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
436 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
439 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
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.
pandora::StringVector m_inputClusterListNames
The names of the input cluster lists.
Header file for the lar pointing cluster class.
static bool IsEmission(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
Whether pointing vertex is emitted from a given position.
std::vector< LArPointingCluster > LArPointingClusterList
float m_directionApexShift
Direction determination, look for vertex inside triangle with apex shifted along the cluster length...
float m_maxVertexLongitudinalDistance
Vertex association check: max longitudinal distance cut.
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterUsageMap
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
AssociationType
AssociationType enum.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void GetSeedAssociationList(const pandora::ClusterVector &particleSeedVector, const pandora::ClusterList *const pClusterList, SeedAssociationList &seedAssociationList) const
Get the seed association list for a given vector of particle seed candidates.
void GetAllVertexSeedCandidates(const pandora::ClusterList *const pClusterList, const pandora::Vertex *const pVertex, pandora::ClusterVector &seedClusters) const
Get all seed candidates associated with a provided vertex.
bool GetNextSeedCandidate(const pandora::ClusterList *const pClusterList, const pandora::ClusterSet &usedClusters, const pandora::Cluster *&pSeedCluster) const
Get the next seed candidate, using a list of available candidates and a list of those already used...
Header file for the geometry helper class.
std::unordered_map< const pandora::Cluster *, pandora::ClusterVector > SeedAssociationList
float m_directionTanAngle
Direction determination, look for vertex inside triangle with apex shifted along the cluster length...
void FindAssociatedClusters(const pandora::Cluster *const pParticleSeed, pandora::ClusterVector &candidateClusters, ClusterUsageMap &forwardUsageMap, ClusterUsageMap &backwardUsageMap) const
Find clusters associated with a particle seed.
Header file for the cluster helper class.
unsigned int GetNVertexConnections(const pandora::CartesianVector &vertexPosition2D, const LArPointingClusterList &pointingClusterList) const
Get the number of clusters associated with the vertex.
void ProcessSeedAssociationDetails(const SeedAssociationList &seedAssociationList, const std::string &clusterListName, pandora::ClusterSet &usedClusters) const
Process the details stored in a specified seed association list.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
const Vertex & GetOuterVertex() const
Get the outer vertex.
static bool SortClusters(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sorting for clusters to determine order in which seeds are considered.
const Vertex & GetInnerVertex() const
Get the inner vertex.
void SimpleModeShowerGrowing(const pandora::ClusterList *const pClusterList, const std::string &clusterListName) const
Simple single-pass shower growing mode.
void ProcessBranchClusters(const pandora::Cluster *const pParentCluster, const pandora::ClusterVector &branchClusters, const std::string &listName) const
Process the list of branch clusters, merging with specified parent cluster, dealing with any existing...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
float m_nearbyClusterDistance
The nearby cluster distance, used for determining cluster associations.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
Header file for the shower growing algorithm class.
void IdentifyClusterMerges(const pandora::ClusterVector &particleSeedVector, const ClusterUsageMap &backwardUsageMap, SeedAssociationList &seedAssociationList) const
Identify cluster merges.
pandora::StatusCode Run()
unsigned int m_minCaloHitsPerCluster
The minimum number of calo hits per (seed or branch) cluster.
bool IsVertexAssociated(const LArPointingCluster &pointingCluster, const pandora::CartesianVector &vertexPosition2D) const
Whether a pointing cluster is assciated with a provided 2D vertex projection.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
AssociationType AreClustersAssociated(const pandora::Cluster *const pClusterSeed, const pandora::Cluster *const pCluster) const
Determine whether two clusters are associated.
float GetFigureOfMerit(const SeedAssociationList &seedAssociationList) const
Get a figure of merit representing the consistency of the provided seed associated list...
std::list< Vertex > VertexList
ClusterDirectionMap m_clusterDirectionMap
The cluster direction map.
float m_vertexAngularAllowance
Vertex association check: pointing angular allowance in degrees.
static bool IsNode(const pandora::CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex, const float minLongitudinalDistance, const float maxTransverseDistance)
Whether pointing vertex is adjacent to a given position.
static ClusterDirection GetClusterDirectionInZ(const pandora::Pandora &pandora, const pandora::Vertex *const pVertex, const pandora::Cluster *const pCluster, const float tanAngle, const float apexShift)
Get the direction of the cluster in z, using a projection of the provided vertex. ...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
float m_remoteClusterDistance
The remote cluster distance, used for determining cluster associations.