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)
54 CartesianVector innerCoordinateLhs(0.
f, 0.
f, 0.
f), outerCoordinateLhs(0.
f, 0.
f, 0.
f);
56 const float dLhs2((outerCoordinateLhs - innerCoordinateLhs).GetMagnitudeSquared());
58 CartesianVector innerCoordinateRhs(0.
f, 0.
f, 0.
f), outerCoordinateRhs(0.
f, 0.
f, 0.
f);
60 const float dRhs2((outerCoordinateRhs - innerCoordinateRhs).GetMagnitudeSquared());
62 return (dLhs2 > dRhs2);
73 const ClusterList *pClusterList =
nullptr;
74 PANDORA_RETURN_RESULT_IF_AND_IF(
75 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this, clusterListName, pClusterList));
77 if (!pClusterList || pClusterList->empty())
79 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
80 std::cout <<
"ShowerGrowingAlgorithm: unable to find cluster list " << clusterListName << std::endl;
88 catch (StatusCodeException &statusCodeException)
91 throw statusCodeException;
95 return STATUS_CODE_SUCCESS;
103 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
104 const Vertex *
const pVertex(
105 ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
107 ClusterSet usedClusters;
121 const Cluster *pSeedCluster(
nullptr);
135 pSeedCluster =
nullptr;
138 clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
141 for (
const Cluster *
const pCluster : clusterVector)
143 if (!pCluster->IsAvailable())
146 if (MU_MINUS ==
std::abs(pCluster->GetParticleId()))
152 if (usedClusters.count(pCluster))
155 pSeedCluster = pCluster;
167 clusterVector.insert(clusterVector.end(), pClusterList->begin(), pClusterList->end());
169 if (clusterVector.empty())
175 for (
const Cluster *
const pCluster : clusterVector)
177 if (!pCluster->IsAvailable())
180 if (MU_MINUS ==
std::abs(pCluster->GetParticleId()))
189 seedClusters.push_back(pCluster);
191 catch (StatusCodeException &)
204 if (particleSeedVector.empty())
208 const ClusterList clusterList(*pClusterList);
210 for (
const Cluster *
const pCandidateCluster : clusterList)
212 if (!pCandidateCluster->IsAvailable())
215 if (MU_MINUS ==
std::abs(pCandidateCluster->GetParticleId()))
221 if (particleSeedVector.end() == std::find(particleSeedVector.begin(), particleSeedVector.end(), pCandidateCluster))
222 candidateClusters.push_back(pCandidateCluster);
228 for (
const Cluster *
const pSeedCluster : particleSeedVector)
239 const SeedAssociationList &seedAssociationList,
const std::string &clusterListName, ClusterSet &usedClusters)
const 241 ClusterList clusterList;
242 for (
const auto &mapEntry : seedAssociationList)
243 clusterList.push_back(mapEntry.first);
246 for (
const Cluster *
const pParentCluster : clusterList)
248 const ClusterVector &branchClusters(seedAssociationList.at(pParentCluster));
251 usedClusters.insert(pParentCluster);
252 usedClusters.insert(branchClusters.begin(), branchClusters.end());
262 for (
const Cluster *
const pBranchCluster : branchClusters)
264 if (pBranchCluster->IsAvailable())
266 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
267 PandoraContentApi::MergeAndDeleteClusters(*
this, pParentCluster, pBranchCluster, listName, listName));
279 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
280 const Vertex *
const pVertex(
281 ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
291 seedIter =
m_clusterDirectionMap.insert(ClusterDirectionMap::value_type(pClusterSeed, direction)).first;
327 if ((checkSeedForward == checkCandidateForward) && (checkSeedBackward == checkCandidateBackward))
361 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
362 const Vertex *
const pVertex(
363 ((pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
369 unsigned int nVertexAssociatedSeeds(0), nVertexAssociatedNonSeeds(0);
371 ClusterList clusterList;
372 for (
const auto &mapEntry : seedAssociationList)
373 clusterList.push_back(mapEntry.first);
376 for (
const Cluster *
const pSeedCluster : clusterList)
378 const ClusterVector &associatedClusters(seedAssociationList.at(pSeedCluster));
387 catch (StatusCodeException &)
392 for (
const Cluster *
const pAssociatedCluster : associatedClusters)
398 catch (StatusCodeException &)
407 const float figureOfMerit(static_cast<float>(nVertexAssociatedSeeds) - static_cast<float>(nVertexAssociatedNonSeeds));
408 return figureOfMerit;
415 unsigned int nConnections(0);
430 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"InputClusterListNames",
m_inputClusterListNames));
432 PANDORA_RETURN_RESULT_IF_AND_IF(
433 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinCaloHitsPerCluster",
m_minCaloHitsPerCluster));
435 PANDORA_RETURN_RESULT_IF_AND_IF(
436 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NearbyClusterDistance",
m_nearbyClusterDistance));
438 PANDORA_RETURN_RESULT_IF_AND_IF(
439 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"RemoteClusterDistance",
m_remoteClusterDistance));
441 PANDORA_RETURN_RESULT_IF_AND_IF(
442 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"DirectionTanAngle",
m_directionTanAngle));
444 PANDORA_RETURN_RESULT_IF_AND_IF(
445 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"DirectionApexShift",
m_directionApexShift));
447 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
450 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
453 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
456 PANDORA_RETURN_RESULT_IF_AND_IF(
457 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"VertexAngularAllowance",
m_vertexAngularAllowance));
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.
constexpr auto abs(T v)
Returns the absolute value of the argument.
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.
std::unordered_map< const pandora::Cluster *, ClusterAssociationMap > ClusterUsageMap
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...
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)
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
AssociationType AreClustersAssociated(const pandora::Cluster *const pClusterSeed, const pandora::Cluster *const pCluster) const
Determine whether two clusters are associated.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
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.