EventValidationBaseAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArMonitoring/EventValidationBaseAlgorithm.cc
3  *
4  * @brief Implementation of the event validation algorithm.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
14 
16 
17 #include <sstream>
18 
19 using namespace pandora;
20 
21 namespace lar_content
22 {
23 
24 EventValidationBaseAlgorithm::EventValidationBaseAlgorithm() :
25  m_fileIdentifier(0),
26  m_eventNumber(0),
27  m_printAllToScreen(false),
28  m_printMatchingToScreen(true),
29  m_writeToTree(false),
30  m_useSmallPrimaries(true),
31  m_matchingMinSharedHits(5),
32  m_matchingMinCompleteness(0.1f),
33  m_matchingMinPurity(0.5f)
34 {
35 }
36 
37 //------------------------------------------------------------------------------------------------------------------------------------------
38 
40 {
41  if (m_writeToTree)
42  {
43  try
44  {
45  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_treeName.c_str(), m_fileName.c_str(), "UPDATE"));
46  }
47  catch (const StatusCodeException &)
48  {
49  std::cout << "EventValidationBaseAlgorithm: Unable to write tree " << m_treeName << " to file " << m_fileName << std::endl;
50  }
51  }
52 }
53 
54 //------------------------------------------------------------------------------------------------------------------------------------------
55 
57 {
58  ++m_eventNumber;
59 
60  const MCParticleList *pMCParticleList = nullptr;
61  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_mcParticleListName, pMCParticleList));
62 
63  const CaloHitList *pCaloHitList = nullptr;
64  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_caloHitListName, pCaloHitList));
65 
66  const PfoList *pPfoList = nullptr;
67  (void)PandoraContentApi::GetList(*this, m_pfoListName, pPfoList);
68 
69  ValidationInfo validationInfo;
70  this->FillValidationInfo(pMCParticleList, pCaloHitList, pPfoList, validationInfo);
71 
73  this->PrintAllMatches(validationInfo);
74 
76  this->PrintInterpretedMatches(validationInfo);
77 
78  if (m_writeToTree)
79  this->WriteInterpretedMatches(validationInfo);
80 
81  return STATUS_CODE_SUCCESS;
82 }
83 
84 //------------------------------------------------------------------------------------------------------------------------------------------
85 
87  const ValidationInfo &validationInfo, LArMCParticleHelper::MCParticleToPfoHitSharingMap &interpretedMCToPfoHitSharingMap) const
88 {
89  MCParticleVector mcPrimaryVector;
91 
92  PfoSet usedPfos;
93  while (this->GetStrongestPfoMatch(validationInfo, mcPrimaryVector, usedPfos, interpretedMCToPfoHitSharingMap))
94  {
95  }
96  this->GetRemainingPfoMatches(validationInfo, mcPrimaryVector, usedPfos, interpretedMCToPfoHitSharingMap);
97 
98  // Ensure all primaries have an entry, and sorting is as desired
99  for (const MCParticle *const pMCPrimary : mcPrimaryVector)
100  {
101  LArMCParticleHelper::PfoToSharedHitsVector &pfoHitPairs(interpretedMCToPfoHitSharingMap[pMCPrimary]);
102  std::sort(pfoHitPairs.begin(), pfoHitPairs.end(),
104  return ((a.second.size() != b.second.size()) ? a.second.size() > b.second.size() : LArPfoHelper::SortByNHits(a.first, b.first));
105  });
106  }
107 }
108 
109 //------------------------------------------------------------------------------------------------------------------------------------------
110 
111 bool EventValidationBaseAlgorithm::GetStrongestPfoMatch(const ValidationInfo &validationInfo, const MCParticleVector &mcPrimaryVector,
112  PfoSet &usedPfos, LArMCParticleHelper::MCParticleToPfoHitSharingMap &interpretedMCToPfoHitSharingMap) const
113 {
114  const MCParticle *pBestMCParticle(nullptr);
115  LArMCParticleHelper::PfoCaloHitListPair bestPfoHitPair(nullptr, CaloHitList());
116 
117  for (const MCParticle *const pMCPrimary : mcPrimaryVector)
118  {
119  if (interpretedMCToPfoHitSharingMap.count(pMCPrimary))
120  continue;
121 
122  if (!m_useSmallPrimaries && !validationInfo.GetTargetMCParticleToHitsMap().count(pMCPrimary))
123  continue;
124 
125  if (!validationInfo.GetMCToPfoHitSharingMap().count(pMCPrimary))
126  continue;
127 
128  for (const LArMCParticleHelper::PfoCaloHitListPair &pfoToSharedHits : validationInfo.GetMCToPfoHitSharingMap().at(pMCPrimary))
129  {
130  if (usedPfos.count(pfoToSharedHits.first))
131  continue;
132 
133  if (!this->IsGoodMatch(validationInfo.GetAllMCParticleToHitsMap().at(pMCPrimary),
134  validationInfo.GetPfoToHitsMap().at(pfoToSharedHits.first), pfoToSharedHits.second))
135  continue;
136 
137  if (pfoToSharedHits.second.size() > bestPfoHitPair.second.size())
138  {
139  pBestMCParticle = pMCPrimary;
140  bestPfoHitPair = pfoToSharedHits;
141  }
142  }
143  }
144 
145  if (!pBestMCParticle || !bestPfoHitPair.first)
146  return false;
147 
148  interpretedMCToPfoHitSharingMap[pBestMCParticle].push_back(bestPfoHitPair);
149  usedPfos.insert(bestPfoHitPair.first);
150  return true;
151 }
152 
153 //------------------------------------------------------------------------------------------------------------------------------------------
154 
156  const PfoSet &usedPfos, LArMCParticleHelper::MCParticleToPfoHitSharingMap &interpretedMCToPfoHitSharingMap) const
157 {
158  LArMCParticleHelper::PfoToMCParticleHitSharingMap pfoToMCParticleHitSharingMap;
159 
160  for (const MCParticle *const pMCPrimary : mcPrimaryVector)
161  {
162  if (!m_useSmallPrimaries && !validationInfo.GetTargetMCParticleToHitsMap().count(pMCPrimary))
163  continue;
164 
165  if (!validationInfo.GetMCToPfoHitSharingMap().count(pMCPrimary))
166  continue;
167 
168  for (const LArMCParticleHelper::PfoCaloHitListPair &pfoToSharedHits : validationInfo.GetMCToPfoHitSharingMap().at(pMCPrimary))
169  {
170  if (usedPfos.count(pfoToSharedHits.first))
171  continue;
172 
173  const LArMCParticleHelper::MCParticleCaloHitListPair mcParticleToHits(pMCPrimary, pfoToSharedHits.second);
174  LArMCParticleHelper::PfoToMCParticleHitSharingMap::iterator iter(pfoToMCParticleHitSharingMap.find(pfoToSharedHits.first));
175 
176  if (pfoToMCParticleHitSharingMap.end() == iter)
177  {
178  pfoToMCParticleHitSharingMap[pfoToSharedHits.first].push_back(mcParticleToHits);
179  }
180  else
181  {
182  if (1 != iter->second.size())
183  throw StatusCodeException(STATUS_CODE_FAILURE);
184 
185  LArMCParticleHelper::MCParticleCaloHitListPair &originalMCParticleToHits(iter->second.at(0));
186 
187  if (mcParticleToHits.second.size() > originalMCParticleToHits.second.size())
188  originalMCParticleToHits = mcParticleToHits;
189  }
190  }
191  }
192 
193  for (const auto &mapEntry : pfoToMCParticleHitSharingMap)
194  {
195  const LArMCParticleHelper::MCParticleCaloHitListPair &mcParticleToHits(mapEntry.second.at(0));
196  interpretedMCToPfoHitSharingMap[mcParticleToHits.first].push_back(
197  LArMCParticleHelper::PfoCaloHitListPair(mapEntry.first, mcParticleToHits.second));
198  }
199 }
200 
201 //------------------------------------------------------------------------------------------------------------------------------------------
202 
203 bool EventValidationBaseAlgorithm::IsGoodMatch(const CaloHitList &trueHits, const CaloHitList &recoHits, const CaloHitList &sharedHits) const
204 {
205  const float purity((recoHits.size() > 0) ? static_cast<float>(sharedHits.size()) / static_cast<float>(recoHits.size()) : 0.f);
206  const float completeness((trueHits.size() > 0) ? static_cast<float>(sharedHits.size()) / static_cast<float>(trueHits.size()) : 0.f);
207 
208  return ((sharedHits.size() >= m_matchingMinSharedHits) && (purity >= m_matchingMinPurity) && (completeness >= m_matchingMinCompleteness));
209 }
210 
211 //------------------------------------------------------------------------------------------------------------------------------------------
212 
213 StatusCode EventValidationBaseAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
214 {
215  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListName", m_caloHitListName));
216  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
217  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "PfoListName", m_pfoListName));
218 
219  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
220  XmlHelper::ReadValue(xmlHandle, "MinPrimaryGoodHits", m_primaryParameters.m_minPrimaryGoodHits));
221 
222  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
223  XmlHelper::ReadValue(xmlHandle, "MinHitsForGoodView", m_primaryParameters.m_minHitsForGoodView));
224 
225  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
226  XmlHelper::ReadValue(xmlHandle, "MinPrimaryGoodViews", m_primaryParameters.m_minPrimaryGoodViews));
227 
228  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
229  XmlHelper::ReadValue(xmlHandle, "SelectInputHits", m_primaryParameters.m_selectInputHits));
230 
231  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
232  XmlHelper::ReadValue(xmlHandle, "MinHitSharingFraction", m_primaryParameters.m_minHitSharingFraction));
233 
234  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
235  XmlHelper::ReadValue(xmlHandle, "MaxPhotonPropagation", m_primaryParameters.m_maxPhotonPropagation));
236 
237  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
238  XmlHelper::ReadValue(xmlHandle, "FoldToPrimaries", m_primaryParameters.m_foldBackHierarchy));
239 
240  PANDORA_RETURN_RESULT_IF_AND_IF(
241  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PrintAllToScreen", m_printAllToScreen));
242 
243  PANDORA_RETURN_RESULT_IF_AND_IF(
244  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PrintMatchingToScreen", m_printMatchingToScreen));
245 
246  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "WriteToTree", m_writeToTree));
247 
248  PANDORA_RETURN_RESULT_IF_AND_IF(
249  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UseSmallPrimaries", m_useSmallPrimaries));
250 
251  PANDORA_RETURN_RESULT_IF_AND_IF(
252  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MatchingMinSharedHits", m_matchingMinSharedHits));
253 
254  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
255  XmlHelper::ReadValue(xmlHandle, "MatchingMinCompleteness", m_matchingMinCompleteness));
256 
257  PANDORA_RETURN_RESULT_IF_AND_IF(
258  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MatchingMinPurity", m_matchingMinPurity));
259 
260  if (m_writeToTree)
261  {
262  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputTree", m_treeName));
263  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputFile", m_fileName));
264 
265  PANDORA_RETURN_RESULT_IF_AND_IF(
266  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "FileIdentifier", m_fileIdentifier));
267  }
268 
269  return STATUS_CODE_SUCCESS;
270 }
271 
272 } // namespace lar_content
intermediate_table::iterator iterator
const LArMCParticleHelper::PfoContributionMap & GetPfoToHitsMap() const
Get the pfo to hits map.
unsigned int m_minPrimaryGoodViews
the minimum number of primary good views
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_selectInputHits
whether to select input hits
std::pair< const pandora::MCParticle *, pandora::CaloHitList > MCParticleCaloHitListPair
const LArMCParticleHelper::MCContributionMap & GetTargetMCParticleToHitsMap() const
Get the target mc particle to hits map.
Header file for the interaction type helper class.
unsigned int m_minPrimaryGoodHits
the minimum number of primary good Hits
void InterpretMatching(const ValidationInfo &validationInfo, LArMCParticleHelper::MCParticleToPfoHitSharingMap &interpretedMCToPfoHitSharingMap) const
Apply an interpretative matching procedure to the comprehensive matches in the provided validation in...
void PrintAllMatches(const ValidationInfo &validationInfo) const
Print all/raw matching information to screen.
const LArMCParticleHelper::MCContributionMap & GetAllMCParticleToHitsMap() const
Get the all mc particle to hits map.
float m_matchingMinPurity
The minimum particle purity to declare a match.
std::map< const pandora::MCParticle *, PfoToSharedHitsVector > MCParticleToPfoHitSharingMap
std::vector< PfoCaloHitListPair > PfoToSharedHitsVector
const LArMCParticleHelper::MCParticleToPfoHitSharingMap & GetMCToPfoHitSharingMap() const
Get the mc to pfo hit sharing map.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
bool m_foldBackHierarchy
whether to fold the hierarchy back to the primary (neutrino) or leading particles (test beam) ...
Header file for the lar monitoring helper helper class.
bool m_printAllToScreen
Whether to print all/raw matching details to screen.
unsigned int m_minHitsForGoodView
the minimum number of Hits for a good view
float m_maxPhotonPropagation
the maximum photon propagation length
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void WriteInterpretedMatches(const ValidationInfo &validationInfo) const
Write interpreted matching information to tree.
Header file for the event validation algorithm.
std::string m_pfoListName
Name of input Pfo list.
static void GetOrderedMCParticleVector(const LArMCParticleHelper::MCContributionMapVector &selectedMCParticleToGoodHitsMaps, pandora::MCParticleVector &orderedMCParticleVector)
Order input MCParticles by their number of hits.
void PrintInterpretedMatches(const ValidationInfo &validationInfo) const
Print interpreted matching information to screen.
LArMCParticleHelper::PrimaryParameters m_primaryParameters
The mc particle primary selection parameters.
const double a
std::string m_mcParticleListName
Name of input MC particle list.
bool m_writeToTree
Whether to write all/raw matching details to tree.
unsigned int m_matchingMinSharedHits
The minimum number of shared hits used in matching scheme.
float m_minHitSharingFraction
the minimum Hit sharing fraction
bool GetStrongestPfoMatch(const ValidationInfo &validationInfo, const pandora::MCParticleVector &mcPrimaryVector, pandora::PfoSet &usedPfos, LArMCParticleHelper::MCParticleToPfoHitSharingMap &interpretedMCToPfoHitSharingMap) const
Get the strongest pfo match (most matched hits) between an available mc primary and an available pfo...
bool m_useSmallPrimaries
Whether to consider matches to mc primaries with fewer than m_matchingMinPrimaryHits.
void GetRemainingPfoMatches(const ValidationInfo &validationInfo, const pandora::MCParticleVector &mcPrimaryVector, const pandora::PfoSet &usedPfos, LArMCParticleHelper::MCParticleToPfoHitSharingMap &interpretedMCToPfoHitSharingMap) const
Get the best matches for any pfos left-over after the strong matching procedure.
std::pair< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoCaloHitListPair
bool m_printMatchingToScreen
Whether to print matching output to screen.
float m_matchingMinCompleteness
The minimum particle completeness to declare a match.
static bool * b
Definition: config.cpp:1043
bool IsGoodMatch(const pandora::CaloHitList &trueHits, const pandora::CaloHitList &recoHits, const pandora::CaloHitList &sharedHits) const
Whether a provided mc primary and pfo are deemed to be a good match.
virtual void FillValidationInfo(const pandora::MCParticleList *const pMCParticleList, const pandora::CaloHitList *const pCaloHitList, const pandora::PfoList *const pPfoList, ValidationInfo &validationInfo) const =0
Fill the validation info containers.
std::string m_caloHitListName
Name of input calo hit list.
std::map< const pandora::ParticleFlowObject *, MCParticleToSharedHitsVector > PfoToMCParticleHitSharingMap
QTextStream & endl(QTextStream &s)