LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
LArMonitoringHelper.cc
Go to the documentation of this file.
1 
9 #include "Pandora/PdgTable.h"
10 
11 #include "Objects/CaloHit.h"
12 #include "Objects/MCParticle.h"
13 #include "Objects/ParticleFlowObject.h"
14 
15 #include "Helpers/MCParticleHelper.h"
16 
20 
21 #include <algorithm>
22 
23 using namespace pandora;
24 
25 namespace lar_content
26 {
27 
28 unsigned int LArMonitoringHelper::CountHitsByType(const HitType hitType, const CaloHitList &caloHitList)
29 {
30  unsigned int nHitsOfSpecifiedType(0);
31 
32  for (const CaloHit *const pCaloHit : caloHitList)
33  {
34  if (hitType == pCaloHit->GetHitType())
35  ++nHitsOfSpecifiedType;
36  }
37 
38  return nHitsOfSpecifiedType;
39 }
40 
41 //------------------------------------------------------------------------------------------------------------------------------------------
42 
43 void LArMonitoringHelper::GetOrderedMCParticleVector(const LArMCParticleHelper::MCContributionMapVector &selectedMCParticleToGoodHitsMaps, MCParticleVector &orderedMCParticleVector)
44 {
45  for (const LArMCParticleHelper::MCContributionMap &mcParticleToGoodHitsMap : selectedMCParticleToGoodHitsMaps)
46  {
47  if (mcParticleToGoodHitsMap.empty())
48  continue;
49 
50  // Copy map contents to vector it can be sorted
51  std::vector<LArMCParticleHelper::MCParticleCaloHitListPair> mcParticleToGoodHitsVect;
52  std::copy(mcParticleToGoodHitsMap.begin(), mcParticleToGoodHitsMap.end(), std::back_inserter(mcParticleToGoodHitsVect));
53 
54  // Sort by number of hits descending
55  std::sort(mcParticleToGoodHitsVect.begin(), mcParticleToGoodHitsVect.end(), [] (const LArMCParticleHelper::MCParticleCaloHitListPair &a, const LArMCParticleHelper::MCParticleCaloHitListPair &b) -> bool
56  {
57  // Neutrinos, then beam particles, then cosmic rays
58  const bool isANuFinalState(LArMCParticleHelper::IsBeamNeutrinoFinalState(a.first)), isBNuFinalState(LArMCParticleHelper::IsBeamNeutrinoFinalState(b.first));
59 
60  if (isANuFinalState != isBNuFinalState)
61  return isANuFinalState;
62 
63  const bool isABeamParticle(LArMCParticleHelper::IsBeamParticle(a.first)), isBBeamParticle(LArMCParticleHelper::IsBeamParticle(b.first));
64 
65  if (isABeamParticle != isBBeamParticle)
66  return isABeamParticle;
67 
68  // Then sort by numbers of true hits
69  if (a.second.size() != b.second.size())
70  return (a.second.size() > b.second.size());
71 
72  // Default to normal MCParticle sorting
73  return LArMCParticleHelper::SortByMomentum(a.first, b.first);
74  });
75 
76  for (const LArMCParticleHelper::MCParticleCaloHitListPair &mcParticleCaloHitPair : mcParticleToGoodHitsVect)
77  orderedMCParticleVector.push_back(mcParticleCaloHitPair.first);
78  }
79 
80  // Check that all elements of the vector are unique
81  const unsigned int nMCParticles(orderedMCParticleVector.size());
82  if (std::distance(orderedMCParticleVector.begin(), std::unique(orderedMCParticleVector.begin(), orderedMCParticleVector.end())) != nMCParticles)
83  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
84 }
85 
86 //------------------------------------------------------------------------------------------------------------------------------------------
87 
88 void LArMonitoringHelper::GetOrderedPfoVector(const LArMCParticleHelper::PfoContributionMap &pfoToReconstructable2DHitsMap, pandora::PfoVector &orderedPfoVector)
89 {
90  // Copy map contents to vector it can be sorted
91  std::vector<LArMCParticleHelper::PfoCaloHitListPair> pfoToReconstructable2DHitsVect;
92  std::copy(pfoToReconstructable2DHitsMap.begin(), pfoToReconstructable2DHitsMap.end(), std::back_inserter(pfoToReconstructable2DHitsVect));
93 
94  // Sort by number of hits descending putting neutrino final states first
95  std::sort(pfoToReconstructable2DHitsVect.begin(), pfoToReconstructable2DHitsVect.end(), [] (const LArMCParticleHelper::PfoCaloHitListPair &a, const LArMCParticleHelper::PfoCaloHitListPair &b) -> bool
96  {
97  // Neutrinos before cosmic rays
98  const bool isANuFinalState(LArPfoHelper::IsNeutrinoFinalState(a.first)), isBNuFinalState(LArPfoHelper::IsNeutrinoFinalState(b.first));
99 
100  if (isANuFinalState != isBNuFinalState)
101  return isANuFinalState;
102 
103  if (a.second.size() != b.second.size())
104  return (a.second.size() > b.second.size());
105 
106  // Default to normal pfo sorting
107  return LArPfoHelper::SortByNHits(a.first, b.first);
108  });
109 
110  for (const LArMCParticleHelper::PfoCaloHitListPair &pfoCaloHitPair : pfoToReconstructable2DHitsVect)
111  orderedPfoVector.push_back(pfoCaloHitPair.first);
112 
113  // Check that all elements of the vector are unique
114  const unsigned int nPfos(orderedPfoVector.size());
115  if (std::distance(orderedPfoVector.begin(), std::unique(orderedPfoVector.begin(), orderedPfoVector.end())) != nPfos)
116  throw StatusCodeException(STATUS_CODE_ALREADY_PRESENT);
117 }
118 
119 //------------------------------------------------------------------------------------------------------------------------------------------
120 
121 void LArMonitoringHelper::PrintMCParticleTable(const LArMCParticleHelper::MCContributionMap &selectedMCParticleToGoodHitsMap, const MCParticleVector &orderedMCParticleVector)
122 {
123  if (selectedMCParticleToGoodHitsMap.empty())
124  {
125  std::cout << "No MCParticles supplied." << std::endl;
126  return;
127  }
128 
129  LArFormattingHelper::Table table({"ID", "NUANCE", "TYPE", "", "E", "dist", "", "nGoodHits", "U", "V", "W"});
130 
131  unsigned int usedParticleCount(0);
132  for (unsigned int id = 0; id < orderedMCParticleVector.size(); ++id)
133  {
134  const MCParticle *const pMCParticle(orderedMCParticleVector.at(id));
135 
136  LArMCParticleHelper::MCContributionMap::const_iterator it = selectedMCParticleToGoodHitsMap.find(pMCParticle);
137  if (selectedMCParticleToGoodHitsMap.end() == it)
138  continue; // ATTN MCParticles in selectedMCParticleToGoodHitsMap may be a subset of orderedMCParticleVector
139 
140  // ATTN enumerate from 1 to match event validation algorithm
141  table.AddElement(id + 1);
142  table.AddElement(LArMCParticleHelper::GetNuanceCode(pMCParticle));
143  table.AddElement(PdgTable::GetParticleName(pMCParticle->GetParticleId()));
144 
145  table.AddElement(pMCParticle->GetEnergy());
146  table.AddElement((pMCParticle->GetEndpoint() - pMCParticle->GetVertex()).GetMagnitude());
147 
148  table.AddElement(it->second.size());
149  table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_U, it->second));
150  table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_V, it->second));
151  table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_W, it->second));
152 
153  usedParticleCount++;
154  }
155 
156  // Check every MCParticle in selectedMCParticleToGoodHitsMap has been printed
157  if (usedParticleCount != selectedMCParticleToGoodHitsMap.size())
158  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
159 
160  table.Print();
161 }
162 
163 //------------------------------------------------------------------------------------------------------------------------------------------
164 
165 void LArMonitoringHelper::PrintPfoTable(const LArMCParticleHelper::PfoContributionMap &pfoToReconstructable2DHitsMap, const PfoVector &orderedPfoVector)
166 {
167  if (pfoToReconstructable2DHitsMap.empty())
168  {
169  std::cout << "No Pfos supplied." << std::endl;
170  return;
171  }
172 
173  LArFormattingHelper::Table table({"ID", "PID", "Is Nu FS", "", "nGoodHits", "U", "V", "W"});
174 
175  for (unsigned int id = 0; id < orderedPfoVector.size(); ++id)
176  {
177  const ParticleFlowObject *const pPfo(orderedPfoVector.at(id));
178 
179  LArMCParticleHelper::PfoContributionMap::const_iterator it = pfoToReconstructable2DHitsMap.find(pPfo);
180  if (pfoToReconstructable2DHitsMap.end() == it)
181  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
182 
183  // ATTN enumerate from 1 to match event validation algorithm
184  table.AddElement(id + 1);
185  table.AddElement(pPfo->GetParticleId());
186  table.AddElement(LArPfoHelper::IsNeutrinoFinalState(pPfo));
187 
188  table.AddElement(it->second.size());
189  table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_U, it->second));
190  table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_V, it->second));
191  table.AddElement(LArMonitoringHelper::CountHitsByType(TPC_VIEW_W, it->second));
192  }
193 
194  table.Print();
195 }
196 
197 //------------------------------------------------------------------------------------------------------------------------------------------
198 
199 void LArMonitoringHelper::PrintMatchingTable(const PfoVector &orderedPfoVector, const MCParticleVector &orderedMCParticleVector, const LArMCParticleHelper::MCParticleToPfoHitSharingMap &mcParticleToPfoHitSharingMap, const unsigned int nMatches)
200 {
201  if (orderedPfoVector.empty())
202  {
203  std::cout << "No Pfos supplied." << std::endl;
204  return;
205  }
206 
207  if (orderedMCParticleVector.empty())
208  {
209  std::cout << "No MCParticles supplied." << std::endl;
210  return;
211  }
212 
213  // Get the maximum number of MCParticle to Pfos matches that need to be shown
214  unsigned int maxMatches(0);
215  for (const auto &entry : mcParticleToPfoHitSharingMap)
216  maxMatches = std::max(static_cast<unsigned int>(entry.second.size()), maxMatches);
217 
218  const bool showOthersColumn(maxMatches > nMatches);
219  const unsigned int nMatchesToShow(std::min(maxMatches, nMatches));
220 
221  // Set up the table headers
222  std::vector<std::string> tableHeaders({"MCParticle",""});
223  for (unsigned int i = 0; i < nMatchesToShow; ++i)
224  {
225  tableHeaders.push_back("");
226  tableHeaders.push_back("Pfo");
227  tableHeaders.push_back("nSharedHits");
228  }
229 
230  if (showOthersColumn)
231  {
232  tableHeaders.push_back("");
233  tableHeaders.push_back("");
234  tableHeaders.push_back("nOtherPfos");
235  tableHeaders.push_back("nSharedHits");
236  }
237 
238  LArFormattingHelper::Table table(tableHeaders);
239 
240  // Make a new row for each MCParticle
241  for (unsigned int mcParticleId = 0; mcParticleId < orderedMCParticleVector.size(); ++mcParticleId)
242  {
243  LArMCParticleHelper::MCParticleToPfoHitSharingMap::const_iterator it = mcParticleToPfoHitSharingMap.find(orderedMCParticleVector.at(mcParticleId));
244  if (it == mcParticleToPfoHitSharingMap.end())
245  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
246 
247  const MCParticle *const pMCParticle(it->first);
248  const LArFormattingHelper::Color mcCol(
249  LArMCParticleHelper::IsBeamNeutrinoFinalState(pMCParticle) ?
250  LArFormattingHelper::LIGHT_GREEN : (LArMCParticleHelper::IsBeamParticle(pMCParticle) ?
251  LArFormattingHelper::LIGHT_BLUE : LArFormattingHelper::LIGHT_RED
252  )
253  );
254 
255  // ATTN enumerate from 1 to match event validation algorithm
256  table.AddElement(mcParticleId + 1, LArFormattingHelper::REGULAR, mcCol);
257 
258  // Get the matched Pfos
259  unsigned int nPfosShown(0);
260  unsigned int nOtherHits(0);
261  for (const auto &pfoNSharedHitsPair : it->second)
262  {
263  for (unsigned int pfoId = 0; pfoId < orderedPfoVector.size(); ++pfoId)
264  {
265  if (pfoNSharedHitsPair.first != orderedPfoVector.at(pfoId)) continue;
266 
267  if (nPfosShown < nMatchesToShow)
268  {
269  // ATTN enumerate from 1 to match event validation algorithm
270  const LArFormattingHelper::Color pfoCol(LArPfoHelper::IsNeutrinoFinalState(pfoNSharedHitsPair.first) ? LArFormattingHelper::LIGHT_GREEN : LArFormattingHelper::LIGHT_RED);
271  table.AddElement(pfoId + 1, LArFormattingHelper::REGULAR, pfoCol);
272  table.AddElement(pfoNSharedHitsPair.second.size(), LArFormattingHelper::REGULAR, pfoCol);
273  nPfosShown++;
274  }
275  else
276  {
277  nOtherHits += pfoNSharedHitsPair.second.size();
278  }
279  break;
280  }
281  }
282 
283  // Pad the rest of the row with empty entries
284  for (unsigned int i = 0; i < nMatchesToShow - nPfosShown; ++i)
285  {
286  table.AddElement("");
287  table.AddElement("");
288  }
289 
290  // Print any remaining matches
291  if (!showOthersColumn) continue;
292 
293  if (nOtherHits != 0)
294  {
295  table.AddElement(it->second.size() - nPfosShown);
296  table.AddElement(nOtherHits);
297  }
298  else
299  {
300  table.AddElement("");
301  table.AddElement("");
302  }
303  }
304  table.Print();
305 }
306 
307 } // namespace lar_content
Header file for the pfo helper class.
Header file for the lar monitoring helper helper class.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
std::map< const pandora::MCParticle *, PfoToSharedHitsVector > MCParticleToPfoHitSharingMap
void AddElement(const T &value, const Style style=REGULAR, const Color color=DEFAULT)
Add an element to the table into the next (non-separator) column.
std::vector< MCContributionMap > MCContributionMapVector
Int_t min
Definition: plot.C:26
std::pair< const pandora::MCParticle *, pandora::CaloHitList > MCParticleCaloHitListPair
void Print() const
Print the table.
std::unordered_map< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoContributionMap
std::pair< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoCaloHitListPair