9 #include "Pandora/AlgorithmHeaders.h" 26 VertexBasedPfoMopUpAlgorithm::VertexBasedPfoMopUpAlgorithm() :
27 m_minVertexLongitudinalDistance(-2.5
f),
28 m_maxVertexTransverseDistance(1.5
f),
29 m_minVertexAssociatedHitTypes(2),
30 m_coneAngleCentile(0.8
f),
31 m_maxConeCosHalfAngle(0.95
f),
32 m_maxConeLengthMultiplier(3.
f),
33 m_directionTanAngle(1.732
f),
34 m_directionApexShift(0.333
f),
35 m_meanBoundedFractionCut(0.6
f),
36 m_maxBoundedFractionCut(0.7
f),
37 m_minBoundedFractionCut(0.3
f),
38 m_minConsistentDirections(2),
39 m_minConsistentDirectionsTrack(3)
48 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetCurrentList(*
this, pVertexList));
50 const Vertex *
const pSelectedVertex((pVertexList && (pVertexList->size() == 1) && (VERTEX_3D == (*(pVertexList->begin()))->GetVertexType())) ? *(pVertexList->begin()) :
nullptr);
54 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
55 std::cout <<
"VertexBasedPfoMopUp: unable to find vertex in current list " << std::endl;
57 return STATUS_CODE_SUCCESS;
62 PfoList vertexPfos, nonVertexPfos;
63 this->
GetInputPfos(pSelectedVertex, vertexPfos, nonVertexPfos);
66 this->
GetPfoAssociations(pSelectedVertex, vertexPfos, nonVertexPfos, pfoAssociationList);
68 std::sort(pfoAssociationList.begin(), pfoAssociationList.end());
75 return STATUS_CODE_SUCCESS;
91 if ((pVertexPfo->GetClusterList().size() != pDaughterPfo->GetClusterList().size()) || (3 != pVertexPfo->GetClusterList().size()))
92 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
94 return PfoAssociation(pVertexPfo, pDaughterPfo, hitTypeToAssociationMap.at(TPC_VIEW_U), hitTypeToAssociationMap.at(TPC_VIEW_V), hitTypeToAssociationMap.at(TPC_VIEW_W));
101 StringVector listNames;
105 for (
const std::string &listName : listNames)
107 const PfoList *pPfoList(
nullptr);
109 if (STATUS_CODE_SUCCESS != PandoraContentApi::GetList(*
this, listName, pPfoList))
112 for (
const Pfo *
const pPfo : *pPfoList)
114 PfoList &pfoTargetList(this->
IsVertexAssociated(pPfo, pVertex) ? vertexPfos : nonVertexPfos);
115 pfoTargetList.push_back(pPfo);
124 if (VERTEX_3D != pVertex->GetVertexType())
125 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
129 for (
const Cluster *
const pCluster : pPfo->GetClusterList())
133 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
143 hitTypeSet.insert(hitType);
145 catch (StatusCodeException &) {}
148 const unsigned int nVertexAssociatedHitTypes(hitTypeSet.size());
157 for (
const Pfo *
const pVertexPfo : vertexPfos)
159 for (
const Pfo *
const pDaughterPfo : nonVertexPfos)
164 pfoAssociationList.push_back(pfoAssociation);
166 catch (StatusCodeException &) {}
174 const Pfo *
const pDaughterPfo)
const 176 if (pVertexPfo->GetClusterList().empty() || pDaughterPfo->GetClusterList().empty())
177 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
181 for (
const Cluster *
const pVertexCluster : pVertexPfo->GetClusterList())
185 for (
const Cluster *
const pDaughterCluster : pDaughterPfo->GetClusterList())
189 if (vertexHitType != daughterHitType)
193 hitTypeToAssociationMap[vertexHitType] = clusterAssociation;
197 return this->
GetPfoAssociation(pVertexPfo, pDaughterPfo, hitTypeToAssociationMap);
203 const Cluster *
const pVertexCluster,
const Cluster *
const pDaughterCluster)
const 215 const bool isConsistentDirection(vertexClusterDirection == daughterClusterDirection);
217 return ClusterAssociation(pVertexCluster, pDaughterCluster, boundedFraction, isConsistentDirection);
224 const PfoList *pTrackPfoList(
nullptr);
239 if ((pTrackPfoList->end() != std::find(pTrackPfoList->begin(), pTrackPfoList->end(), pfoAssociation.GetVertexPfo())) &&
240 (pTrackPfoList->end() != std::find(pTrackPfoList->begin(), pTrackPfoList->end(), pfoAssociation.GetDaughterPfo())))
245 if (((pTrackPfoList->end() != std::find(pTrackPfoList->begin(), pTrackPfoList->end(), pfoAssociation.GetVertexPfo())) ||
246 (pTrackPfoList->end() != std::find(pTrackPfoList->begin(), pTrackPfoList->end(), pfoAssociation.GetDaughterPfo()))) &&
264 const PfoList *pTrackPfoList(
nullptr), *pShowerPfoList(
nullptr);
268 if (!pTrackPfoList && !pShowerPfoList)
269 throw StatusCodeException(STATUS_CODE_FAILURE);
271 const Pfo *
const pVertexPfo(pfoAssociation.
GetVertexPfo());
272 const bool isvertexTrack(pTrackPfoList && (pTrackPfoList->end() != std::find(pTrackPfoList->begin(), pTrackPfoList->end(), pVertexPfo)));
274 const bool isDaughterShower(pShowerPfoList && (pShowerPfoList->end() != std::find(pShowerPfoList->begin(), pShowerPfoList->end(), pDaughterPfo)));
278 if (isvertexTrack && isDaughterShower)
280 const PfoList vertexPfoList(1, pVertexPfo);
282 PandoraContentApi::ParticleFlowObject::Metadata metadata;
283 metadata.m_particleId = E_MINUS;
284 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*
this, pVertexPfo, metadata));
294 m_pVertexCluster(nullptr),
295 m_pDaughterCluster(nullptr),
296 m_boundedFraction(0.
f),
297 m_isConsistentDirection(false)
304 const float boundedFraction,
const bool isConsistentDirection) :
317 m_pVertexPfo(pVertexPfo),
318 m_pDaughterPfo(pDaughterPfo),
319 m_clusterAssociationU(clusterAssociationU),
320 m_clusterAssociationV(clusterAssociationV),
321 m_clusterAssociationW(clusterAssociationW)
350 unsigned int nConsistentDirections(0);
353 ++nConsistentDirections;
356 ++nConsistentDirections;
359 ++nConsistentDirections;
361 return nConsistentDirections;
381 const float coneAngleCentile,
const float maxCosHalfAngle) :
382 m_pCluster(pCluster),
383 m_apex(vertexPosition2D),
384 m_direction(0.
f, 0.
f, 0.
f),
386 m_coneCosHalfAngle(0.
f)
392 if (
m_coneLength < std::numeric_limits<float>::epsilon())
405 unsigned int nMatchedHits(0);
406 const OrderedCaloHitList &orderedCaloHitList(pDaughterCluster->GetOrderedCaloHitList());
412 const CartesianVector &positionVector((*hIter)->GetPositionVector());
424 if (0 == pDaughterCluster->GetNCaloHits())
425 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
427 return (static_cast<float>(nMatchedHits) /
static_cast<float>(pDaughterCluster->GetNCaloHits()));
434 const OrderedCaloHitList &orderedCaloHitList(
m_pCluster->GetOrderedCaloHitList());
435 float sumDxDz(0.
f), sumDxDx(0.
f);
439 for (
CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
441 const CartesianVector apexDisplacement((*hitIter)->GetPositionVector() -
m_apex);
442 sumDxDz += apexDisplacement.GetX() * apexDisplacement.GetZ();
443 sumDxDx += apexDisplacement.GetX() * apexDisplacement.GetX();
447 if (sumDxDx < std::numeric_limits<float>::epsilon())
448 return CartesianVector(0.
f, 0.
f, 1.
f);
450 return CartesianVector(1.
f, 0.
f, sumDxDz / sumDxDx).GetUnitVector();
457 float maxProjectedLength(0.
f);
458 const OrderedCaloHitList &orderedCaloHitList(
m_pCluster->GetOrderedCaloHitList());
462 for (
CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
464 const float projectedLength(
m_direction.GetDotProduct((*hitIter)->GetPositionVector() -
m_apex));
466 if (std::fabs(projectedLength) > std::fabs(maxProjectedLength))
467 maxProjectedLength = projectedLength;
471 return maxProjectedLength;
478 FloatVector halfAngleValues;
479 const OrderedCaloHitList &orderedCaloHitList(
m_pCluster->GetOrderedCaloHitList());
483 for (
CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
484 halfAngleValues.push_back(
m_direction.GetOpeningAngle((*hitIter)->GetPositionVector() -
m_apex));
487 std::sort(halfAngleValues.begin(), halfAngleValues.end());
489 if (halfAngleValues.empty())
490 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
492 const unsigned int halfAngleBin(coneAngleCentile * halfAngleValues.size());
493 return std::cos(halfAngleValues.at(halfAngleBin));
501 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
504 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
507 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
510 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
513 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
516 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
519 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
522 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
525 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
528 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
531 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
534 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
537 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
540 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
543 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::set< pandora::HitType > HitTypeSet
float GetBoundedFraction(const pandora::Cluster *const pDaughterCluster, const float coneLengthMultiplier) const
Get the fraction of hits in a candidate daughter cluster bounded by the cone.
void GetPfoAssociations(const pandora::Vertex *const pVertex, const pandora::PfoList &vertexPfos, const pandora::PfoList &nonVertexPfos, PfoAssociationList &pfoAssociationList) const
Get the list of associations between vertex-associated pfos and non-vertex-associated pfos...
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
Header file for the pfo helper class.
unsigned int m_minVertexAssociatedHitTypes
The min number of vertex associated hit types for a vertex associated pfo.
float m_maxConeLengthMultiplier
Consider hits as bound if inside cone, with projected distance less than N times cone length...
PfoAssociation(const pandora::Pfo *const pVertexPfo, const pandora::Pfo *const pDaughterPfo, const ClusterAssociation &clusterAssociationU, const ClusterAssociation &clusterAssociationV, const ClusterAssociation &clusterAssociationW)
Constructor.
ClusterAssociation GetClusterAssociation(const pandora::Vertex *const pVertex, const pandora::Cluster *const pVertexCluster, const pandora::Cluster *const pDaughterCluster) const
Get cluster association details between a vertex-associated cluster and a non-vertex associated daugh...
ConeParameters(const pandora::Cluster *const pCluster, const pandora::CartesianVector &vertexPosition2D, const float coneAngleCentile, const float maxConeCosHalfAngle)
Constructor.
Header file for the lar pointing cluster class.
const pandora::Cluster * m_pDaughterCluster
The address of the daughter cluster.
unsigned int GetNConsistentDirections() const
Get the number of views for which the vertex and daughter cluster directions are consistent.
float m_coneAngleCentile
Cluster cone angle is defined using specified centile of distribution of hit half angles...
float GetCosHalfAngleEstimate(const float coneAngleCentile) const
Get the cone cos half angle estimate.
unsigned int m_minConsistentDirections
The minimum number of consistent cluster directions to allow a pfo merge.
pandora::StringVector m_daughterListNames
The list of potential daughter object list names.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
pandora::CartesianVector m_direction
The cone direction.
void MergePfos(const PfoAssociation &pfoAssociation) const
Merge the vertex and daughter pfos (deleting daughter pfo, merging clusters, etc.) described in the s...
std::vector< PfoAssociation > PfoAssociationList
LArPointingCluster class.
float GetMaxBoundedFraction() const
Get the maximum bounded fraction from the u, v and w views.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
bool m_isConsistentDirection
Whether the vertex and daughter clusters have consistent directions.
float m_maxVertexTransverseDistance
Vertex association check: max transverse distance cut.
float m_minVertexLongitudinalDistance
Vertex association check: min longitudinal distance cut.
float m_maxBoundedFractionCut
Cut on association info (max bounded fraction) for determining pfo merges.
float GetSignedConeLength() const
Get the cone length (signed, by projections of hits onto initial direction estimate) ...
bool ProcessPfoAssociations(const PfoAssociationList &pfoAssociationList) const
Process the list of pfo associations, merging the best-matching pfo.
ClusterAssociation()
Default constructor.
Header file for the geometry helper class.
std::map< pandora::HitType, ClusterAssociation > HitTypeToAssociationMap
Header file for the cluster helper class.
float m_directionApexShift
Direction determination, look for vertex inside triangle with apex shifted along the cluster length...
const Vertex & GetOuterVertex() const
Get the outer vertex.
float m_meanBoundedFractionCut
Cut on association info (mean bounded fraction) for determining pfo merges.
pandora::StatusCode Run()
float m_coneLength
The cone length.
const Vertex & GetInnerVertex() const
Get the inner vertex.
virtual PfoAssociation GetPfoAssociation(const pandora::Pfo *const pVertexPfo, const pandora::Pfo *const pDaughterPfo, HitTypeToAssociationMap &hitTypeToAssociationMap) const
Get pfo association details between a vertex-associated pfo and a non-vertex associated daughter cand...
float m_coneCosHalfAngle
The cone cos half angle.
pandora::CartesianVector GetDirectionEstimate() const
Get the cone direction estimate, with apex fixed at the 2d vertex position.
float m_boundedFraction
The fraction of daughter hits bounded by the cone defined by the vertex cluster.
const ClusterAssociation & GetClusterAssociationW() const
Get the cluster association in the w view.
const pandora::Pfo * m_pDaughterPfo
The address of the non-vertex-associated candidate daughter pfo.
float m_directionTanAngle
Direction determination, look for vertex inside triangle with apex shifted along the cluster length...
void GetInputPfos(const pandora::Vertex *const pVertex, pandora::PfoList &vertexPfos, pandora::PfoList &nonVertexPfos) const
Get the list of input pfos and divide them into vertex-associated and non-vertex-associated lists...
Header file for the vertex helper class.
virtual bool IsVertexAssociated(const pandora::CartesianVector &vertex2D, const LArPointingCluster &pointingCluster) const
Whether a specified pfo is associated with a specified vertex.
unsigned int m_minConsistentDirectionsTrack
The minimum number of consistent cluster directions to allow a merge involving a track pfo...
pandora::CartesianVector m_apex
The cone apex.
float m_maxConeCosHalfAngle
Maximum value for cosine of cone half angle.
const pandora::Pfo * GetDaughterPfo() const
Get the address of the non-vertex-associated candidate daughter pfo.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const ClusterAssociation & GetClusterAssociationU() const
Get the cluster association in the u view.
std::string m_trackPfoListName
The input track pfo list name.
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.
ClusterAssociation class.
const pandora::Pfo * GetVertexPfo() const
Get the address of the vertex-associated pfo.
float GetMinBoundedFraction() const
Get the minimum bounded fraction from the u, v and w views.
const ClusterAssociation & GetClusterAssociationV() const
Get the cluster association in the v view.
const pandora::Cluster * m_pVertexCluster
The address of the vertex cluster.
const pandora::Pfo * m_pVertexPfo
The address of the vertex-associated pfo.
float GetMeanBoundedFraction() const
Get the mean bounded fraction, averaging over the u, v and w views.
bool operator<(const PfoAssociation &rhs) const
operator<
std::list< Vertex > VertexList
const pandora::Cluster * m_pCluster
The parent cluster.
Header file for the vertex based pfo mop up algorithm class.
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. ...
std::string m_showerPfoListName
The input shower pfo list name.
float m_minBoundedFractionCut
Cut on association info (min bounded fraction) for determining pfo merges.