9 #include "Pandora/AlgorithmHeaders.h" 25 SlidingConePfoMopUpAlgorithm::SlidingConePfoMopUpAlgorithm() :
28 m_maxIterations(1000),
29 m_maxHitsToConsider3DTrack(100),
30 m_minHitsToConsider3DShower(20),
31 m_halfWindowLayers(20),
34 m_coneLengthMultiplier(7.
f),
35 m_maxConeLength(126.
f),
36 m_coneTanHalfAngle1(0.5
f),
37 m_coneBoundedFraction1(0.5
f),
38 m_coneTanHalfAngle2(0.75
f),
39 m_coneBoundedFraction2(0.75
f),
40 m_minVertexLongitudinalDistance(-2.5
f),
41 m_maxVertexTransverseDistance(3.5
f)
49 const Vertex *pVertex(
nullptr);
54 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
55 std::cout <<
"SlidingConePfoMopUpAlgorithm - interaction vertex not available for use." << std::endl;
56 return STATUS_CODE_SUCCESS;
59 unsigned int nIterations(0);
74 return STATUS_CODE_SUCCESS;
85 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
88 ((pVertexList && (pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
97 const PfoList *pPfoList(
nullptr);
99 if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*
this, pfoListName, pPfoList))
102 for (
const Pfo *
const pPfo : *pPfoList)
104 ClusterList pfoClusters3D;
107 for (
const Cluster *
const pCluster3D : pfoClusters3D)
112 if (!clusterToPfoMap.insert(ClusterToPfoMap::value_type(pCluster3D, pPfo)).second)
113 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
115 clusters3D.push_back(pCluster3D);
132 const float pitchMax{std::max({pitchU, pitchV, pitchW})};
134 for (
const Cluster *
const pShowerCluster : clusters3D)
139 float coneLength(0.
f);
141 bool isShowerVertexAssociated(
false);
145 float layerPitch{0.f};
147 if (view == TPC_VIEW_U || view == TPC_VIEW_V || view == TPC_VIEW_W)
150 layerPitch = pitchMax;
158 const float vertexToMinLayer(!pVertex ? 0.
f : (pVertex->GetPosition() - minLayerPosition).GetMagnitude());
159 const float vertexToMaxLayer(!pVertex ? 0.
f : (pVertex->GetPosition() - maxLayerPosition).GetMagnitude());
165 isShowerVertexAssociated =
168 catch (
const StatusCodeException &)
173 for (
const Cluster *
const pNearbyCluster : clusters3D)
175 if (pNearbyCluster == pShowerCluster)
180 for (
const SimpleCone &simpleCone : simpleConeList)
182 const float boundedFraction1(simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength,
m_coneTanHalfAngle1));
183 const float boundedFraction2(simpleCone.GetBoundedHitFraction(pNearbyCluster, coneLength,
m_coneTanHalfAngle2));
184 const ClusterMerge clusterMerge(pShowerCluster, boundedFraction1, boundedFraction2);
186 if (clusterMerge < bestClusterMerge)
187 bestClusterMerge = clusterMerge;
190 if (isShowerVertexAssociated && this->
IsVertexAssociated(pNearbyCluster, pVertex, vertexAssociationMap))
195 clusterMergeMap[pNearbyCluster].push_back(bestClusterMerge);
199 for (ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
200 std::sort(mapEntry.second.begin(), mapEntry.second.end());
213 if (vertexAssociationMap.end() != iter)
216 const bool isVertexAssociated(this->
IsVertexAssociated(pCluster, pVertex->GetPosition(), pSlidingFitResult));
217 (void)vertexAssociationMap.insert(VertexAssociationMap::value_type(pCluster, isVertexAssociated));
219 return isVertexAssociated;
225 const Cluster *
const pCluster,
const CartesianVector &vertexPosition,
const ThreeDSlidingFitResult *
const pSlidingFitResult)
const 230 const float pitchMax{std::max({pitchU, pitchV, pitchW})};
234 float layerPitch{0.f};
236 if (view == TPC_VIEW_U || view == TPC_VIEW_V || view == TPC_VIEW_W)
239 layerPitch = pitchMax;
250 catch (
const StatusCodeException &)
262 for (
const ClusterMergeMap::value_type &mapEntry : clusterMergeMap)
263 daughterClusters.push_back(mapEntry.first);
266 bool pfosMerged(
false);
269 for (ClusterVector::const_reverse_iterator rIter = daughterClusters.rbegin(), rIterEnd = daughterClusters.rend(); rIter != rIterEnd; ++rIter)
271 const Cluster *
const pDaughterCluster(*rIter);
273 if (clusterReplacementMap.count(pDaughterCluster))
274 throw StatusCodeException(STATUS_CODE_FAILURE);
276 const Cluster *pParentCluster(clusterMergeMap.at(pDaughterCluster).at(0).GetParentCluster());
278 if (clusterReplacementMap.count(pParentCluster))
279 pParentCluster = clusterReplacementMap.at(pParentCluster);
282 if (pDaughterCluster == pParentCluster)
286 const Pfo *
const pDaughterPfo(clusterToPfoMap.at(pDaughterCluster));
287 const Pfo *
const pParentPfo(clusterToPfoMap.at(pParentCluster));
292 clusterReplacementMap[pDaughterCluster] = pParentCluster;
294 for (ClusterReplacementMap::value_type &mapEntry : clusterReplacementMap)
296 if (pDaughterCluster == mapEntry.second)
297 mapEntry.second = pParentCluster;
318 if (std::fabs(this->GetBoundedFraction1() - rhs.
GetBoundedFraction1()) > std::numeric_limits<float>::epsilon())
321 if (std::fabs(this->GetBoundedFraction2() - rhs.
GetBoundedFraction2()) > std::numeric_limits<float>::epsilon())
332 PANDORA_RETURN_RESULT_IF_AND_IF(
333 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"InputPfoListNames",
m_inputPfoListNames));
335 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"UseVertex",
m_useVertex));
337 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"LegacyMode",
m_legacyMode));
339 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxIterations",
m_maxIterations));
341 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
344 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
347 PANDORA_RETURN_RESULT_IF_AND_IF(
348 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitHalfWindow",
m_halfWindowLayers));
350 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NConeFitLayers",
m_nConeFitLayers));
352 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NConeFits",
m_nConeFits));
354 PANDORA_RETURN_RESULT_IF_AND_IF(
355 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeLengthMultiplier",
m_coneLengthMultiplier));
357 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxConeLength",
m_maxConeLength));
359 PANDORA_RETURN_RESULT_IF_AND_IF(
360 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeTanHalfAngle1",
m_coneTanHalfAngle1));
362 PANDORA_RETURN_RESULT_IF_AND_IF(
363 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeBoundedFraction1",
m_coneBoundedFraction1));
365 PANDORA_RETURN_RESULT_IF_AND_IF(
366 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeTanHalfAngle2",
m_coneTanHalfAngle2));
368 PANDORA_RETURN_RESULT_IF_AND_IF(
369 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"ConeBoundedFraction2",
m_coneBoundedFraction2));
371 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
374 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
std::unordered_map< const pandora::Cluster *, const pandora::Cluster * > ClusterReplacementMap
float GetBoundedFraction2() const
Get the bounded fraction for algorithm-specified cone angle 2.
void GetClusterMergeMap(const pandora::Vertex *const pVertex, const pandora::ClusterVector &clusters3D, const ClusterToPfoMap &clusterToPfoMap, ClusterMergeMap &clusterMergeMap) const
Get the cluster merge map describing all potential 3d cluster merges.
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.
float m_coneBoundedFraction2
The minimum cluster bounded fraction for association 2.
void GetInteractionVertex(const pandora::Vertex *&pVertex) const
Get the neutrino interaction vertex if it is available and if the algorithm is configured to do so...
Header file for the pfo helper class.
float m_maxConeLength
The maximum allowed cone length to use when calculating bounded cluster fractions.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
std::unordered_map< const pandora::Cluster *, const pandora::ParticleFlowObject * > ClusterToPfoMap
float m_coneLengthMultiplier
The cone length multiplier to use when calculating bounded cluster fractions.
std::vector< SimpleCone > SimpleConeList
pandora::StringVector m_daughterListNames
The list of potential daughter object list names.
void GetSimpleConeList(const unsigned int nLayersForConeFit, const unsigned int nCones, const ConeSelection coneSelection, SimpleConeList &simpleConeList, const float tanHalfAngle=0.5f, const bool legacyMode=true) const
Get the list of simple cones fitted to the three dimensional cluster.
bool MakePfoMerges(const ClusterToPfoMap &clusterToPfoMap, const ClusterMergeMap &clusterMergeMap) const
Make pfo merges based on the provided cluster merge map.
const ThreeDSlidingFitResult & GetSlidingFitResult() const
Get the sliding fit result for the full cluster.
LArPointingCluster class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void GetThreeDClusters(pandora::ClusterVector &clusters3D, ClusterToPfoMap &clusterToPfoMap) const
Get all 3d clusters contained in the input pfo lists and a mapping from clusters to pfos...
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
bool m_useVertex
Whether to use the interaction vertex to select useful cone directions.
Header file for the lar three dimensional sliding cone fit result class.
float GetBoundedFraction1() const
Get the bounded fraction for algorithm-specified cone angle 1.
bool IsVertexAssociated(const pandora::Cluster *const pCluster, const pandora::Vertex *const pVertex, VertexAssociationMap &vertexAssociationMap, const ThreeDSlidingFitResult *const pSlidingFitResult=nullptr) const
Whether a 3D cluster is nodally associated with a provided vertex.
Header file for the geometry helper class.
bool m_legacyMode
Whether to use the legacy cone generation.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
static bool IsShower(const pandora::ParticleFlowObject *const pPfo)
Return shower flag based on Pfo Particle ID.
unsigned int m_nConeFitLayers
The number of layers over which to sum fitted direction to obtain cone fit.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
unsigned int m_maxHitsToConsider3DTrack
The maximum number of hits in a 3d track cluster to warrant inclusion in algorithm.
const Vertex & GetInnerVertex() const
Get the inner vertex.
float m_coneTanHalfAngle1
The cone tan half angle to use when calculating bounded cluster fractions 1.
pandora::StringVector m_inputPfoListNames
The input pfo list names.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
Header file for the sliding cone pfo mop up algorithm class.
static const pandora::Cluster * GetParentCluster(const pandora::ClusterList &clusterList, const pandora::HitType hitType)
Select the parent cluster (same hit type and most hits) using a provided cluster list and hit type...
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
float m_coneBoundedFraction1
The minimum cluster bounded fraction for association 1.
pandora::StatusCode Run()
std::unordered_map< const pandora::Cluster *, bool > VertexAssociationMap
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
ThreeDSlidingFitResult class.
unsigned int m_maxIterations
The maximum allowed number of algorithm iterations.
virtual void MergeAndDeletePfos(const pandora::ParticleFlowObject *const pPfoToEnlarge, const pandora::ParticleFlowObject *const pPfoToDelete) const
Merge and delete a pair of pfos, with a specific set of conventions for cluster merging, vertex use, etc.
ConeSelection
ConeSelection enum.
unsigned int m_minHitsToConsider3DShower
The minimum number of hits in a 3d shower cluster to attempt cone fits.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
std::vector< art::Ptr< recob::Cluster > > ClusterVector
ThreeDSlidingConeFitResult class.
bool operator<(const ClusterMerge &rhs) const
operator <
unsigned int m_nConeFits
The number of cone fits to perform, spread roughly uniformly along the shower length.
std::unordered_map< const pandora::Cluster *, ClusterMergeList > ClusterMergeMap
const pandora::Cluster * GetParentCluster() const
Get the address of the candidate parent (shower) cluster.
std::list< Vertex > VertexList
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
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.
float m_coneTanHalfAngle2
The cone tan half angle to use when calculating bounded cluster fractions 2.
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.