26 m_minMatchedFraction(0.25f),
27 m_minMatchedSamplingPoints(40),
28 m_checkClusterProximities(true),
29 m_maxClusterSeparation(25.f),
30 m_checkClusterVertexRelations(true),
31 m_minVertexLongitudinalDistance(-2.5f),
32 m_maxVertexLongitudinalDistance(20.f),
33 m_maxVertexTransverseDistance(1.5f),
34 m_vertexAngularAllowance(3.f),
35 m_maxVertexAssociations(1),
36 m_checkClusterSplitPositions(false),
37 m_vetoMergeXDifference(2.f),
38 m_vetoMergeXOverlap(2.f)
47 std::cout <<
"----> Running Algorithm Tool: " << this->
GetInstanceName() <<
", " << this->
GetType() << std::endl;
61 overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
63 for (
const Cluster *
const pKeyCluster : sortedKeyClusters)
65 if (!pKeyCluster->IsAvailable())
68 unsigned int nU(0), nV(0), nW(0);
69 TensorType::ElementList elementList;
70 overlapTensor.GetConnectedElements(pKeyCluster,
true, elementList, nU, nV, nW);
75 for (TensorType::ElementList::const_iterator eIter = elementList.begin(); eIter != elementList.end(); ++eIter)
83 if (iteratorList.size() < 2)
86 this->
FindShowerMerges(pAlgorithm, iteratorList, usedClusters, clusterMergeMap);
95 if (usedClusters.count(eIter->GetClusterU()) || usedClusters.count(eIter->GetClusterV()) || usedClusters.count(eIter->GetClusterW()))
112 iteratorList.push_back(eIter);
114 for (TensorType::ElementList::const_iterator eIter2 = elementList.begin(); eIter2 != elementList.end(); ++eIter2)
122 for (IteratorList::const_iterator iIter = iteratorList.begin(); iIter != iteratorList.end(); ++iIter)
124 if ((*iIter) == eIter2)
127 unsigned int nMatchedClusters(0);
129 if ((*iIter)->GetClusterU() == eIter2->GetClusterU())
132 if ((*iIter)->GetClusterV() == eIter2->GetClusterV())
135 if ((*iIter)->GetClusterW() == eIter2->GetClusterW())
140 iteratorList.push_back(eIter2);
152 for (IteratorList::const_iterator iIter1 = iteratorList.begin(), iIter1End = iteratorList.end(); iIter1 != iIter1End; ++iIter1)
154 for (IteratorList::const_iterator iIter2 = iIter1; iIter2 != iIter1End; ++iIter2)
158 if (iIter1 == iIter2)
161 const TensorType::Element &element1(*(*iIter1));
162 const TensorType::Element &element2(*(*iIter2));
164 ClusterList clusterListU(1, element1.GetClusterU());
165 if (element1.GetClusterU() != element2.GetClusterU())
166 clusterListU.push_back(element2.GetClusterU());
168 ClusterList clusterListV(1, element1.GetClusterV());
169 if (element1.GetClusterV() != element2.GetClusterV())
170 clusterListV.push_back(element2.GetClusterV());
172 ClusterList clusterListW(1, element1.GetClusterW());
173 if (element1.GetClusterW() != element2.GetClusterW())
174 clusterListW.push_back(element2.GetClusterW());
176 const unsigned int nClustersU(clusterListU.size()), nClustersV(clusterListV.size()), nClustersW(clusterListW.size());
177 const unsigned int nClustersProduct(nClustersU * nClustersV * nClustersW);
182 if ((1 ==
m_nCommonClusters) && !((2 == nClustersU) || (2 == nClustersV) || (2 == nClustersW)))
208 usedClusters.insert(clusterListU.begin(), clusterListU.end());
209 usedClusters.insert(clusterListV.begin(), clusterListV.end());
210 usedClusters.insert(clusterListW.begin(), clusterListW.end());
223 if (1 == clusterList.size())
226 if (2 != clusterList.size())
229 const Cluster *
const pCluster1(*(clusterList.begin()));
230 const Cluster *
const pCluster2(*(++(clusterList.begin())));
249 const Vertex *
const pVertex(
250 ((pVertexList->size() == 1) && (
VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) : NULL);
255 unsigned int nVertexAssociations(0);
257 for (ClusterList::const_iterator iter = clusterList.begin(), iterEnd = clusterList.end(); iter != iterEnd; ++iter)
272 ++nVertexAssociations;
291 const unsigned int nClustersU(clusterListU.size()), nClustersV(clusterListV.size()), nClustersW(clusterListW.size());
292 const unsigned int nClustersProduct(nClustersU * nClustersV * nClustersW);
294 if (2 == nClustersProduct)
297 const ClusterList &clusterList1((1 == nClustersU) ? clusterListV : clusterListU);
298 const ClusterList &clusterList2((1 == nClustersU) ? clusterListW : (1 == nClustersV) ? clusterListW : clusterListV);
300 if ((2 != clusterList1.size()) || (2 != clusterList2.size()))
303 float splitXPosition1(0.f), overlapX1(0.f);
304 this->
GetSplitXDetails(pAlgorithm, *(clusterList1.begin()), *(++(clusterList1.begin())), splitXPosition1, overlapX1);
306 float splitXPosition2(0.f), overlapX2(0.f);
307 this->
GetSplitXDetails(pAlgorithm, *(clusterList2.begin()), *(++(clusterList2.begin())), splitXPosition2, overlapX2);
318 const Cluster *
const pClusterB,
float &splitXPosition,
float &overlapX)
const
329 floatVector.push_back(minXA);
330 floatVector.push_back(maxXA);
331 floatVector.push_back(minXB);
332 floatVector.push_back(maxXB);
333 std::sort(floatVector.begin(), floatVector.end());
335 if (4 != floatVector.size())
338 splitXPosition = 0.5f * (floatVector.at(1) + floatVector.at(2));
339 overlapX = std::max(0.f, std::min(maxXA, maxXB) - std::max(minXA, minXB));
346 if (1 == clusterList.size())
349 if (2 != clusterList.size())
352 const Cluster *
const pClusterA(*(clusterList.begin())), *
const pClusterB(*(++(clusterList.begin())));
359 const Cluster *
const pLowXCluster((minXA < minXB) ? pClusterA : pClusterB);
360 const Cluster *
const pHighXCluster((minXA < minXB) ? pClusterB : pClusterA);
361 clusterMergeMap[pLowXCluster].push_back(pHighXCluster);
371 for (
const auto &mapEntry : clusterMergeMap)
372 clusterList.push_back(mapEntry.first);
375 for (
const Cluster *
const pParentCluster : clusterList)
377 const ClusterList &daughterClusters(clusterMergeMap.at(pParentCluster));
379 for (
const Cluster *
const pDaughterCluster : daughterClusters)
381 if (consolidatedMergeMap.count(pDaughterCluster))
385 ClusterList &targetClusterList(consolidatedMergeMap[pParentCluster]);
386 targetClusterList.insert(targetClusterList.end(), daughterClusters.begin(), daughterClusters.end());
400 std::cout <<
"SplitShowersTool: NCommonClusters must be set to either 1 or 2 (provided: " <<
m_nCommonClusters <<
") " << std::endl;
401 return STATUS_CODE_INVALID_PARAMETER;
443 return STATUS_CODE_SUCCESS;
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the lar pointing cluster class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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,...
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
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 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.
LArPointingCluster class.
const Vertex & GetInnerVertex() const
Get the inner vertex.
const Vertex & GetOuterVertex() const
Get the outer vertex.
virtual bool MakeClusterMerges(const ClusterMergeMap &clusterMergeMap)
Merge clusters together.
std::vector< TensorType::ElementList::const_iterator > IteratorList
ThreeViewShowersAlgorithm::MatchingType::TensorType TensorType
float m_vetoMergeXOverlap
The x overlap between candidate cluster sliding fits below which may refuse a merge.
void SelectTensorElements(TensorType::ElementList::const_iterator eIter, const TensorType::ElementList &elementList, const pandora::ClusterSet &usedClusters, IteratorList &iteratorList) const
Select elements representing possible components of interest due to undershoots in clustering.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
float m_minMatchedFraction
The min matched sampling point fraction for use as a key tensor element.
void FindShowerMerges(ThreeViewShowersAlgorithm *const pAlgorithm, const IteratorList &iteratorList, pandora::ClusterSet &usedClusters, ClusterMergeMap &clusterMergeMap) const
Get cluster merges specific elements of the tensor.
bool ApplyChanges(ThreeViewShowersAlgorithm *const pAlgorithm, const ClusterMergeMap &clusterMergeMap) const
Apply the changes cached in a cluster merge map and update the tensor accordingly.
float m_vertexAngularAllowance
Vertex association check: pointing angular allowance in degrees.
unsigned int m_minMatchedSamplingPoints
The min number of matched sampling points for use as a key tensor element.
unsigned int m_maxVertexAssociations
The maximum number of vertex associations for clusters to be merged.
bool m_checkClusterSplitPositions
Whether to check the cluster split positions, if there are splits in multiple views.
float m_maxVertexLongitudinalDistance
Vertex association check: max longitudinal distance cut.
bool CheckClusterVertexRelations(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList) const
Check the consistency of the clusters in a provided cluster list with the event vertex,...
SplitShowersTool()
Default constructor.
bool m_checkClusterVertexRelations
Whether to check the consistency of the clusters with the event vertex.
bool PassesElementCuts(TensorType::ElementList::const_iterator eIter, const pandora::ClusterSet &usedClusters) const
Whether a provided (iterator to a) tensor element passes the selection cuts for undershoots identific...
float m_vetoMergeXDifference
The x distance between split positions in two views below which may refuse a merge.
bool Run(ThreeViewShowersAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void FindSplitShowers(ThreeViewShowersAlgorithm *const pAlgorithm, const TensorType &overlapTensor, ClusterMergeMap &clusterMergeMap) const
Find split showers, using information from the overlap tensor.
void GetSplitXDetails(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::Cluster *const pClusterA, const pandora::Cluster *const pClusterB, float &splitXPosition, float &overlapX) const
Get the x coordinate representing the midpoint between two clusters (hypothesis: clusters represent a...
bool CheckClusterSplitPositions(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterListU, const pandora::ClusterList &clusterListV, const pandora::ClusterList &clusterListW) const
Check the consistency of the split positions in the provided u, v and w cluster lists.
float m_maxClusterSeparation
The maximum separation for clusters to be merged.
bool m_checkClusterProximities
Whether to check the proximities of the candidate split shower clusters.
void SpecifyClusterMerges(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList, ClusterMergeMap &clusterMergeMap) const
Populate the cluster merge map, based on the information contained in the provided cluster list.
bool CheckClusterProximities(ThreeViewShowersAlgorithm *const pAlgorithm, const pandora::ClusterList &clusterList) const
Check the clusters in a provided cluster list are in suitable proximity for merging.
unsigned int m_nCommonClusters
The number of common clusters.
ThreeViewShowersAlgorithm class.
const TwoDSlidingShowerFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding shower fit result from the algorithm cache.
TwoDSlidingFitResult class.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
const TwoDSlidingFitResult & GetShowerFitResult() const
Get the sliding fit result for the full shower cluster.
float GetX() const
Get the cartesian x coordinate.
unsigned int GetOuterPseudoLayer() const
Get the outermost pseudo layer in the cluster.
unsigned int GetInnerPseudoLayer() const
Get the innermost pseudo layer in the cluster.
const CartesianVector GetCentroid(const unsigned int pseudoLayer) const
Get unweighted centroid for cluster at a particular pseudo layer, calculated using cached values of h...
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
const std::string & GetType() const
Get the type.
const Pandora & GetPandora() const
Get the associated pandora instance.
const std::string & GetInstanceName() const
Get the instance name.
StatusCodeException class.
const CartesianVector & GetPosition() const
Get the vertex position.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterMergeMap
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::unordered_set< const Cluster * > ClusterSet
std::vector< float > FloatVector
MANAGED_CONTAINER< const Vertex * > VertexList
StatusCode
The StatusCode enum.