9 #include "Pandora/AlgorithmHeaders.h"
21 DeltaRayIdentificationAlgorithm::DeltaRayIdentificationAlgorithm() :
22 m_distanceForMatching(3.f),
23 m_minParentLengthSquared(10.f * 10.f),
24 m_maxDaughterLengthSquared(175.f * 175.f)
32 PfoVector parentPfos, daughterPfos;
36 if (parentPfos.empty())
38 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
40 return STATUS_CODE_SUCCESS;
48 PfoList newDaughterPfoList;
51 if (!newDaughterPfoList.empty())
53 PANDORA_THROW_RESULT_IF(
57 return STATUS_CODE_SUCCESS;
64 const PfoList *pPfoList = NULL;
65 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this, inputPfoListName, pPfoList));
70 outputPfoVector.insert(outputPfoVector.end(), pPfoList->begin(), pPfoList->end());
78 PfoSet parentPfoList, daughterPfoList;
79 parentPfoList.insert(parentPfos.begin(), parentPfos.end());
80 daughterPfoList.insert(daughterPfos.begin(), daughterPfos.end());
82 PfoVector allPfos(parentPfos.begin(), parentPfos.end());
83 allPfos.insert(allPfos.end(), daughterPfos.begin(), daughterPfos.end());
86 for (PfoVector::const_iterator iter1 = parentPfos.begin(), iterEnd1 = parentPfos.end(); iter1 != iterEnd1; ++iter1)
88 const ParticleFlowObject *
const pDaughterPfo = *iter1;
91 const ParticleFlowObject *pBestParentPfo = NULL;
92 float bestDisplacement(std::numeric_limits<float>::max());
94 for (PfoVector::const_iterator iter2 = allPfos.begin(), iterEnd2 = allPfos.end(); iter2 != iterEnd2; ++iter2)
96 const ParticleFlowObject *
const pThisParentPfo = *iter2;
97 float thisDisplacement(std::numeric_limits<float>::max());
99 if (pDaughterPfo == pThisParentPfo)
102 if (!this->
IsAssociated(pDaughterPfo, pThisParentPfo, thisDisplacement))
105 if (thisDisplacement < bestDisplacement)
107 bestDisplacement = thisDisplacement;
108 pBestParentPfo = pThisParentPfo;
116 if (pBestParentPfo->GetParentPfoList().empty())
119 if (daughterPfoList.count(pBestParentPfo))
120 throw StatusCodeException(STATUS_CODE_FAILURE);
122 pfoAssociationMap.insert(PfoAssociationMap::value_type(pDaughterPfo, pBestParentPfo));
129 if (parentPfoList.count(pBestParentPfo))
130 throw StatusCodeException(STATUS_CODE_FAILURE);
133 if (pBestParentPfo->GetParentPfoList().size() != 1)
134 throw StatusCodeException(STATUS_CODE_FAILURE);
137 PfoList::const_iterator pIter = pBestParentPfo->GetParentPfoList().begin();
138 const ParticleFlowObject *
const pReplacementParentPfo = *pIter;
139 if (pReplacementParentPfo->GetParentPfoList().size() != 0)
140 throw StatusCodeException(STATUS_CODE_FAILURE);
142 pfoAssociationMap.insert(PfoAssociationMap::value_type(pDaughterPfo, pReplacementParentPfo));
150 const ParticleFlowObject *
const pDaughterPfo,
const ParticleFlowObject *
const pParentPfo,
float &displacement)
const
152 displacement = std::numeric_limits<float>::max();
154 if (pDaughterPfo == pParentPfo)
160 if (daughterLengthSquared >
m_maxDaughterLengthSquared || parentLengthSquared < m_minParentLengthSquared || daughterLengthSquared > 0.5 * parentLengthSquared)
163 const float transitionLengthSquared(125.f);
164 const float displacementCut((daughterLengthSquared > transitionLengthSquared)
172 catch (StatusCodeException &statusCodeException)
174 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
175 throw statusCodeException;
178 if (displacement > displacementCut)
188 CartesianPointVector vertexVectorU, vertexVectorV, vertexVectorW;
193 ClusterList clusterListU, clusterListV, clusterListW;
199 float sumDisplacementSquared(0.f);
201 if (!vertexVectorU.empty())
204 sumDisplacementSquared += thisDisplacement * thisDisplacement;
208 if (!vertexVectorV.empty())
211 sumDisplacementSquared += thisDisplacement * thisDisplacement;
215 if (!vertexVectorW.empty())
218 sumDisplacementSquared += thisDisplacement * thisDisplacement;
222 if (sumViews < std::numeric_limits<float>::epsilon())
223 throw StatusCodeException(STATUS_CODE_FAILURE);
225 return std::sqrt(sumDisplacementSquared / sumViews);
232 ClusterList clusterList;
235 for (ClusterList::const_iterator iter = clusterList.begin(), iterEnd = clusterList.end(); iter != iterEnd; ++iter)
237 const Cluster *
const pCluster = *iter;
239 CartesianVector firstCoordinate(0.f, 0.f, 0.f), secondCoordinate(0.f, 0.f, 0.f);
242 vertexVector.push_back(firstCoordinate);
243 vertexVector.push_back(secondCoordinate);
251 if (vertexVector.empty() || clusterList.empty())
252 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
254 float bestDisplacement(std::numeric_limits<float>::max());
256 for (CartesianPointVector::const_iterator iter1 = vertexVector.begin(), iterEnd1 = vertexVector.end(); iter1 != iterEnd1; ++iter1)
258 const CartesianVector &thisVertex = *iter1;
260 for (ClusterList::const_iterator iter2 = clusterList.begin(), iterEnd2 = clusterList.end(); iter2 != iterEnd2; ++iter2)
262 const Cluster *
const pCluster = *iter2;
265 if (thisDisplacement < bestDisplacement)
266 bestDisplacement = thisDisplacement;
270 return bestDisplacement;
278 for (
const auto &mapEntry : pfoAssociationMap)
279 pfoList.push_back(mapEntry.first);
282 for (
const ParticleFlowObject *
const pDaughterPfo : pfoList)
284 const ParticleFlowObject *
const pParentPfo(this->
GetParent(pfoAssociationMap, pDaughterPfo));
287 throw StatusCodeException(STATUS_CODE_FAILURE);
292 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pParentPfo, pDaughterPfo));
294 PandoraContentApi::ParticleFlowObject::Metadata metadata;
295 metadata.m_particleId = E_MINUS;
296 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*
this, pDaughterPfo, metadata));
298 daughterPfoList.push_back(pDaughterPfo);
306 const ParticleFlowObject *pParentPfo =
nullptr;
307 const ParticleFlowObject *pDaughterPfo = pPfo;
311 PfoAssociationMap::const_iterator iter = pfoAssociationMap.find(pDaughterPfo);
312 if (pfoAssociationMap.end() == iter)
315 pParentPfo = iter->second;
316 pDaughterPfo = pParentPfo;
326 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"ParentPfoListName",
m_parentPfoListName));
327 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"DaughterPfoListName",
m_daughterPfoListName));
329 PANDORA_RETURN_RESULT_IF_AND_IF(
330 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"DistanceForMatching",
m_distanceForMatching));
333 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinParentLength", minParentLength));
337 PANDORA_RETURN_RESULT_IF_AND_IF(
338 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxDaughterLength", maxDaughterLength));
341 return STATUS_CODE_SUCCESS;
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.
pandora::StatusCode Run()
float m_distanceForMatching
Maximum allowed distance of delta ray from parent cosmic ray.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
void GetPfos(const std::string &inputPfoListName, pandora::PfoVector &outputPfoVector) const
Get the vector of Pfos, given the input list name.
const pandora::ParticleFlowObject * GetParent(const PfoAssociationMap &pfoAssociationMap, const pandora::ParticleFlowObject *const pPfo) const
For a given daughter, follow the parent/daughter links to find the overall parent.
float GetTwoDSeparation(const pandora::ParticleFlowObject *const pDaughterPfo, const pandora::ParticleFlowObject *const pParentPfo) const
Calculate 2D separation between two Pfos.
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
std::string m_parentPfoListName
The parent pfo list name.
static float GetTwoDLengthSquared(const pandora::ParticleFlowObject *const pPfo)
Calculate length of Pfo using 2D clusters.
float m_maxDaughterLengthSquared
Maximum allowed length of daughter delta ray.
std::string m_daughterPfoListName
The daughter pfo list name.
Header file for the cluster helper class.
void GetTwoDVertices(const pandora::ParticleFlowObject *const pPfo, const pandora::HitType &hitType, pandora::CartesianPointVector &vertexVector) const
Calculate 2D separation between two Pfos.
bool IsAssociated(const pandora::ParticleFlowObject *const pDaughterPfo, const pandora::ParticleFlowObject *const pParentPfo, float &displacement) const
Determine if a given pair of Pfos have a parent/daughter association.
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) ...
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
void BuildParentDaughterLinks(const PfoAssociationMap &pfoAssociationMap, pandora::PfoList &outputPfoList) const
Build the parent/daughter links from the map of parent/daughter associations.
void BuildAssociationMap(const pandora::PfoVector &inputPfos, const pandora::PfoVector &outputPfos, PfoAssociationMap &pfoAssociationMap) const
Build parent/daughter associations between PFOs.
float m_minParentLengthSquared
Minimum allowed length of parent cosmic ray.
float GetClosestDistance(const pandora::CartesianPointVector &vertexVector, const pandora::ClusterList &clusterList) const
Calculate closest 2D separation between a set of vertices and a set of clusters.
Header file for the delta ray identification algorithm class.
BEGIN_PROLOG could also be cout
std::unordered_map< const pandora::ParticleFlowObject *, const pandora::ParticleFlowObject * > PfoAssociationMap
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.