23 m_detector{
"dune_fd_hd"},
25 m_foldToPrimaries{false},
27 m_foldToLeadingShowers{false},
28 m_validateEvent{false},
31 m_minCompleteness{0.65f}
54 const PfoList *pPfoList(
nullptr);
71 matchInfo.
Print(mcHierarchy);
75 this->EventValidation(matchInfo);
77 this->MCValidation(matchInfo);
80 return STATUS_CODE_SUCCESS;
94 const LArHierarchyHelper::RecoHierarchy &recoHierarchy{matchInfo.
GetRecoHierarchy()};
97 std::map<const LArHierarchyHelper::RecoHierarchy::Node *, const ParticleFlowObject *> recoNodeToRootMap;
101 recoHierarchy.GetFlattenedNodes(pRoot, nodes);
102 for (
const LArHierarchyHelper::RecoHierarchy::Node *pNode : nodes)
103 recoNodeToRootMap[pNode] = pRoot;
106 std::set<const pandora::ParticleFlowObject *> matchedRecoSliceRoots;
107 for (
const MCParticle *
const pRoot : rootMCParticles)
112 for (
const LArHierarchyHelper::MCMatches &match : matches)
114 const LArHierarchyHelper::MCHierarchy::Node *pMCNode{match.GetMC()};
115 if (pMCNode->GetHierarchyTier() == 1)
117 const MCParticle *
const pLeadingMC{pMCNode->GetLeadingMCParticle()};
118 primaries.emplace_back(pLeadingMC);
124 const int isCC{descriptor.
IsCC()};
125 const int isQE{descriptor.IsQE()};
126 const int isResonant{descriptor.IsResonant()};
127 const int isDIS{descriptor.IsDIS()};
128 const int isCoherent{descriptor.IsCoherent()};
129 const int isNuMu{descriptor.IsMuonNeutrino()};
130 const int isNuE{descriptor.IsElectronNeutrino()};
131 const int nPiZero{
static_cast<int>(descriptor.GetNumPiZero())};
132 const int nPiPlus{
static_cast<int>(descriptor.GetNumPiPlus())};
133 const int nPiMinus{
static_cast<int>(descriptor.GetNumPiMinus())};
134 const int nPhotons{
static_cast<int>(descriptor.GetNumPhotons())};
135 const int nProtons{
static_cast<int>(descriptor.GetNumProtons())};
137 std::set<const LArHierarchyHelper::MCHierarchy::Node *> trackNodeSet, showerNodeSet;
138 int nGoodTrackMatches{0}, nGoodShowerMatches{0};
139 int nGoodMatches{0}, nPoorMatches{0}, nUnmatched{0};
140 int nGoodTier1Matches{0}, nTier1Nodes{0};
141 int nGoodTier1TrackMatches{0}, nTier1TrackNodes{0};
142 int nGoodTier1ShowerMatches{0}, nTier1ShowerNodes{0};
143 int hasLeadingMuon{0}, hasLeadingElectron{0}, isLeadingLeptonCorrect{0};
144 for (
const LArHierarchyHelper::MCMatches &mcMatch : matches)
146 const LArHierarchyHelper::MCHierarchy::Node *pNode{mcMatch.GetMC()};
148 for (
const LArHierarchyHelper::RecoHierarchy::Node *pReco : mcMatch.GetRecoMatches())
149 matchedRecoSliceRoots.insert(recoNodeToRootMap[pReco]);
151 const int nReco{
static_cast<int>(mcMatch.GetRecoMatches().size())};
152 const bool isQuality{mcMatch.IsQuality(matchInfo.
GetQualityCuts())};
153 if (nReco == 1 && isQuality)
159 if (pNode->GetHierarchyTier() == 1)
162 if (nReco == 1 && isQuality)
166 const int pdg{std::abs(pNode->GetParticleId())};
167 if (pNode->IsLeadingLepton())
171 else if (pdg == E_MINUS)
172 hasLeadingElectron = 1;
173 isLeadingLeptonCorrect = nReco == 1 ? 1 : 0;
176 if (pdg == PHOTON || pdg == E_MINUS)
178 showerNodeSet.insert(pNode);
179 if (nReco == 1 && isQuality)
181 ++nGoodShowerMatches;
182 if (pNode->GetHierarchyTier() == 1)
183 ++nGoodTier1ShowerMatches;
185 if (pNode->GetHierarchyTier() == 1)
190 trackNodeSet.insert(pNode);
191 if (nReco == 1 && isQuality)
194 if (pNode->GetHierarchyTier() == 1)
195 ++nGoodTier1TrackMatches;
197 if (pNode->GetHierarchyTier() == 1)
202 const int nNodes{
static_cast<int>(matchInfo.
GetNMCNodes(pRoot))};
203 const int nTrackNodes{
static_cast<int>(trackNodeSet.size())}, nShowerNodes{
static_cast<int>(showerNodeSet.size())};
204 const int nRecoSlices{
static_cast<int>(matchedRecoSliceRoots.size())};
206 float vtxDx{std::numeric_limits<float>::max()};
207 float vtxDy{std::numeric_limits<float>::max()};
208 float vtxDz{std::numeric_limits<float>::max()};
209 float vtxDr{std::numeric_limits<float>::max()};
215 const float dx{recoVertex.
GetX() - trueVertex.GetX()};
216 const float dy{recoVertex.GetY() - trueVertex.GetY()};
217 const float dz{recoVertex.GetZ() - trueVertex.GetZ()};
218 const float dr{std::sqrt(dx * dx + dy * dy + dz * dz)};
273void HierarchyValidationAlgorithm::MCValidation(
const LArHierarchyHelper::MatchInfo &matchInfo)
const
279 matchInfo.GetRootMCParticles(rootMCParticles);
281 const LArHierarchyHelper::RecoHierarchy &recoHierarchy{matchInfo.GetRecoHierarchy()};
282 recoHierarchy.GetRootPfos(rootPfos);
283 std::map<const LArHierarchyHelper::RecoHierarchy::Node *, const ParticleFlowObject *> recoNodeToRootMap;
287 recoHierarchy.GetFlattenedNodes(pRoot, nodes);
288 for (
const LArHierarchyHelper::RecoHierarchy::Node *pNode : nodes)
289 recoNodeToRootMap[pNode] = pRoot;
292 for (
const MCParticle *
const pRoot : rootMCParticles)
295 for (
const LArHierarchyHelper::MCMatches &matches : matchInfo.GetMatches(pRoot))
297 const LArHierarchyHelper::MCHierarchy::Node *pMCNode{matches.GetMC()};
298 if (pMCNode->GetHierarchyTier() == 1)
300 const MCParticle *
const pLeadingMC{pMCNode->GetLeadingMCParticle()};
301 primaries.emplace_back(pLeadingMC);
307 for (
const LArHierarchyHelper::MCMatches &matches : matchInfo.GetMatches(pRoot))
309 const LArHierarchyHelper::MCHierarchy::Node *pMCNode{matches.GetMC()};
310 const int isTestBeam{pMCNode->IsTestBeamParticle() ? 1 : 0};
311 const int isCosmicRay{!isTestBeam && pMCNode->IsCosmicRay() ? 1 : 0};
312 const int isNeutrinoInt{!(isTestBeam || isCosmicRay) ? 1 : 0};
313 const int mcId{pMCNode->GetId()};
314 const int pdg{pMCNode->GetParticleId()};
315 const int tier{pMCNode->GetHierarchyTier()};
316 const int mcHits{
static_cast<int>(pMCNode->GetCaloHits().size())};
317 const int isLeadingLepton{pMCNode->IsLeadingLepton() ? 1 : 0};
319 const MCParticle *
const pLeadingMC{pMCNode->GetLeadingMCParticle()};
321 const int isElectron{std::abs(pLeadingMC->GetParticleId()) == E_MINUS ? 1 : 0};
322 const int hasMuonParent{parentList.size() == 1 && std::abs(parentList.front()->GetParticleId()) == MU_MINUS ? 1 : 0};
324 const float mcMomentum{pLeadingMC->GetMomentum().GetMagnitude()};
327 const int nMatches{
static_cast<int>(nodeVector.size())};
328 IntVector recoSliceIdVector, recoIdVector, nRecoHitsVector, nSharedHitsVector;
330 FloatVector purityAdcVector, completenessAdcVector;
331 FloatVector purityVectorU, purityVectorV, purityVectorW, completenessVectorU, completenessVectorV, completenessVectorW;
332 FloatVector purityAdcVectorU, purityAdcVectorV, purityAdcVectorW, completenessAdcVectorU, completenessAdcVectorV, completenessAdcVectorW;
334 float vtxDx{0.f}, vtxDy{0.f}, vtxDz{0.f}, vtxDr{0.f};
336 const int isCC{descriptor.IsCC()};
337 const int isQE{descriptor.IsQE()};
338 const int isResonant{descriptor.IsResonant()};
339 const int isDIS{descriptor.IsDIS()};
340 const int isCoherent{descriptor.IsCoherent()};
341 const int isNuMu{descriptor.IsMuonNeutrino()};
342 const int isNuE{descriptor.IsElectronNeutrino()};
343 const int nPiZero{
static_cast<int>(descriptor.GetNumPiZero())};
344 const int nPiPlus{
static_cast<int>(descriptor.GetNumPiPlus())};
345 const int nPiMinus{
static_cast<int>(descriptor.GetNumPiMinus())};
346 const int nPhotons{
static_cast<int>(descriptor.GetNumPhotons())};
347 const int nProtons{
static_cast<int>(descriptor.GetNumProtons())};
349 for (
const LArHierarchyHelper::RecoHierarchy::Node *pRecoNode : nodeVector)
351 const int sliceId{
static_cast<int>(
352 std::distance(rootPfos.begin(), std::find(rootPfos.begin(), rootPfos.end(), recoNodeToRootMap[pRecoNode])))};
353 recoSliceIdVector.emplace_back(sliceId);
354 recoIdVector.emplace_back(pRecoNode->GetParticleId());
355 nRecoHitsVector.emplace_back(
static_cast<int>(pRecoNode->GetCaloHits().size()));
356 nSharedHitsVector.emplace_back(
static_cast<int>(matches.GetSharedHits(pRecoNode)));
357 purityVector.emplace_back(matches.GetPurity(pRecoNode));
358 completenessVector.emplace_back(matches.GetCompleteness(pRecoNode));
359 purityAdcVector.emplace_back(matches.GetPurity(pRecoNode,
true));
360 completenessAdcVector.emplace_back(matches.GetCompleteness(pRecoNode,
true));
361 purityVectorU.emplace_back(matches.GetPurity(pRecoNode,
TPC_VIEW_U));
362 purityVectorV.emplace_back(matches.GetPurity(pRecoNode,
TPC_VIEW_V));
363 purityVectorW.emplace_back(matches.GetPurity(pRecoNode,
TPC_VIEW_W));
364 completenessVectorU.emplace_back(matches.GetCompleteness(pRecoNode,
TPC_VIEW_U));
365 completenessVectorV.emplace_back(matches.GetCompleteness(pRecoNode,
TPC_VIEW_V));
366 completenessVectorW.emplace_back(matches.GetCompleteness(pRecoNode,
TPC_VIEW_W));
367 purityAdcVectorU.emplace_back(matches.GetPurity(pRecoNode,
TPC_VIEW_U,
true));
368 purityAdcVectorV.emplace_back(matches.GetPurity(pRecoNode,
TPC_VIEW_V,
true));
369 purityAdcVectorW.emplace_back(matches.GetPurity(pRecoNode,
TPC_VIEW_W,
true));
370 completenessAdcVectorU.emplace_back(matches.GetCompleteness(pRecoNode,
TPC_VIEW_U,
true));
371 completenessAdcVectorV.emplace_back(matches.GetCompleteness(pRecoNode,
TPC_VIEW_V,
true));
372 completenessAdcVectorW.emplace_back(matches.GetCompleteness(pRecoNode,
TPC_VIEW_W,
true));
376 vtxDx = recoVertex.
GetX() - trueVertex.GetX();
377 vtxDy = recoVertex.GetY() - trueVertex.GetY();
378 vtxDz = recoVertex.GetZ() - trueVertex.GetZ();
379 vtxDr = std::sqrt(vtxDx * vtxDx + vtxDy * vtxDy + vtxDz * vtxDz);
463 std::cout <<
"Error: WriteTree requested but no tree names found" << std::endl;
464 return STATUS_CODE_NOT_FOUND;
468 std::cout <<
"Error: Both event-level and MC-level validation requested simulataneously" << std::endl;
469 return STATUS_CODE_INVALID_PARAMETER;
481 return STATUS_CODE_SUCCESS;
Header file for the hierarchy validation algorithm.
Header file for the interaction type helper class.
Header file for the vertex helper class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
std::vector< float > FloatVector
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
pandora::StatusCode Run()
Run the algorithm.
std::string m_pfoListName
Name of input PFO list.
std::string m_detector
Name of the detector.
float m_minPurity
Minimum purity to tag a node as being of good quality.
std::string m_treename
The name of the ROOT tree to write.
bool m_validateEvent
Whether to validate at the level of an event.
HierarchyValidationAlgorithm()
Default constructor.
std::string m_filename
The name of the ROOT file to write.
bool m_validateMC
Whether to validate at the level of MC nodes.
float m_minCompleteness
Minimum completeness to tag a node as being of good quality.
bool m_foldToLeadingShowers
Whether or not to fold the hierarchy back to leading shower particles.
bool m_foldToPrimaries
Whether or not to fold the hierarchy back to primary particles.
virtual ~HierarchyValidationAlgorithm()
bool m_writeTree
Whether or not to output validation information to a ROOT file.
std::string m_caloHitListName
Name of input calo hit list.
int m_event
The current event.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
bool m_foldDynamic
Whether or not to fold the hierarchy dynamically.
bool IsCC() const
Whether or not the interaction is CC.
bool m_foldToTier
Whether or not to apply folding based on particle tier.
bool m_foldDynamic
Whether or not to use process and topological information to make folding decisions.
bool m_foldToLeadingShowers
Whether or not to fold shower children to the leading shower particle.
void Print(const MCHierarchy &mcHierarchy) const
Prints information about which reco nodes are matched to the MC nodes, information about hit sharing,...
void GetRootMCParticles(pandora::MCParticleList &rootMCParticles) const
Retrieve the root MC particles of the interaction hierarchies.
unsigned int GetNMCNodes(const pandora::MCParticle *const pRoot) const
Retrieve the number of MC nodes available to match.
const MCMatchesVector & GetMatches(const pandora::MCParticle *const pRoot) const
Retrieve the vector of matches (this will include null matches - i.e. MC nodes with no corresponding ...
const RecoHierarchy & GetRecoHierarchy() const
Retrieve the reco hierarchy used for the matching.
const QualityCuts & GetQualityCuts() const
Retrieve the quality cuts for matching.
std::vector< const Node * > NodeVector
void GetRootPfos(pandora::PfoList &rootPfos) const
Retrieve the root particle flow objects of the interaction hierarchies.
static void MatchHierarchies(MatchInfo &matchInfo)
Finds the matches between reconstructed and MC hierarchies.
static void FillRecoHierarchy(const pandora::PfoList &pfoList, const FoldingParameters &foldParameters, RecoHierarchy &hierarchy)
Fill a reconstructed hierarchy based on the specified folding criteria (see RecoHierarchy::FillHierar...
std::vector< MCMatches > MCMatchesVector
static void FillMCHierarchy(const pandora::MCParticleList &mcParticleList, const pandora::CaloHitList &caloHitList, const FoldingParameters &foldParameters, MCHierarchy &hierarchy)
Fill an MC hierarchy based on the specified folding criteria (see MCHierarchy::FillHierarchy for deta...
static InteractionDescriptor GetInteractionDescriptor(const pandora::MCParticleList &mcPrimaryList)
Get the interaction descriptor of an event.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
static bool IsDecay(const pandora::MCParticle *const pMCParticle)
Check whether or not an MC particle comes from a decay process.
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
static bool IsInFiducialVolume(const pandora::Pandora &pandora, const pandora::CartesianVector &vertex, const std::string &detector)
Determine if a vertex is within a detector's fiducial volume. This throws a STATUS_CODE_INVALID_PARAM...
float GetX() const
Get the cartesian x coordinate.
const MCParticleList & GetParentList() const
Get list of parents of mc particle.
ParticleFlowObject class.
const Pandora & GetPandora() const
Get the associated pandora instance.
const CartesianVector & GetPosition() const
Get the vertex position.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
MANAGED_CONTAINER< const MCParticle * > MCParticleList
std::vector< int > IntVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList