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