LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
HierarchyValidationAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
15 
16 using namespace pandora;
17 
18 namespace lar_content
19 {
20 
21 HierarchyValidationAlgorithm::HierarchyValidationAlgorithm() :
22  m_event{-1},
23  m_detector{"dune_fd_hd"},
24  m_writeTree{false},
25  m_foldToPrimaries{false},
26  m_foldDynamic{false},
28  m_validateEvent{false},
29  m_validateMC{false},
30  m_minPurity{0.8f},
31  m_minCompleteness{0.65f}
32 {
33 }
34 
35 //------------------------------------------------------------------------------------------------------------------------------------------
36 
38 {
39  if (m_writeTree)
40  {
41  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_treename.c_str(), m_filename.c_str(), "UPDATE"));
42  }
43 }
44 
45 //------------------------------------------------------------------------------------------------------------------------------------------
46 
48 {
49  ++m_event;
50  const CaloHitList *pCaloHitList(nullptr);
51  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_caloHitListName, pCaloHitList));
52  const MCParticleList *pMCParticleList(nullptr);
53  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pMCParticleList));
54  const PfoList *pPfoList(nullptr);
55  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_pfoListName, pPfoList));
56 
59  foldParameters.m_foldToTier = true;
60  else if (m_foldDynamic)
61  foldParameters.m_foldDynamic = true;
62  else if (m_foldToLeadingShowers)
63  foldParameters.m_foldToLeadingShowers = true;
65  LArHierarchyHelper::FillMCHierarchy(*pMCParticleList, *pCaloHitList, foldParameters, mcHierarchy);
67  LArHierarchyHelper::FillRecoHierarchy(*pPfoList, foldParameters, recoHierarchy);
69  LArHierarchyHelper::MatchInfo matchInfo(mcHierarchy, recoHierarchy, quality);
71  matchInfo.Print(mcHierarchy);
72 
73 #ifdef MONITORING
74  if (m_validateEvent)
75  this->EventValidation(matchInfo);
76  else if (m_validateMC)
77  this->MCValidation(matchInfo);
78 #endif
79 
80  return STATUS_CODE_SUCCESS;
81 }
82 
83 //------------------------------------------------------------------------------------------------------------------------------------------
84 
85 #ifdef MONITORING
86 void HierarchyValidationAlgorithm::EventValidation(const LArHierarchyHelper::MatchInfo &matchInfo) const
87 {
88  if (m_writeTree)
89  {
90  int interaction{0};
91  MCParticleList rootMCParticles;
92  matchInfo.GetRootMCParticles(rootMCParticles);
93 
94  const LArHierarchyHelper::RecoHierarchy &recoHierarchy{matchInfo.GetRecoHierarchy()};
95  PfoList rootPfos;
96  recoHierarchy.GetRootPfos(rootPfos);
97  std::map<const LArHierarchyHelper::RecoHierarchy::Node *, const ParticleFlowObject *> recoNodeToRootMap;
98  for (const ParticleFlowObject *const pRoot : rootPfos)
99  {
101  recoHierarchy.GetFlattenedNodes(pRoot, nodes);
102  for (const LArHierarchyHelper::RecoHierarchy::Node *pNode : nodes)
103  recoNodeToRootMap[pNode] = pRoot;
104  }
105 
106  std::set<const pandora::ParticleFlowObject *> matchedRecoSliceRoots;
107  for (const MCParticle *const pRoot : rootMCParticles)
108  {
109  const LArHierarchyHelper::MCMatchesVector &matches{matchInfo.GetMatches(pRoot)};
110 
111  MCParticleList primaries;
112  for (const LArHierarchyHelper::MCMatches &match : matches)
113  {
114  const LArHierarchyHelper::MCHierarchy::Node *pMCNode{match.GetMC()};
115  if (pMCNode->GetHierarchyTier() == 1)
116  {
117  const MCParticle *const pLeadingMC{pMCNode->GetLeadingMCParticle()};
118  primaries.emplace_back(pLeadingMC);
119  }
120  }
121  primaries.sort(LArMCParticleHelper::SortByMomentum);
123 
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())};
136 
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)
145  {
146  const LArHierarchyHelper::MCHierarchy::Node *pNode{mcMatch.GetMC()};
147 
148  for (const LArHierarchyHelper::RecoHierarchy::Node *pReco : mcMatch.GetRecoMatches())
149  matchedRecoSliceRoots.insert(recoNodeToRootMap[pReco]);
150 
151  const int nReco{static_cast<int>(mcMatch.GetRecoMatches().size())};
152  const bool isQuality{mcMatch.IsQuality(matchInfo.GetQualityCuts())};
153  if (nReco == 1 && isQuality)
154  ++nGoodMatches;
155  else if (nReco >= 1)
156  ++nPoorMatches;
157  else
158  ++nUnmatched;
159  if (pNode->GetHierarchyTier() == 1)
160  {
161  ++nTier1Nodes;
162  if (nReco == 1 && isQuality)
163  ++nGoodTier1Matches;
164  }
165 
166  const int pdg{std::abs(pNode->GetParticleId())};
167  if (pNode->IsLeadingLepton())
168  {
169  if (pdg == MU_MINUS)
170  hasLeadingMuon = 1;
171  else if (pdg == E_MINUS)
172  hasLeadingElectron = 1;
173  isLeadingLeptonCorrect = nReco == 1 ? 1 : 0;
174  }
175 
176  if (pdg == PHOTON || pdg == E_MINUS)
177  {
178  showerNodeSet.insert(pNode);
179  if (nReco == 1 && isQuality)
180  {
181  ++nGoodShowerMatches;
182  if (pNode->GetHierarchyTier() == 1)
183  ++nGoodTier1ShowerMatches;
184  }
185  if (pNode->GetHierarchyTier() == 1)
186  ++nTier1ShowerNodes;
187  }
188  else
189  {
190  trackNodeSet.insert(pNode);
191  if (nReco == 1 && isQuality)
192  {
193  ++nGoodTrackMatches;
194  if (pNode->GetHierarchyTier() == 1)
195  ++nGoodTier1TrackMatches;
196  }
197  if (pNode->GetHierarchyTier() == 1)
198  ++nTier1TrackNodes;
199  }
200  }
201 
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())};
205  const CartesianVector &trueVertex{pRoot->GetVertex()};
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()};
210  const int isFiducial{LArVertexHelper::IsInFiducialVolume(this->GetPandora(), trueVertex, m_detector)};
211 
212  for (const ParticleFlowObject *pRootPfo : matchedRecoSliceRoots)
213  {
214  const CartesianVector &recoVertex{LArPfoHelper::GetVertex(pRootPfo)->GetPosition()};
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)};
219  if (dr < vtxDr)
220  {
221  vtxDx = dx;
222  vtxDy = dy;
223  vtxDz = dz;
224  vtxDr = dr;
225  }
226  }
227 
228  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "event", m_event));
229  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "interaction", interaction));
230  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nRecoSlices", nRecoSlices));
231  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isCC", isCC));
232  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isQE", isQE));
233  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isResonant", isResonant));
234  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isDIS", isDIS));
235  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isCoherent", isCoherent));
236  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isNuMu", isNuMu));
237  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isNuE", isNuE));
238  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPiZero", nPiZero));
239  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPiPlus", nPiPlus));
240  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPiMinus", nPiMinus));
241  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPhotons", nPhotons));
242  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nProtons", nProtons));
243  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isFiducial", isFiducial));
244  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDx", vtxDx));
245  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDy", vtxDy));
246  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDz", vtxDz));
247  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDr", vtxDr));
248  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nGoodMatches", nGoodMatches));
249  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPoorMatches", nPoorMatches));
250  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nUnmatched", nUnmatched));
251  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nNodes", nNodes));
252  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nGoodTier1Matches", nGoodTier1Matches));
253  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nTier1Nodes", nTier1Nodes));
254  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nGoodTrackMatches", nGoodTrackMatches));
255  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nGoodShowerMatches", nGoodShowerMatches));
256  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nTrackNodes", nTrackNodes));
257  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nShowerNodes", nShowerNodes));
258  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nGoodTier1TrackMatches", nGoodTier1TrackMatches));
259  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nTier1TrackNodes", nTier1TrackNodes));
260  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nGoodTier1ShowerMatches", nGoodTier1ShowerMatches));
261  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nTier1ShowerNodes", nTier1ShowerNodes));
262  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "hasLeadingMuon", hasLeadingMuon));
263  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "hasLeadingElectron", hasLeadingElectron));
264  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isLeadingLeptonCorrect", isLeadingLeptonCorrect));
265  PANDORA_MONITORING_API(FillTree(this->GetPandora(), m_treename.c_str()));
266  ++interaction;
267  }
268  }
269 }
270 
271 //------------------------------------------------------------------------------------------------------------------------------------------
272 
273 void HierarchyValidationAlgorithm::MCValidation(const LArHierarchyHelper::MatchInfo &matchInfo) const
274 {
275  if (m_writeTree)
276  {
277  int interaction{0};
278  MCParticleList rootMCParticles;
279  matchInfo.GetRootMCParticles(rootMCParticles);
280  PfoList rootPfos;
281  const LArHierarchyHelper::RecoHierarchy &recoHierarchy{matchInfo.GetRecoHierarchy()};
282  recoHierarchy.GetRootPfos(rootPfos);
283  std::map<const LArHierarchyHelper::RecoHierarchy::Node *, const ParticleFlowObject *> recoNodeToRootMap;
284  for (const ParticleFlowObject *const pRoot : rootPfos)
285  {
287  recoHierarchy.GetFlattenedNodes(pRoot, nodes);
288  for (const LArHierarchyHelper::RecoHierarchy::Node *pNode : nodes)
289  recoNodeToRootMap[pNode] = pRoot;
290  }
291 
292  for (const MCParticle *const pRoot : rootMCParticles)
293  {
294  MCParticleList primaries;
295  for (const LArHierarchyHelper::MCMatches &matches : matchInfo.GetMatches(pRoot))
296  {
297  const LArHierarchyHelper::MCHierarchy::Node *pMCNode{matches.GetMC()};
298  if (pMCNode->GetHierarchyTier() == 1)
299  {
300  const MCParticle *const pLeadingMC{pMCNode->GetLeadingMCParticle()};
301  primaries.emplace_back(pLeadingMC);
302  }
303  }
304  primaries.sort(LArMCParticleHelper::SortByMomentum);
306 
307  for (const LArHierarchyHelper::MCMatches &matches : matchInfo.GetMatches(pRoot))
308  {
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};
318 
319  const MCParticle *const pLeadingMC{pMCNode->GetLeadingMCParticle()};
320  const MCParticleList &parentList{pLeadingMC->GetParentList()};
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};
323  const int isMichel{isElectron && hasMuonParent && LArMCParticleHelper::IsDecay(pLeadingMC) ? 1 : 0};
324  const float mcMomentum{pLeadingMC->GetMomentum().GetMagnitude()};
325 
326  const LArHierarchyHelper::RecoHierarchy::NodeVector &nodeVector{matches.GetRecoMatches()};
327  const int nMatches{static_cast<int>(nodeVector.size())};
328  IntVector recoSliceIdVector, recoIdVector, nRecoHitsVector, nSharedHitsVector;
329  FloatVector purityVector, completenessVector;
330  FloatVector purityAdcVector, completenessAdcVector;
331  FloatVector purityVectorU, purityVectorV, purityVectorW, completenessVectorU, completenessVectorV, completenessVectorW;
332  FloatVector purityAdcVectorU, purityAdcVectorV, purityAdcVectorW, completenessAdcVectorU, completenessAdcVectorV, completenessAdcVectorW;
333  const CartesianVector &trueVertex{pLeadingMC->GetVertex()};
334  float vtxDx{0.f}, vtxDy{0.f}, vtxDz{0.f}, vtxDr{0.f};
335 
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())};
348 
349  for (const LArHierarchyHelper::RecoHierarchy::Node *pRecoNode : nodeVector)
350  {
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));
373  if (nMatches > 0)
374  {
375  const CartesianVector recoVertex{LArPfoHelper::GetVertex(pRecoNode->GetLeadingPfo())->GetPosition()};
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);
380  }
381  }
382 
383  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "event", m_event));
384  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "interaction", interaction));
385  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "mcId", mcId));
386  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "mcPDG", pdg));
387  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "mcTier", tier));
388  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "mcNHits", mcHits));
389  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "mcMomentum", mcMomentum));
390  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isNuInteration", isNeutrinoInt));
391  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isCosmicRay", isCosmicRay));
392  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isTestBeam", isTestBeam));
393  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isLeadingLepton", isLeadingLepton));
394  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isMichel", isMichel));
395  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nMatches", nMatches));
396  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "recoSliceIdVector", &recoSliceIdVector));
397  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "recoIdVector", &recoIdVector));
398  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nRecoHitsVector", &nRecoHitsVector));
399  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nSharedHitsVector", &nSharedHitsVector));
400  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityVector", &purityVector));
401  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessVector", &completenessVector));
402  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityAdcVector", &purityAdcVector));
403  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessAdcVector", &completenessAdcVector));
404  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityVectorU", &purityVectorU));
405  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityVectorV", &purityVectorV));
406  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityVectorW", &purityVectorW));
407  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessVectorU", &completenessVectorU));
408  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessVectorV", &completenessVectorV));
409  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessVectorW", &completenessVectorW));
410  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityAdcVectorU", &purityAdcVectorU));
411  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityAdcVectorV", &purityAdcVectorV));
412  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "purityAdcVectorW", &purityAdcVectorW));
413  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessAdcVectorU", &completenessAdcVectorU));
414  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessAdcVectorV", &completenessAdcVectorV));
415  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "completenessAdcVectorW", &completenessAdcVectorW));
416  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDx", vtxDx));
417  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDy", vtxDy));
418  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDz", vtxDz));
419  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "vtxDr", vtxDr));
420  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isCC", isCC));
421  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isQE", isQE));
422  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isResonant", isResonant));
423  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isDIS", isDIS));
424  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isCoherent", isCoherent));
425  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isNuMu", isNuMu));
426  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "isNuE", isNuE));
427  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPiZero", nPiZero));
428  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPiPlus", nPiPlus));
429  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPiMinus", nPiMinus));
430  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nPhotons", nPhotons));
431  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_treename.c_str(), "nProtons", nProtons));
432  PANDORA_MONITORING_API(FillTree(this->GetPandora(), m_treename.c_str()));
433  }
434  ++interaction;
435  }
436  }
437 }
438 #endif
439 
440 //------------------------------------------------------------------------------------------------------------------------------------------
441 
442 StatusCode HierarchyValidationAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
443 {
444  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListName", m_caloHitListName));
445  if (m_caloHitListName.empty())
446  m_caloHitListName = "CaloHitList2D";
447  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PfoListName", m_pfoListName));
448  if (m_pfoListName.empty())
449  m_pfoListName = "RecreatedPfos";
450 
451  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Detector", m_detector));
452 
453  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ValidateEvent", m_validateEvent));
454  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ValidateMC", m_validateMC));
455 
456  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "WriteTree", m_writeTree));
457  if (m_writeTree)
458  {
459  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "FileName", m_filename));
460  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "TreeName", m_treename));
461  if (!(m_validateEvent || m_validateMC))
462  {
463  std::cout << "Error: WriteTree requested but no tree names found" << std::endl;
464  return STATUS_CODE_NOT_FOUND;
465  }
466  else if (m_validateEvent && m_validateMC)
467  {
468  std::cout << "Error: Both event-level and MC-level validation requested simulataneously" << std::endl;
469  return STATUS_CODE_INVALID_PARAMETER;
470  }
471  }
472 
473  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FoldToPrimaries", m_foldToPrimaries));
474  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FoldDynamic", m_foldDynamic));
475  PANDORA_RETURN_RESULT_IF_AND_IF(
476  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FoldToLeadingShowers", m_foldToLeadingShowers));
477 
478  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinPurity", m_minPurity));
479  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCompleteness", m_minCompleteness));
480 
481  return STATUS_CODE_SUCCESS;
482 }
483 
484 } // namespace lar_content
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.
bool m_foldToTier
Whether or not to apply folding based on particle tier.
bool m_foldToPrimaries
Whether or not to fold the hierarchy back to primary particles.
Header file for the interaction type helper class.
void GetRootMCParticles(pandora::MCParticleList &rootMCParticles) const
Retrieve the root MC particles of the interaction hierarchies.
bool m_foldToLeadingShowers
Whether or not to fold the hierarchy back to leading shower particles.
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::vector< int > IntVector
static void MatchHierarchies(MatchInfo &matchInfo)
Finds the matches between reconstructed and MC hierarchies.
float m_minPurity
Minimum purity to tag a node as being of good quality.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
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...
const pandora::MCParticle * GetLeadingMCParticle() const
Retrieve the leading MC particle associated with this node.
float m_minCompleteness
Minimum completeness to tag a node as being of good quality.
static bool IsInFiducialVolume(const pandora::Pandora &pandora, const pandora::CartesianVector &vertex, const std::string &detector)
Determine if a vertex is within a detector&#39;s fiducial volume. This throws a STATUS_CODE_INVALID_PARAM...
static bool IsDecay(const pandora::MCParticle *const pMCParticle)
Check whether or not an MC particle comes from a decay process.
const QualityCuts & GetQualityCuts() const
Retrieve the quality cuts for matching.
std::string m_pfoListName
Name of input PFO list.
bool m_foldDynamic
Whether or not to use process and topological information to make folding decisions.
Header file for the vertex helper class.
bool m_foldDynamic
Whether or not to fold the hierarchy dynamically.
void Print(const MCHierarchy &mcHierarchy) const
Prints information about which reco nodes are matched to the MC nodes, information about hit sharing...
bool m_foldToLeadingShowers
Whether or not to fold shower children to the leading shower particle.
std::string m_caloHitListName
Name of input calo hit list.
std::vector< MCMatches > MCMatchesVector
bool m_writeTree
Whether or not to output validation information to a ROOT file.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void GetRootPfos(pandora::PfoList &rootPfos) const
Retrieve the root particle flow objects of the interaction hierarchies.
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...
unsigned int GetNMCNodes(const pandora::MCParticle *const pRoot) const
Retrieve the number of MC nodes available to match.
std::string m_filename
The name of the ROOT file to write.
static InteractionDescriptor GetInteractionDescriptor(const pandora::MCParticleList &mcPrimaryList)
Get the interaction descriptor of an event.
std::string m_treename
The name of the ROOT tree to write.
bool m_validateMC
Whether to validate at the level of MC nodes.
bool IsCC() const
Whether or not the interaction is CC.
bool IsTestBeamParticle() const
Check if this is a test beam particle.
Header file for the hierarchy validation algorithm.
bool m_validateEvent
Whether to validate at the level of an event.