All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PFPSliceValidation_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 // Class: PFPSliceValidation //
3 // Plugin Type: analyzer (art v3_02_06) //
4 // File: PFPSliceValidation_module.cc //
5 // //
6 // Generated at Wed Oct 2 03:27:09 2019 by Edward Tyley using cetskelgen //
7 // from cetlib version v3_07_02. //
8 ////////////////////////////////////////////////////////////////////////////////
9 
10 #include "art/Framework/Core/EDAnalyzer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "art_root_io/TFileService.h"
17 #include "canvas/Persistency/Common/FindManyP.h"
18 #include "canvas/Persistency/Common/FindOneP.h"
19 #include "canvas/Persistency/Common/Ptr.h"
20 #include "canvas/Persistency/Common/PtrVector.h"
21 #include "canvas/Utilities/InputTag.h"
22 #include "fhiclcpp/ParameterSet.h"
23 #include "messagefacility/MessageLogger/MessageLogger.h"
24 
25 // LArSoft Includes
36 #include "nusimdata/SimulationBase/MCTruth.h"
37 
38 // Root Includes
39 #include "TTree.h"
40 #include <iostream>
41 #include <vector>
42 
43 namespace ana {
44 class PFPSliceValidation;
45 }
46 
47 class ana::PFPSliceValidation : public art::EDAnalyzer {
48 public:
49  explicit PFPSliceValidation(fhicl::ParameterSet const &pset);
50  // The compiler-generated destructor is fine for non-base
51  // classes without bare pointers or other resource use.
52 
53  // Plugins should not be copied or assigned.
54  PFPSliceValidation(PFPSliceValidation const &) = delete;
58 
59  // Required functions.
60  void analyze(art::Event const &evt) override;
61  void beginJob() override;
62 
63  // Function to get a map of MCTruth to number of hits from that truth
64  std::map<art::Ptr<simb::MCTruth>, int>
66  const sim::ParticleList &trueParticlesMap,
67  const std::map<int, art::Ptr<simb::MCTruth>> &particleTruthMap,
68  const std::vector<art::Ptr<recob::Hit>> &allHits);
69 
70  // Function to match a slice, really any selection of hits, back to MCTruth
71  // Also calculates purity and completeness of match (by reference)
72  art::Ptr<simb::MCTruth>
74  const std::vector<art::Ptr<recob::Hit>> &sliceHits,
75  const std::map<int, art::Ptr<simb::MCTruth>> &particleTruthMap,
76  const std::map<art::Ptr<simb::MCTruth>, int> &truthHitMap,
77  float &completeness, float &purity);
78 
79  // Functions to reset tree variables
80  void ClearTrueTree();
81  void ClearEventTree();
82 
83  // Function to create branches on tree for a list of labels
84  // Branches will have the form branchName_PFParticleLabel
85  template <class T>
86  void initTree(TTree *Tree, std::string branchName, std::map<std::string, T> &Metric,
87  std::vector<std::string> fPFParticleLabels);
88 
89  struct SliceMatch {
90 
91  // Default constructor initialise all of the things to -999
93  : mRecoId(-999)
94  , mRecoPdg(-999)
95  , mComp(-999)
96  , mPurity(-999)
97  , mNuScore(-999)
98  , mVtxX(-999)
99  , mVtxY(-999)
100  , mVtxZ(-999){};
101 
102  SliceMatch(int recoId, int recoPdg, float comp, float purity, float nuScore, double vtx[3])
103  : mRecoId(recoId)
104  , mRecoPdg(recoPdg)
105  , mComp(comp)
106  , mPurity(purity)
107  , mNuScore(nuScore)
108  , mVtxX(vtx[0])
109  , mVtxY(vtx[1])
110  , mVtxZ(vtx[2]){};
111 
112  int mRecoId, mRecoPdg;
114  float mVtxX, mVtxY, mVtxZ;
115 
116  // bool operator<(const SliceMatch& match) const {
117  // return mComp < match,mComp;
118  // }
119  };
120 
121 private:
122  int fVerbose;
123 
125  std::vector<std::string> fPFParticleLabels;
126 
127  art::ServiceHandle<art::TFileService> tfs;
128  art::ServiceHandle<cheat::BackTrackerService> bt_serv;
129  art::ServiceHandle<cheat::ParticleInventoryService> particleInventory;
130 
131  TTree *eventTree;
132  TTree *trueTree;
133 
134  // Event wide metrics
136  std::map<std::string, int> eventPFPSlices, eventPFPNeutrinos;
137  std::map<std::string, std::vector<float>> eventCosmicScores, eventNeutrinoScores;
138 
139  // Truth-by-truth metrics
140  std::map<std::string, bool> nuMatchNeutrino;
141  std::map<std::string, int> nuSlices, nuNeutrinos, bestNuPdg;
142  std::map<std::string, float> bestNuPurity, bestNuComp, bestNuScore;
143 
144  // Neutrino Interaction variables
146  float W, X, Y, QSqr, Pt, Theta, neutrinoE, leptonP;
148 
149  // Vertex reco information
150  std::map<std::string, float> pfpVertexX, pfpVertexY, pfpVertexZ;
152 };
153 
154 ana::PFPSliceValidation::PFPSliceValidation(fhicl::ParameterSet const &pset)
155  : EDAnalyzer{pset}
156  , fVerbose(pset.get<int>("Verbose", 0))
157  , fHitLabel(pset.get<std::string>("HitLabel"))
158  , fGenieGenModuleLabel(pset.get<std::string>("GenieGenModuleLabel"))
159  , fPFParticleLabels(pset.get<std::vector<std::string>>("PFParticleLabels")) {}
160 
162  trueTree = tfs->make<TTree>("trueTree", "Tree with true neutrino metrics");
163  eventTree = tfs->make<TTree>("eventTree", "Tree with event wide metrics");
164 
165  eventTree->Branch("trueNeutrinos", &eventTrueNeutrinos);
166 
167  initTree(eventTree, "pfpNeutrinos", eventPFPNeutrinos, fPFParticleLabels);
168  initTree(eventTree, "pfpSlices", eventPFPSlices, fPFParticleLabels);
169  // Vector of scores of all slices that match to a cosmic
170  initTree(eventTree, "cosmicScores", eventCosmicScores, fPFParticleLabels);
171  // Vector of socres of all slices that match to a neutrino
172  initTree(eventTree, "nuScores", eventNeutrinoScores, fPFParticleLabels);
173 
174  // Truth variables from GENIE
175  trueTree->Branch("intType", &intType);
176  trueTree->Branch("CCNC", &CCNC);
177  trueTree->Branch("neutrinoPDG", &neutrinoPDG);
178  trueTree->Branch("numProtons", &numProtons); // Note, 21Mev KE cut
179  trueTree->Branch("numPi", &numPi);
180  trueTree->Branch("numPi0", &numPi0);
181  trueTree->Branch("numTrueHits", &numTrueHits);
182  trueTree->Branch("W", &W);
183  trueTree->Branch("X", &X);
184  trueTree->Branch("Y", &Y);
185  trueTree->Branch("QSqr", &QSqr);
186  trueTree->Branch("Pt", &Pt);
187  trueTree->Branch("Theta", &Theta);
188  trueTree->Branch("neutrinoE", &neutrinoE);
189  trueTree->Branch("leptonP", &leptonP);
190 
191  // Total number of all slices, and only neutrino slices matched to true interaction
192  initTree(trueTree, "numSlices", nuSlices, fPFParticleLabels);
193  initTree(trueTree, "numNeutrinos", nuNeutrinos, fPFParticleLabels);
194  // Metrics of only best matched slice (Highest completeness)
195  initTree(trueTree, "bestMatchNeutrino", nuMatchNeutrino, fPFParticleLabels);
196  initTree(trueTree, "purity", bestNuPurity, fPFParticleLabels);
197  initTree(trueTree, "comp", bestNuComp, fPFParticleLabels);
198  initTree(trueTree, "score", bestNuScore, fPFParticleLabels);
199  initTree(trueTree, "recoPdg", bestNuPdg, fPFParticleLabels);
200  // True vertex, needed for FV cuts
201  trueTree->Branch("trueVertexX", &trueVertexX);
202  trueTree->Branch("trueVertexY", &trueVertexY);
203  trueTree->Branch("trueVertexZ", &trueVertexZ);
204  // reco vertex of best matched slice, only available for neutrino slices
205  initTree(trueTree, "pfpVertexX", pfpVertexX, fPFParticleLabels);
206  initTree(trueTree, "pfpVertexY", pfpVertexY, fPFParticleLabels);
207  initTree(trueTree, "pfpVertexZ", pfpVertexZ, fPFParticleLabels);
208  initTree(trueTree, "pfpVertexDistX", pfpVertexDistX, fPFParticleLabels);
209  initTree(trueTree, "pfpVertexDistY", pfpVertexDistY, fPFParticleLabels);
210  initTree(trueTree, "pfpVertexDistZ", pfpVertexDistZ, fPFParticleLabels);
211  initTree(trueTree, "pfpVertexDistMag", pfpVertexDistMag, fPFParticleLabels);
212 }
213 
214 void ana::PFPSliceValidation::analyze(art::Event const &evt) {
215  ClearEventTree();
216 
217  // Get the truths in the event:
218  const std::vector<art::Ptr<simb::MCTruth>> truthVec = particleInventory->MCTruthVector_Ps();
219 
220  std::cout << std::setprecision(1) << std::fixed;
221  if (fVerbose) {
222  for (auto const &truth : truthVec) {
223  std::cout << "Truth: " << truth << std::endl;
224  if (truth->NeutrinoSet()) {
225  const simb::MCNeutrino neutrino = truth->GetNeutrino();
226  std::cout << "Neutrino: " << neutrino << std::endl;
227 
228  const simb::MCParticle nu = neutrino.Nu();
229  std::cout << "X: " << nu.Vx() << " Y: " << nu.Vy() << " Z " << nu.Vz() << std::endl;
230  } // truth->NeutrinoSet
231  } // fVerbose
232  } // truth: truthVec
233  std::cout << std::setprecision(2) << std::fixed;
234 
235  // Get a map of each true particle to the MC Truth
236  std::map<int, art::Ptr<simb::MCTruth>> particleTruthMap;
237  const sim::ParticleList &trueParticlesMap = particleInventory->ParticleList();
238  for (auto const &[trackId, particle] : trueParticlesMap) {
239  particleTruthMap[trackId] = particleInventory->ParticleToMCTruth_P(particle);
240  } // [trackId, particle]: trueParticlesMap
241  eventTrueNeutrinos = truthVec.size();
242 
243  // Get reco stuff initialised
244  //std::vector<art::Handle<std::vector<recob::Hit>>> hitHandles;
245  //evt.getManyByType(hitHandles);
246  auto hitHandles = evt.getMany<std::vector<recob::Hit>>();
247  //std::vector<art::Handle<std::vector<recob::Vertex>>> vertexHandles;
248  //evt.getManyByType(vertexHandles);
249  auto vertexHandles = evt.getMany<std::vector<recob::Vertex>>();
250 
251  // Set the handles
252  art::Handle<std::vector<recob::Hit>> hitHandle;
253  art::Handle<std::vector<recob::PFParticle>> pfpHandle;
254  art::Handle<std::vector<recob::Slice>> sliceHandle;
255  art::Handle<std::vector<recob::Vertex>> vertexHandle;
256 
257  // Get all the hits
258  std::vector<art::Ptr<recob::Hit>> allHits;
259  if (evt.getByLabel(fHitLabel, hitHandle))
260  art::fill_ptr_vector(allHits, hitHandle);
261 
262  // Get map of true primary particle to number of reco hits / energy in reco hits
263  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
264  std::map<art::Ptr<simb::MCTruth>, int> truthHitMap =
265  GetTruthHitMap(clockData, trueParticlesMap, particleTruthMap, allHits);
266 
267  // Create maps to store the best matched slice to each truth
268  std::map<std::string, std::map<art::Ptr<simb::MCTruth>, unsigned int>> pfpTruthNuCounterMap;
269  std::map<std::string, std::map<art::Ptr<simb::MCTruth>, unsigned int>> pfpTruthSliceCounterMap;
270  std::map<std::string, std::map<art::Ptr<simb::MCTruth>, SliceMatch>> pfpTruthSliceMatchMap;
271 
272  // Initialise the counters in the maps
273  for (auto const fPFParticleLabel : fPFParticleLabels) {
274  for (auto const &truth : truthVec) {
275  pfpTruthNuCounterMap[fPFParticleLabel][truth] = 0;
276  pfpTruthSliceCounterMap[fPFParticleLabel][truth] = 0;
277  } // truth: truthVec
278  } // fPFParticleLabel: fPFParticleLabels
279 
280  for (auto const fPFParticleLabel : fPFParticleLabels) {
281 
282  if (fVerbose) {
283  std::cout << "On PFParticleLabel: " << fPFParticleLabel << std::endl;
284  } // fVerbose
285 
286  // Get all the PFPs
287  std::vector<art::Ptr<recob::Slice>> pfpSliceVec;
288  if (evt.getByLabel(fPFParticleLabel, sliceHandle))
289  art::fill_ptr_vector(pfpSliceVec, sliceHandle);
290 
291  std::vector<art::Ptr<recob::PFParticle>> pfps;
292  if (evt.getByLabel(fPFParticleLabel, pfpHandle))
293  art::fill_ptr_vector(pfps, pfpHandle);
294 
295  art::FindOneP<recob::Vertex> fopfv(pfpHandle, evt, fPFParticleLabel);
296  if (fopfv.isValid() && fopfv.size() > 0) {
297  evt.get(fopfv.at(0).id(), vertexHandle);
298  if (!vertexHandle.isValid()) {
299  std::cout << "Vertex handle not valid" << std::endl;
300  return;
301  }
302  }
303 
304  art::FindManyP<recob::Hit> fmSliceHits(pfpSliceVec, evt, fPFParticleLabel);
305  if (!fmSliceHits.isValid() || fmSliceHits.size() == 0) {
306  std::cout << "FindMany Slice Hits not valid" << std::endl;
307  return;
308  }
309  art::FindManyP<recob::PFParticle> fmSlicePFPs(pfpSliceVec, evt, fPFParticleLabel);
310  if (!fmSlicePFPs.isValid()) {
311  std::cout << "FindMany Slice PFPs not valid" << std::endl;
312  return;
313  }
314  // Create a map between PFParticles and their IDs
315  art::FindManyP<larpandoraobj::PFParticleMetadata> fmpfpmd(pfps, evt, fPFParticleLabel);
316  if (!fmpfpmd.isValid()) {
317  std::cout << "PFP MetaData handle not valid" << std::endl;
318  return;
319  }
320 
321  // Get maps of the pfp's Id to the pfp objects
322  // And for pfp neutrinos, get the slice id mva score
323  std::map<long unsigned int, art::Ptr<recob::PFParticle>> pfpMap;
324  std::map<long unsigned int, float> pfpNuScoreMap;
325  std::vector<art::Ptr<recob::PFParticle>> pfpNeutrinoVec;
326 
327  for (auto const &pfp : pfps) {
328 
329  long unsigned int pfpID = pfp->Self();
330  pfpMap[pfpID] = pfp;
331 
332  // Select PFP neutrinos
333  if (pfp->PdgCode() == 12 || pfp->PdgCode() == 14) {
334  pfpNeutrinoVec.push_back(pfp);
335  if (fmpfpmd.size() == 0) {
336  std::cout << "PFP neutrino has no metadata" << std::endl;
337  return;
338  } // fmpfpmd.size()
339 
340  // Get the pfparticle metadata to get the MVA score for each slice
341  const std::vector<art::Ptr<larpandoraobj::PFParticleMetadata>> pfpMetaVec =
342  fmpfpmd.at(pfpID);
343  for (auto const pfpMeta : pfpMetaVec) {
345  pfpMeta->GetPropertiesMap();
346  pfpNuScoreMap[pfpID] = propertiesMap.at("NuScore");
347  } // pfpMeta: pfpMetaVec
348  } // pfp->PdgCode()==12 || pfp->PdgCode()==14
349  } // pfp: pfps
350 
351  eventPFPSlices[fPFParticleLabel] = pfpSliceVec.size();
352  eventPFPNeutrinos[fPFParticleLabel] = pfpNeutrinoVec.size();
353 
354  for (const auto &pfpSlice : pfpSliceVec) {
355 
356  std::vector<art::Ptr<recob::Hit>> sliceHits = fmSliceHits.at(pfpSlice.key());
357  std::vector<art::Ptr<recob::PFParticle>> slicePFPs = fmSlicePFPs.at(pfpSlice.key());
358 
359  bool isNeutrinoSlice(false);
360  float nuScore(-999);
361  long unsigned int pfpNu(-999);
362  // Check if it is a neutrino slice, if so get some info from the pfp neutrino
363  for (auto const &pfp : slicePFPs) {
364  if (pfp->PdgCode() == 12 || pfp->PdgCode() == 14) {
365  pfpNu = pfp->Self();
366  nuScore = pfpNuScoreMap[pfpNu];
367  isNeutrinoSlice = true;
368  break; // Should only be 1 neutrino per slice
369  } // pfp->PdgCode()==12 || pfp->PdgCode()==14
370  } // pfp:slicePFPs
371 
372  // Find the MCTruth that contains most of the hits from the slice
373  float purity(-999), completeness(-999);
374  art::Ptr<simb::MCTruth> trueMatch = GetSliceTruthMatchHits(
375  clockData, sliceHits, particleTruthMap, truthHitMap, completeness, purity);
376 
377  // Check if it matched to anything
378  if (trueMatch.isNull())
379  continue;
380 
381  if (fVerbose && isNeutrinoSlice)
382  std::cout << "True Match: " << trueMatch << " with completeness: " << completeness
383  << " and purity: " << purity << " and score: " << nuScore << std::endl;
384 
385  // Increment the counters for the true match
386  ++pfpTruthSliceCounterMap[fPFParticleLabel][trueMatch];
387  if (isNeutrinoSlice) {
388  ++pfpTruthNuCounterMap[fPFParticleLabel][trueMatch];
389  if (trueMatch->NeutrinoSet()) {
390  eventNeutrinoScores[fPFParticleLabel].push_back(nuScore);
391  } else { // cosmicTruth
392  eventCosmicScores[fPFParticleLabel].push_back(nuScore);
393  } // trueMatch->NeutrinoSet()
394  } // isNeutrinoSlice
395 
396  // Choose the best match slice, defined as the slice with the best completeness
397  if (completeness > pfpTruthSliceMatchMap[fPFParticleLabel][trueMatch].mComp) {
398  if (isNeutrinoSlice) {
399 
400  art::Ptr<recob::PFParticle> pfpNeutrino = pfpMap.at(pfpNu);
401  art::Ptr<recob::Vertex> pfpVertex = fopfv.at(pfpNeutrino.key());
402  double pfpVtx[3] = {-999, -999, -999};
403  pfpVertex->XYZ(pfpVtx);
404 
405  SliceMatch match(pfpNu, pfpNeutrino->PdgCode(), completeness, purity, nuScore, pfpVtx);
406 
407  pfpTruthSliceMatchMap[fPFParticleLabel][trueMatch] = match;
408 
409  } else { // isNeutrinoSlice
410  double pfpVtx[3] = {-999, -999, -999};
411  SliceMatch match(-999, -999, completeness, purity, -999, pfpVtx);
412  pfpTruthSliceMatchMap[fPFParticleLabel][trueMatch] = match;
413  } // else isNeutrinoSlice
414  } // bestMatch
415  } // pfpSlice:pfpSliceVec
416  } // auto const fPFParticleLabel: fPFParticleLabels
417 
418  eventTree->Fill();
419 
420  // Get the true neutrinos
421  for (auto const &truth : truthVec) {
422 
423  ClearTrueTree();
424 
425  // Only fill the tree for truth neutrinos
426  if (!truth->NeutrinoSet())
427  continue;
428 
429  // Get the truth interaction variables
430  const simb::MCNeutrino neutrino = truth->GetNeutrino();
431  const simb::MCParticle nu = neutrino.Nu();
432  const simb::MCParticle lepton = neutrino.Lepton();
433 
434  intType = neutrino.Mode();
435  CCNC = neutrino.CCNC();
436  neutrinoPDG = nu.PdgCode();
437  W = neutrino.W();
438  X = neutrino.X();
439  Y = neutrino.Y();
440  QSqr = neutrino.QSqr();
441  Pt = neutrino.Pt();
442  Theta = neutrino.Theta();
443  neutrinoE = nu.E();
444  leptonP = lepton.P();
445 
446  trueVertexX = nu.Vx();
447  trueVertexY = nu.Vy();
448  trueVertexZ = nu.Vz();
449 
450  // Number of true hits from the slice
451  numTrueHits = truthHitMap.at(truth);
452 
453  // Calculate the number of direct daughters
454  for (auto const &[particleId, truthIter] : particleTruthMap) {
455  if (truthIter != truth)
456  continue;
457  const simb::MCParticle *particle = trueParticlesMap.at(particleId);
458  // We only want the primary daughters
459  if (particle->Process() != "primary")
460  continue;
461  // Apply 21MeV KE cut on protons
462  if (particle->PdgCode() == 2212 && (particle->E() - particle->Mass()) > 0.021) {
463  ++numProtons;
464  } else if (std::abs(particle->PdgCode()) == 211) {
465  ++numPi;
466  } else if (std::abs(particle->PdgCode()) == 111) {
467  ++numPi0;
468  }
469  }
470 
471  if (fVerbose) {
472  std::cout << "\nTruth: " << truth << std::endl;
473  } // fVerbose
474 
475  for (auto const fPFParticleLabel : fPFParticleLabels) {
476 
477  // Check we actually match a slice to the truth
478  if (pfpTruthSliceCounterMap[fPFParticleLabel].at(truth)) {
479 
480  SliceMatch match = pfpTruthSliceMatchMap[fPFParticleLabel][truth];
481 
482  nuSlices[fPFParticleLabel] = pfpTruthSliceCounterMap[fPFParticleLabel][truth];
483  nuNeutrinos[fPFParticleLabel] = pfpTruthNuCounterMap[fPFParticleLabel][truth];
484  bestNuComp[fPFParticleLabel] = match.mComp;
485  bestNuPurity[fPFParticleLabel] = match.mPurity;
486  bestNuScore[fPFParticleLabel] = match.mNuScore;
487  bestNuPdg[fPFParticleLabel] = match.mRecoPdg;
488  nuMatchNeutrino[fPFParticleLabel] = (match.mRecoId != -999);
489 
490  // If we matched a neutrino slice, get the vertex info
491  if (nuMatchNeutrino[fPFParticleLabel]) {
492 
493  pfpVertexX[fPFParticleLabel] = match.mVtxX;
494  pfpVertexY[fPFParticleLabel] = match.mVtxY;
495  pfpVertexZ[fPFParticleLabel] = match.mVtxZ;
496 
497  pfpVertexDistX[fPFParticleLabel] = pfpVertexX[fPFParticleLabel] - nu.Vx();
498  pfpVertexDistY[fPFParticleLabel] = pfpVertexY[fPFParticleLabel] - nu.Vy();
499  pfpVertexDistZ[fPFParticleLabel] = pfpVertexZ[fPFParticleLabel] - nu.Vz();
500 
501  pfpVertexDistMag[fPFParticleLabel] =
502  std::hypot(pfpVertexDistX[fPFParticleLabel], pfpVertexDistY[fPFParticleLabel],
503  pfpVertexDistZ[fPFParticleLabel]);
504  } // nuMatchNeutrino
505  } // pfpTruthSliceCounter
506 
507  if (fVerbose) {
508  std::cout << "PFParticleLabel: " << fPFParticleLabel << std::endl;
509 
510  std::cout << "Nu Slices: " << nuSlices[fPFParticleLabel]
511  << " and Nu Neutrinos: " << nuNeutrinos[fPFParticleLabel]
512  << " with best Nu Pdg: " << bestNuPdg[fPFParticleLabel]
513  << "\nCompleteness: " << bestNuComp[fPFParticleLabel]
514  << " and purity: " << bestNuPurity[fPFParticleLabel]
515  << " and score: " << bestNuScore[fPFParticleLabel] << std::endl;
516  } // fVerbose
517  } // fPFParticleLabel: fPFParticleLabels
518  trueTree->Fill();
519  } // truth: truthVec
520  std::cout << "\n" << std::endl;
521 } // analyze
522 
523 std::map<art::Ptr<simb::MCTruth>, int> ana::PFPSliceValidation::GetTruthHitMap(
524  const detinfo::DetectorClocksData &clockData, const sim::ParticleList &trueParticlesMap,
525  const std::map<int, art::Ptr<simb::MCTruth>> &particleTruthMap,
526  const std::vector<art::Ptr<recob::Hit>> &allHits) {
527 
528  // Create a map of true particles to number of hits
529  std::map<int, int> trueParticleHits;
530  for (const auto &hit : allHits) {
531  int trackID = 0;
532  float hitEnergy = 0;
533 
534  // For each hit, chose the particle that contributed the most energy
535  std::vector<sim::TrackIDE> trackIDEs = bt_serv->HitToTrackIDEs(clockData, hit);
536  for (const auto &ide : trackIDEs) {
537  if (ide.energy > hitEnergy) {
538  hitEnergy = ide.energy;
539  trackID = std::abs(ide.trackID);
540  } // ide.energy > hitEnergy
541  } // ide: trackIDEs
542  ++trueParticleHits[trackID];
543  } // hit: allHits
544 
545  // Roll up the particles in their slices
546  std::map<art::Ptr<simb::MCTruth>, int> truthHitMap;
547  for (const auto &[trueParticle, truth] : particleTruthMap) {
548  truthHitMap[truth] += trueParticleHits[trueParticle];
549  } // [trueParticle, truth]: particleTruthMap
550 
551  return truthHitMap;
552 } // GetTruthHitMap
553 
555  const detinfo::DetectorClocksData &clockData,
556  const std::vector<art::Ptr<recob::Hit>> &sliceHits,
557  const std::map<int, art::Ptr<simb::MCTruth>> &particleTruthMap,
558  const std::map<art::Ptr<simb::MCTruth>, int> &truthHitMap, float &completeness, float &purity) {
559 
560  // Create a map of true particles to number of hits
561  std::map<int, int> trueParticleHits;
562  for (const auto &hit : sliceHits) {
563  int trackID = 0;
564  float hitEnergy = 0;
565 
566  // For each hit, chose the particle that contributed the most energy
567  std::vector<sim::TrackIDE> trackIDEs = bt_serv->HitToTrackIDEs(clockData, hit);
568  for (const auto &ide : trackIDEs) {
569  if (ide.energy > hitEnergy) {
570  hitEnergy = ide.energy;
571  trackID = std::abs(ide.trackID);
572  } // ide.energy > hitEnergy
573  } // ide: trackIDEs
574  ++trueParticleHits[trackID];
575  } // hit: sliceHits
576 
577  // Roll up the particles in their slices
578  std::map<art::Ptr<simb::MCTruth>, int> sliceTruthHitMap;
579  for (const auto &[trueParticle, truth] : particleTruthMap) {
580  sliceTruthHitMap[truth] += trueParticleHits[trueParticle];
581  } // [trueParticle, truth]: particleTruthMap
582 
583  // Choose the truth that contributed the most hits
584  int maxHits = 0;
585  art::Ptr<simb::MCTruth> bestTruthMatch;
586  for (const auto &[truth, truthHits] : sliceTruthHitMap) {
587  if (truthHits > maxHits) {
588  maxHits = truthHits;
589  bestTruthMatch = truth;
590  } // truthHits > maxHuts
591  } // [truth, truthHits]: sliceTruthHitMap
592 
593  // If we have truth matched the slice, calculate purtity and completeness
594  // Note these are passed by referecne
595  if (!bestTruthMatch.isNull()) {
596  purity = (float)maxHits / sliceHits.size();
597  completeness = (float)maxHits / truthHitMap.at(bestTruthMatch);
598  } // !bestTruthMatch.isNull()
599 
600  return bestTruthMatch;
601 } // GetSliceTruthMatchHits
602 
604 
605  intType = -999;
606  CCNC = -999;
607  neutrinoPDG = -999;
608  numProtons = 0;
609  numNeutrons = 0;
610  numPi = 0;
611  numPi0 = 0;
612  numTrueHits = 0;
613  W = -999;
614  X = -999;
615  Y = -999;
616  QSqr = -999;
617  Pt = -999;
618  Theta = -999;
619  neutrinoE = -999;
620  leptonP = -999;
621 
622  trueVertexX = -999;
623  trueVertexY = -999;
624  trueVertexZ = -999;
625 
626  for (auto const fPFParticleLabel : fPFParticleLabels) {
627 
628  nuMatchNeutrino[fPFParticleLabel] = false;
629  nuSlices[fPFParticleLabel] = -99999;
630  nuNeutrinos[fPFParticleLabel] = -99999;
631  bestNuPurity[fPFParticleLabel] = -99999;
632  bestNuComp[fPFParticleLabel] = -99999;
633  bestNuScore[fPFParticleLabel] = -99999;
634  bestNuPdg[fPFParticleLabel] = -99999;
635 
636  pfpVertexX[fPFParticleLabel] = -99999;
637  pfpVertexY[fPFParticleLabel] = -99999;
638  pfpVertexZ[fPFParticleLabel] = -99999;
639 
640  pfpVertexDistX[fPFParticleLabel] = -99999;
641  pfpVertexDistY[fPFParticleLabel] = -99999;
642  pfpVertexDistZ[fPFParticleLabel] = -99999;
643  pfpVertexDistMag[fPFParticleLabel] = -99999;
644  } // fPFParticleLabel: fPFParticleLabels
645 } // ClearTrueTree
646 
648  eventTrueNeutrinos = -999;
649  for (auto const fPFParticleLabel : fPFParticleLabels) {
650  eventPFPNeutrinos[fPFParticleLabel] = -999;
651  eventPFPSlices[fPFParticleLabel] = -999;
652  eventCosmicScores[fPFParticleLabel].clear();
653  eventNeutrinoScores[fPFParticleLabel].clear();
654  } // fPFParticleLabel: fPFParticleLabels
655 } // ClearEventTree
656 
657 template <class T>
658 void ana::PFPSliceValidation::initTree(TTree *Tree, std::string branchName,
659  std::map<std::string, T> &Metric,
660  std::vector<std::string> fPFParticleLabels) {
661 
662  for (auto const &fPFParticleLabel : fPFParticleLabels) {
663  std::string branchString = branchName + "_" + fPFParticleLabel;
664  const char *branchChar = branchString.c_str();
665  Tree->Branch(branchChar, &Metric[fPFParticleLabel], 32000, 0);
666  } // fPFParticleLabel: fPFParticleLabels
667 } // initTree
668 
669 DEFINE_ART_MODULE(ana::PFPSliceValidation)
std::map< std::string, float > pfpVertexDistZ
std::vector< std::string > fPFParticleLabels
art::ServiceHandle< cheat::ParticleInventoryService > particleInventory
void initTree(TTree *Tree, std::string branchName, std::map< std::string, T > &Metric, std::vector< std::string > fPFParticleLabels)
std::map< std::string, int > eventPFPSlices
Declaration of signal hit object.
std::map< art::Ptr< simb::MCTruth >, int > GetTruthHitMap(const detinfo::DetectorClocksData &clockData, const sim::ParticleList &trueParticlesMap, const std::map< int, art::Ptr< simb::MCTruth >> &particleTruthMap, const std::vector< art::Ptr< recob::Hit >> &allHits)
std::map< std::string, float > PropertiesMap
art::ServiceHandle< cheat::BackTrackerService > bt_serv
std::map< std::string, float > pfpVertexDistX
process_name hit
Definition: cheaterreco.fcl:51
process_name opflashCryoW ana
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
std::map< std::string, std::vector< float > > eventNeutrinoScores
SliceMatch(int recoId, int recoPdg, float comp, float purity, float nuScore, double vtx[3])
art::Ptr< simb::MCTruth > GetSliceTruthMatchHits(const detinfo::DetectorClocksData &clockData, const std::vector< art::Ptr< recob::Hit >> &sliceHits, const std::map< int, art::Ptr< simb::MCTruth >> &particleTruthMap, const std::map< art::Ptr< simb::MCTruth >, int > &truthHitMap, float &completeness, float &purity)
void analyze(art::Event const &evt) override
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
std::map< std::string, float > bestNuPurity
T abs(T value)
std::map< std::string, std::vector< float > > eventCosmicScores
double Metric(double q, double p)
Definition: Solver.cxx:71
std::map< std::string, float > pfpVertexDistMag
Declaration of cluster object.
art::ServiceHandle< art::TFileService > tfs
std::map< std::string, int > nuNeutrinos
std::map< std::string, float > pfpVertexDistY
std::map< std::string, float > bestNuComp
std::map< std::string, float > pfpVertexZ
std::map< std::string, bool > nuMatchNeutrino
std::map< std::string, float > bestNuScore
Contains all timing reference information for the detector.
std::map< std::string, int > nuSlices
PFPSliceValidation(fhicl::ParameterSet const &pset)
std::map< std::string, float > pfpVertexX
object containing MC truth information necessary for making RawDigits and doing back tracking ...
art::ServiceHandle< art::TFileService > tfs
PFPSliceValidation & operator=(PFPSliceValidation const &)=delete
TCEvent evt
Definition: DataStructs.cxx:8
std::map< std::string, float > pfpVertexY
BEGIN_PROLOG SN nu
std::map< std::string, int > eventPFPNeutrinos
BEGIN_PROLOG could also be cout
std::map< std::string, int > bestNuPdg