9 #include "Pandora/AlgorithmHeaders.h" 22 NeutrinoHierarchyAlgorithm::NeutrinoHierarchyAlgorithm() :
23 m_halfWindowLayers(20),
24 m_displayPfoInfoMap(false)
33 for (
const auto &mapEntry : pfoInfoMap)
34 sortedPfos.push_back(mapEntry.first);
37 for (
const Pfo *
const pPfo : sortedPfos)
39 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
41 if (pPfoInfo->IsNeutrinoVertexAssociated() || pPfoInfo->GetParentPfo())
43 assignedPfos.push_back(pPfoInfo->GetThisPfo());
47 unassignedPfos.push_back(pPfoInfo->GetThisPfo());
56 const ParticleFlowObject *pNeutrinoPfo(
nullptr);
57 PfoList candidateDaughterPfoList;
64 catch (StatusCodeException &statusCodeException)
66 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
67 std::cout <<
"NeutrinoHierarchyAlgorithm: required input pfos unavailable." << std::endl;
69 if (STATUS_CODE_NOT_FOUND != statusCodeException.GetStatusCode())
70 throw statusCodeException;
72 return STATUS_CODE_SUCCESS;
79 if (!pNeutrinoPfo->GetVertexList().empty())
85 pPfoRelationTool->Run(
this, pNeutrinoVertex, pfoInfoMap);
90 catch (StatusCodeException &statusCodeException)
92 std::cout <<
"NeutrinoHierarchyAlgorithm: unable to process input neutrino pfo, " << statusCodeException.ToString() << std::endl;
98 for (
auto &mapIter : pfoInfoMap)
99 delete mapIter.second;
101 return STATUS_CODE_SUCCESS;
108 const PfoList *pPfoList =
nullptr;
109 PANDORA_THROW_RESULT_IF_AND_IF(
110 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*
this,
m_neutrinoPfoListName, pPfoList));
112 if (!pPfoList || pPfoList->empty())
114 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
115 std::cout <<
"NeutrinoHierarchyAlgorithm: unable to find pfo list " <<
m_neutrinoPfoListName << std::endl;
117 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
121 pNeutrinoPfo = ((1 == pPfoList->size()) ? *(pPfoList->begin()) :
nullptr);
124 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
133 const PfoList *pCandidatePfoList(
nullptr);
135 if (STATUS_CODE_SUCCESS == PandoraContentApi::GetList(*
this, daughterPfoListName, pCandidatePfoList))
137 candidateDaughterPfoList.insert(candidateDaughterPfoList.end(), pCandidatePfoList->begin(), pCandidatePfoList->end());
139 else if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
141 std::cout <<
"NeutrinoHierarchyAlgorithm: unable to find pfo list " << daughterPfoListName << std::endl;
145 if (candidateDaughterPfoList.empty())
146 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
156 const float pitchMax{std::max({pitchU, pitchV, pitchW})};
157 const float layerPitch(pitchMax);
159 for (
const ParticleFlowObject *
const pPfo : pfoList)
166 (void)pfoInfoMap.insert(PfoInfoMap::value_type(pPfo, pPfoInfo));
168 catch (StatusCodeException &)
170 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
171 std::cout <<
"NeutrinoHierarchyAlgorithm: Unable to calculate pfo information " << std::endl;
181 PfoInfoMap &pfoInfoMap,
const unsigned int callDepth)
const 183 PfoVector candidateDaughterPfoVector(candidateDaughterPfoList.begin(), candidateDaughterPfoList.end());
187 for (
const ParticleFlowObject *
const pDaughterPfo : candidateDaughterPfoVector)
191 if ((pfoInfoMap.end() != iter) && (iter->second->IsNeutrinoVertexAssociated()))
192 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pNeutrinoPfo, pDaughterPfo));
196 if ((0 == callDepth) && (0 == pNeutrinoPfo->GetNDaughterPfos()))
199 return this->
ProcessPfoInfoMap(pNeutrinoPfo, candidateDaughterPfoList, pfoInfoMap, callDepth + 1);
203 PfoVector sortedPfos;
204 for (
const auto &mapEntry : pfoInfoMap)
205 sortedPfos.push_back(mapEntry.first);
208 for (
const Pfo *
const pPfo : sortedPfos)
210 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
212 PfoVector daughterPfos(pPfoInfo->GetDaughterPfoList().begin(), pPfoInfo->GetDaughterPfoList().end());
215 for (
const ParticleFlowObject *
const pDaughterPfo : daughterPfos)
216 PANDORA_THROW_RESULT_IF(
217 STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pPfoInfo->GetThisPfo(), pDaughterPfo));
221 for (
const ParticleFlowObject *
const pRemainingPfo : candidateDaughterPfoVector)
223 if (!pRemainingPfo->GetParentPfoList().empty())
227 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*
this, pNeutrinoPfo, pRemainingPfo));
234 const ParticleFlowObject *
const pNeutrinoPfo,
const PfoList &candidateDaughterPfoList,
PfoInfoMap &pfoInfoMap)
const 236 PfoVector candidateDaughterPfoVector(candidateDaughterPfoList.begin(), candidateDaughterPfoList.end());
240 if (candidateDaughterPfoVector.empty())
241 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
243 ClusterList daughterClusterList3D;
248 if (daughterClusterList3D.empty())
254 PandoraContentApi::Vertex::Parameters parameters;
255 parameters.m_position = newVertexPosition;
256 parameters.m_vertexLabel = pOldNeutrinoVertex->GetVertexLabel();
257 parameters.m_vertexType = pOldNeutrinoVertex->GetVertexType();
258 parameters.m_x0 = pOldNeutrinoVertex->GetX0();
261 if (neutrinoVertexListName.empty())
262 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentListName<Vertex>(*
this, neutrinoVertexListName));
264 std::string temporaryVertexListName;
265 const VertexList *pTemporaryVertexList(
nullptr);
266 const Vertex *pNewNeutrinoVertex(
nullptr);
267 PANDORA_THROW_RESULT_IF(
268 STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*
this, pTemporaryVertexList, temporaryVertexListName));
269 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*
this, parameters, pNewNeutrinoVertex));
270 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*
this, neutrinoVertexListName));
272 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromPfo(*
this, pNeutrinoPfo, pOldNeutrinoVertex));
273 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToPfo(*
this, pNeutrinoPfo, pNewNeutrinoVertex));
274 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Delete<Vertex>(*
this, pOldNeutrinoVertex, neutrinoVertexListName));
276 for (
auto &mapIter : pfoInfoMap)
277 delete mapIter.second;
282 pPfoRelationTool->Run(
this, pNewNeutrinoVertex, pfoInfoMap);
290 PANDORA_MONITORING_API(SetEveDisplayParameters(this->GetPandora(),
false, DETECTOR_VIEW_XZ, -1.
f, -1.
f, 1.
f));
291 std::cout <<
"-Neutrino Pfo, nDaughters " << pNeutrinoPfo->GetDaughterPfoList().size() <<
", nVertices " 292 << pNeutrinoPfo->GetVertexList().size() << std::endl;
294 PfoVector sortedPfos;
295 for (
const auto &mapEntry : pfoInfoMap)
296 sortedPfos.push_back(mapEntry.first);
299 for (
const Pfo *
const pPfo : sortedPfos)
301 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
303 std::cout <<
"Pfo " << pPfoInfo->
GetThisPfo() <<
", vtxAssoc " << pPfoInfo->IsNeutrinoVertexAssociated() <<
", parent " 304 << pPfoInfo->GetParentPfo() <<
", nDaughters " << pPfoInfo->GetDaughterPfoList().size() <<
" (";
306 for (
const ParticleFlowObject *
const pDaughterPfo : pPfoInfo->GetDaughterPfoList())
307 std::cout << pDaughterPfo <<
" ";
308 std::cout <<
") " << std::endl;
310 if (pPfoInfo->IsNeutrinoVertexAssociated())
313 const PfoList tempPfoList(1, pPfoInfo->GetThisPfo());
314 PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &tempPfoList,
"VertexPfo", RED,
true,
false));
320 PANDORA_MONITORING_API(VisualizeVertices(this->GetPandora(), &(pNeutrinoPfo->GetVertexList()),
"NeutrinoVertex", ORANGE));
321 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
325 for (
const Pfo *
const pPfo : sortedPfos)
327 const PfoInfo *
const pPfoInfo(pfoInfoMap.at(pPfo));
329 if (!pPfoInfo->GetDaughterPfoList().empty())
332 const PfoList tempPfoList(1, pPfoInfo->GetThisPfo());
333 PANDORA_MONITORING_API(VisualizeParticleFlowObjects(this->GetPandora(), &tempPfoList,
"ParentPfo", RED,
true,
false));
334 PANDORA_MONITORING_API(
335 VisualizeParticleFlowObjects(this->GetPandora(), &(pPfoInfo->GetDaughterPfoList()),
"DaughterPfos", BLUE,
true,
false));
336 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
346 m_pCluster3D(nullptr),
347 m_pVertex3D(nullptr),
348 m_pSlidingFitResult3D(nullptr),
349 m_isNeutrinoVertexAssociated(false),
350 m_isInnerLayerAssociated(false),
351 m_pParentPfo(nullptr)
353 ClusterList clusterList3D;
356 if (1 != clusterList3D.size())
357 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
363 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
379 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
392 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
436 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
453 throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
465 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
475 AlgorithmToolVector algorithmToolVector;
476 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle,
"PfoRelationTools", algorithmToolVector));
480 PfoRelationTool *
const pPfoRelationTool(dynamic_cast<PfoRelationTool *>(*iter));
482 if (!pPfoRelationTool)
483 return STATUS_CODE_INVALID_PARAMETER;
488 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"NeutrinoPfoListName",
m_neutrinoPfoListName));
490 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
"DaughterPfoListNames",
m_daughterPfoListNames));
492 PANDORA_RETURN_RESULT_IF_AND_IF(
493 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"NeutrinoVertexListName",
m_neutrinoVertexListName));
495 PANDORA_RETURN_RESULT_IF_AND_IF(
496 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SlidingFitHalfWindow",
m_halfWindowLayers));
498 PANDORA_RETURN_RESULT_IF_AND_IF(
499 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"DisplayPfoInfoMap",
m_displayPfoInfoMap));
501 return STATUS_CODE_SUCCESS;
void SetInnerLayerAssociation(const bool isInnerLayerAssociated)
Set the inner layer association flag.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
const pandora::ParticleFlowObject * GetThisPfo() const
Get the address of the pfo.
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.
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.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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.
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.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
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
void GetInitialPfoInfoMap(const pandora::PfoList &pfoList, PfoInfoMap &pfoInfoMap) const
Process a provided pfo list and populate an initial pfo info map.