9 #include "Pandora/AlgorithmHeaders.h"
22 NeutrinoHierarchyAlgorithm::NeutrinoHierarchyAlgorithm() : m_halfWindowLayers(20), m_displayPfoInfoMap(
false)
31 for (
const auto &mapEntry : pfoInfoMap)
32 sortedPfos.push_back(mapEntry.first);
35 for (
const Pfo *
const pPfo : sortedPfos)
37 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
39 if (pPfoInfo->IsNeutrinoVertexAssociated() || pPfoInfo->GetParentPfo())
41 assignedPfos.push_back(pPfoInfo->GetThisPfo());
45 unassignedPfos.push_back(pPfoInfo->GetThisPfo());
54 const ParticleFlowObject *pNeutrinoPfo(
nullptr);
55 PfoList candidateDaughterPfoList;
62 catch (StatusCodeException &statusCodeException)
64 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
65 std::cout <<
"NeutrinoHierarchyAlgorithm: required input pfos unavailable." << std::endl;
67 if (STATUS_CODE_NOT_FOUND != statusCodeException.GetStatusCode())
68 throw statusCodeException;
70 return STATUS_CODE_SUCCESS;
77 if (!pNeutrinoPfo->GetVertexList().empty())
83 pPfoRelationTool->Run(
this, pNeutrinoVertex, pfoInfoMap);
88 catch (StatusCodeException &statusCodeException)
90 std::cout <<
"NeutrinoHierarchyAlgorithm: unable to process input neutrino pfo, " << statusCodeException.ToString() << std::endl;
96 for (
auto &mapIter : pfoInfoMap)
97 delete mapIter.second;
99 return STATUS_CODE_SUCCESS;
106 const PfoList *pPfoList =
nullptr;
107 PANDORA_THROW_RESULT_IF_AND_IF(
108 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this,
m_neutrinoPfoListName, pPfoList));
110 if (!pPfoList || pPfoList->empty())
112 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
115 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
119 pNeutrinoPfo = ((1 == pPfoList->size()) ? *(pPfoList->begin()) :
nullptr);
122 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
131 const PfoList *pCandidatePfoList(
nullptr);
133 if (STATUS_CODE_SUCCESS == PandoraContentApi::GetList(*
this, daughterPfoListName, pCandidatePfoList))
135 candidateDaughterPfoList.insert(candidateDaughterPfoList.end(), pCandidatePfoList->begin(), pCandidatePfoList->end());
137 else if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
139 std::cout <<
"NeutrinoHierarchyAlgorithm: unable to find pfo list " << daughterPfoListName << std::endl;
143 if (candidateDaughterPfoList.empty())
144 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
153 for (
const ParticleFlowObject *
const pPfo : pfoList)
160 (
void)pfoInfoMap.insert(PfoInfoMap::value_type(pPfo, pPfoInfo));
162 catch (StatusCodeException &)
164 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
165 std::cout <<
"NeutrinoHierarchyAlgorithm: Unable to calculate pfo information " << std::endl;
175 PfoInfoMap &pfoInfoMap,
const unsigned int callDepth)
const
177 PfoVector candidateDaughterPfoVector(candidateDaughterPfoList.begin(), candidateDaughterPfoList.end());
181 for (
const ParticleFlowObject *
const pDaughterPfo : candidateDaughterPfoVector)
183 PfoInfoMap::const_iterator iter = pfoInfoMap.find(pDaughterPfo);
185 if ((pfoInfoMap.end() != iter) && (iter->second->IsNeutrinoVertexAssociated()))
186 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pNeutrinoPfo, pDaughterPfo));
190 if ((0 == callDepth) && (0 == pNeutrinoPfo->GetNDaughterPfos()))
193 return this->
ProcessPfoInfoMap(pNeutrinoPfo, candidateDaughterPfoList, pfoInfoMap, callDepth + 1);
197 PfoVector sortedPfos;
198 for (
const auto &mapEntry : pfoInfoMap)
199 sortedPfos.push_back(mapEntry.first);
202 for (
const Pfo *
const pPfo : sortedPfos)
204 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
206 PfoVector daughterPfos(pPfoInfo->GetDaughterPfoList().begin(), pPfoInfo->GetDaughterPfoList().end());
209 for (
const ParticleFlowObject *
const pDaughterPfo : daughterPfos)
210 PANDORA_THROW_RESULT_IF(
211 STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pPfoInfo->GetThisPfo(), pDaughterPfo));
215 for (
const ParticleFlowObject *
const pRemainingPfo : candidateDaughterPfoVector)
217 if (!pRemainingPfo->GetParentPfoList().empty())
221 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pNeutrinoPfo, pRemainingPfo));
228 const ParticleFlowObject *
const pNeutrinoPfo,
const PfoList &candidateDaughterPfoList,
PfoInfoMap &pfoInfoMap)
const
230 PfoVector candidateDaughterPfoVector(candidateDaughterPfoList.begin(), candidateDaughterPfoList.end());
234 if (candidateDaughterPfoVector.empty())
235 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
237 ClusterList daughterClusterList3D;
242 if (daughterClusterList3D.empty())
249 parameters.m_position = newVertexPosition;
250 parameters.m_vertexLabel = pOldNeutrinoVertex->GetVertexLabel();
251 parameters.m_vertexType = pOldNeutrinoVertex->GetVertexType();
252 parameters.m_x0 = pOldNeutrinoVertex->GetX0();
255 if (neutrinoVertexListName.empty())
256 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Vertex>(*
this, neutrinoVertexListName));
258 std::string temporaryVertexListName;
259 const VertexList *pTemporaryVertexList(
nullptr);
260 const Vertex *pNewNeutrinoVertex(
nullptr);
261 PANDORA_THROW_RESULT_IF(
262 STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*
this, pTemporaryVertexList, temporaryVertexListName));
263 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*
this, parameters, pNewNeutrinoVertex));
264 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*
this, neutrinoVertexListName));
266 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*
this, pNeutrinoPfo, pOldNeutrinoVertex));
267 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*
this, pNeutrinoPfo, pNewNeutrinoVertex));
268 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete<Vertex>(*
this, pOldNeutrinoVertex, neutrinoVertexListName));
270 for (
auto &mapIter : pfoInfoMap)
271 delete mapIter.second;
276 pPfoRelationTool->Run(
this, pNewNeutrinoVertex, pfoInfoMap);
284 PANDORA_MONITORING_API(SetEveDisplayParameters(this->GetPandora(),
false, DETECTOR_VIEW_XZ, -1.f, -1.f, 1.f));
285 std::cout <<
"-Neutrino Pfo, nDaughters " << pNeutrinoPfo->GetDaughterPfoList().size() <<
", nVertices "
286 << pNeutrinoPfo->GetVertexList().size() << std::endl;
288 PfoVector sortedPfos;
289 for (
const auto &mapEntry : pfoInfoMap)
290 sortedPfos.push_back(mapEntry.first);
293 for (
const Pfo *
const pPfo : sortedPfos)
295 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
297 std::cout <<
"Pfo " << pPfoInfo->GetThisPfo() <<
", vtxAssoc " << pPfoInfo->IsNeutrinoVertexAssociated() <<
", parent "
298 << pPfoInfo->GetParentPfo() <<
", nDaughters " << pPfoInfo->GetDaughterPfoList().size() <<
" (";
300 for (
const ParticleFlowObject *
const pDaughterPfo : pPfoInfo->GetDaughterPfoList())
304 if (pPfoInfo->IsNeutrinoVertexAssociated())
307 const PfoList tempPfoList(1, pPfoInfo->GetThisPfo());
308 PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &tempPfoList,
"VertexPfo", RED,
true,
false));
314 PANDORA_MONITORING_API(VisualizeVertices(this->GetPandora(), &(pNeutrinoPfo->GetVertexList()),
"NeutrinoVertex", ORANGE));
315 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
319 for (
const Pfo *
const pPfo : sortedPfos)
321 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
323 if (!pPfoInfo->GetDaughterPfoList().empty())
326 const PfoList tempPfoList(1, pPfoInfo->GetThisPfo());
327 PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &tempPfoList,
"ParentPfo", RED,
true,
false));
328 PANDORA_MONITORING_API(
329 VisualizeParticleFlowObjects(this->GetPandora(), &(pPfoInfo->GetDaughterPfoList()),
"DaughterPfos",
BLUE,
true,
false));
330 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
340 m_pCluster3D(nullptr),
341 m_pVertex3D(nullptr),
342 m_pSlidingFitResult3D(nullptr),
343 m_isNeutrinoVertexAssociated(
false),
344 m_isInnerLayerAssociated(
false),
345 m_pParentPfo(nullptr)
347 ClusterList clusterList3D;
350 if (1 != clusterList3D.size())
351 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
357 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
363 m_pThisPfo(rhs.m_pThisPfo),
364 m_pCluster3D(rhs.m_pCluster3D),
365 m_pVertex3D(rhs.m_pVertex3D),
366 m_pSlidingFitResult3D(nullptr),
367 m_isNeutrinoVertexAssociated(rhs.m_isNeutrinoVertexAssociated),
368 m_isInnerLayerAssociated(rhs.m_isInnerLayerAssociated),
369 m_pParentPfo(rhs.m_pParentPfo),
370 m_daughterPfoList(rhs.m_daughterPfoList)
373 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
386 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
396 delete m_pSlidingFitResult3D;
408 delete m_pSlidingFitResult3D;
415 m_isNeutrinoVertexAssociated = isNeutrinoVertexAssociated;
422 m_isInnerLayerAssociated = isInnerLayerAssociated;
430 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
432 m_pParentPfo = pParentPfo;
439 m_pParentPfo =
nullptr;
446 if (m_daughterPfoList.end() != std::find(m_daughterPfoList.begin(), m_daughterPfoList.end(), pDaughterPfo))
447 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
449 m_daughterPfoList.push_back(pDaughterPfo);
456 PfoList::iterator eraseIter = std::find(m_daughterPfoList.begin(), m_daughterPfoList.end(), pDaughterPfo);
458 if (m_daughterPfoList.end() == eraseIter)
459 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
461 m_daughterPfoList.erase(eraseIter);
469 AlgorithmToolVector algorithmToolVector;
470 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
"PfoRelationTools", algorithmToolVector));
472 for (AlgorithmToolVector::const_iterator iter = algorithmToolVector.begin(), iterEnd = algorithmToolVector.end(); iter != iterEnd; ++iter)
474 PfoRelationTool *
const pPfoRelationTool(dynamic_cast<PfoRelationTool *>(*iter));
476 if (!pPfoRelationTool)
477 return STATUS_CODE_INVALID_PARAMETER;
482 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"NeutrinoPfoListName",
m_neutrinoPfoListName));
484 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"DaughterPfoListNames",
m_daughterPfoListNames));
486 PANDORA_RETURN_RESULT_IF_AND_IF(
487 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NeutrinoVertexListName",
m_neutrinoVertexListName));
489 PANDORA_RETURN_RESULT_IF_AND_IF(
490 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitHalfWindow",
m_halfWindowLayers));
492 PANDORA_RETURN_RESULT_IF_AND_IF(
493 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"DisplayPfoInfoMap",
m_displayPfoInfoMap));
495 return STATUS_CODE_SUCCESS;
void SetInnerLayerAssociation(const bool isInnerLayerAssociated)
Set the inner layer association flag.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
unsigned int GetLayerFitHalfWindow() const
Get the layer fit half window.
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.
const pandora::Cluster * m_pCluster3D
The address of the three dimensional cluster.
PfoInfo & operator=(const PfoInfo &rhs)
Assignment operator.
void ProcessPfoInfoMap(const pandora::ParticleFlowObject *const pNeutrinoPfo, const pandora::PfoList &candidateDaughterPfoList, PfoInfoMap &pfoInfoMap, const unsigned int callDepth=0) const
Process the information in a pfo info map, creating pfo parent/daughter links.
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.
bool m_isNeutrinoVertexAssociated
Whether the pfo is associated with the neutrino vertex.
PfoRelationToolVector m_algorithmToolVector
The algorithm tool vector.
const pandora::ParticleFlowObject * m_pThisPfo
The address of the pfo.
bool m_displayPfoInfoMap
Whether to display the pfo info map (if monitoring is enabled)
void DisplayPfoInfoMap(const pandora::ParticleFlowObject *const pNeutrinoPfo, const PfoInfoMap &pfoInfoMap) const
Display the information in a pfo info map, visualising pfo parent/daughter links. ...
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
void SeparatePfos(const NeutrinoHierarchyAlgorithm::PfoInfoMap &pfoInfoMap, pandora::PfoVector &assignedPfos, pandora::PfoVector &unassignedPfos) const
Query the pfo info map and separate/extract pfos currently either acting as parents or associated wit...
unsigned int m_halfWindowLayers
The number of layers to use for half-window of sliding fit.
std::string m_neutrinoVertexListName
The neutrino vertex list name - if not specified will assume current list.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
bool m_isInnerLayerAssociated
If associated, whether association to parent (vtx or pfo) is at sliding fit inner layer...
void RemoveDaughterPfo(const pandora::ParticleFlowObject *const pDaughterPfo)
Remove a daughter pfo.
void AdjustVertexAndPfoInfo(const pandora::ParticleFlowObject *const pNeutrinoPfo, const pandora::PfoList &candidateDaughterPfoList, PfoInfoMap &pfoInfoMap) const
Adjust neutrino vertex to ensure agreement with at least one pfo (first in sorted input list) ...
Header file for the geometry helper class.
ThreeDSlidingFitResult * m_pSlidingFitResult3D
The three dimensional sliding fit result.
pandora::StatusCode Run()
pandora::PfoList m_daughterPfoList
The daughter pfo list.
Header file for the cluster helper class.
void SetParentPfo(const pandora::ParticleFlowObject *const pParentPfo)
Set the parent pfo.
std::unordered_map< const pandora::ParticleFlowObject *, PfoInfo * > PfoInfoMap
float GetLayerPitch() const
Get the layer pitch, units cm.
void RemoveParentPfo()
Remove the parent pfo.
void GetNeutrinoPfo(const pandora::ParticleFlowObject *&pNeutrinoPfo) const
Get the address of the input neutrino pfo - enforces only one pfo present in input list; can return N...
static bool IsNeutrino(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a neutrino or (antineutrino)
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
PfoInfo(const pandora::ParticleFlowObject *const pPfo, const unsigned int halfWindowLayers, const float layerPitch)
Constructor.
Header file for the neutrino hierarchy algorithm class.
std::string m_neutrinoPfoListName
The neutrino pfo list name.
const pandora::Vertex * m_pVertex3D
The address of the three dimensional vertex.
pandora::StringVector m_daughterPfoListNames
The list of daughter pfo list names.
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
void SetNeutrinoVertexAssociation(const bool isNeutrinoVertexAssociated)
Set the neutrino vertex association flag.
ThreeDSlidingFitResult class.
const TwoDSlidingFitResult & GetFirstFitResult() const
Get the first sliding fit result for this cluster.
void AddDaughterPfo(const pandora::ParticleFlowObject *const pDaughterPfo)
Add a daughter pfo.
const pandora::ParticleFlowObject * m_pParentPfo
The address of the parent pfo.
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
void GetCandidateDaughterPfoList(pandora::PfoList &candidateDaughterPfoList) const
Get the list of candidate daughter pfos.
NeutrinoHierarchyAlgorithm::PfoInfo PfoInfo
std::list< Vertex > VertexList
BEGIN_PROLOG could also be cout
void GetInitialPfoInfoMap(const pandora::PfoList &pfoList, PfoInfoMap &pfoInfoMap) const
Process a provided pfo list and populate an initial pfo info map.