PFParticleMonitoring_module.cc
Go to the documentation of this file.
1 /**
2  * @file larpandora/LArPandoraAnalysis/PFParticleMonitoring_module.cc
3  *
4  * @brief Analysis module for created particles
5  *
6  */
7 
10 
11 #include "TTree.h"
12 
14 
15 #include <string>
16 
17 //------------------------------------------------------------------------------------------------------------------------------------------
18 
19 namespace lar_pandora {
20 
21  /**
22  * @brief PFParticleMonitoring class
23  */
25  public:
26  /**
27  * @brief Constructor
28  *
29  * @param pset
30  */
32 
33  /**
34  * @brief Destructor
35  */
36  virtual ~PFParticleMonitoring();
37 
38  void beginJob();
39  void endJob();
40  void analyze(const art::Event& evt);
41  void reconfigure(fhicl::ParameterSet const& pset);
42 
43  private:
44  typedef std::set<art::Ptr<recob::PFParticle>> PFParticleSet;
45  typedef std::set<art::Ptr<simb::MCParticle>> MCParticleSet;
46  typedef std::set<art::Ptr<simb::MCTruth>> MCTruthSet;
47 
48  /**
49  * @brief Build mapping from true neutrinos to hits
50  *
51  * @param truthToParticles the input mapping from true event to true particles
52  * @param trueParticlesToHits the input mapping from true particles to hits
53  * @param trueNeutrinosToHits the output mapping from trues event to hits
54  * @param trueHitsToNeutrinos the output mappign from hits to true events
55  */
56  void BuildTrueNeutrinoHitMaps(const MCTruthToMCParticles& truthToParticles,
57  const MCParticlesToHits& trueParticlesToHits,
58  MCTruthToHits& trueNeutrinosToHits,
59  HitsToMCTruth& trueHitsToNeutrinos) const;
60 
61  /**
62  * @brief Build mapping from reconstructed neutrinos to hits
63  *
64  * @param recoParticleMap the input mapping from reconstructed particle and particle ID
65  * @param recoParticlesToHits the input mapping from reconstructed particles to hits
66  * @param recoNeutrinosToHits the output mapping from reconstructed particles to hits
67  * @param recoHitsToNeutrinos the output mapping from reconstructed hits to particles
68  */
69  void BuildRecoNeutrinoHitMaps(const PFParticleMap& recoParticleMap,
70  const PFParticlesToHits& recoParticlesToHits,
71  PFParticlesToHits& recoNeutrinosToHits,
72  HitsToPFParticles& recoHitsToNeutrinos) const;
73 
74  /**
75  * @brief Perform matching between true and reconstructed neutrino events
76  *
77  * @param recoNeutrinosToHits the mapping from reconstructed neutrino events to hits
78  * @param trueHitsToNeutrinos the mapping from hits to true neutrino events
79  * @param matchedNeutrinos the output matches between reconstructed and true neutrinos
80  * @param matchedNeutrinoHits the output matches between reconstructed neutrinos and hits
81  */
82  void GetRecoToTrueMatches(const PFParticlesToHits& recoNeutrinosToHits,
83  const HitsToMCTruth& trueHitsToNeutrinos,
84  MCTruthToPFParticles& matchedNeutrinos,
85  MCTruthToHits& matchedNeutrinoHits) const;
86 
87  /**
88  * @brief Perform matching between true and reconstructed neutrino events
89  *
90  * @param recoNeutrinosToHits the mapping from reconstructed neutrino events to hits
91  * @param trueHitsToNeutrinos the mapping from hits to true neutrino events
92  * @param matchedNeutrinos the output matches between reconstructed and true neutrinos
93  * @param matchedNeutrinoHits the output matches between reconstructed neutrinos and hits
94  * @param recoVeto the veto list for reconstructed particles
95  * @param trueVeto the veto list for true particles
96  */
97  void GetRecoToTrueMatches(const PFParticlesToHits& recoNeutrinosToHits,
98  const HitsToMCTruth& trueHitsToNeutrinos,
99  MCTruthToPFParticles& matchedNeutrinos,
100  MCTruthToHits& matchedNeutrinoHits,
101  PFParticleSet& recoVeto,
102  MCTruthSet& trueVeto) const;
103 
104  /**
105  * @brief Perform matching between true and reconstructed particles
106  *
107  * @param recoParticlesToHits the mapping from reconstructed particles to hits
108  * @param trueHitsToParticles the mapping from hits to true particles
109  * @param matchedParticles the output matches between reconstructed and true particles
110  * @param matchedHits the output matches between reconstructed particles and hits
111  */
112  void GetRecoToTrueMatches(const PFParticlesToHits& recoParticlesToHits,
113  const HitsToMCParticles& trueHitsToParticles,
114  MCParticlesToPFParticles& matchedParticles,
115  MCParticlesToHits& matchedHits) const;
116 
117  /**
118  * @brief Perform matching between true and reconstructed particles
119  *
120  * @param recoParticlesToHits the mapping from reconstructed particles to hits
121  * @param trueHitsToParticles the mapping from hits to true particles
122  * @param matchedParticles the output matches between reconstructed and true particles
123  * @param matchedHits the output matches between reconstructed particles and hits
124  * @param recoVeto the veto list for reconstructed particles
125  * @param trueVeto the veto list for true particles
126  */
127  void GetRecoToTrueMatches(const PFParticlesToHits& recoParticlesToHits,
128  const HitsToMCParticles& trueHitsToParticles,
129  MCParticlesToPFParticles& matchedParticles,
130  MCParticlesToHits& matchedHits,
131  PFParticleSet& recoVeto,
132  MCParticleSet& trueVeto) const;
133 
134  /**
135  * @brief Count the number of reconstructed hits in a given wire plane
136  *
137  * @param view the wire plane ID
138  * @param hitVector the input vector of reconstructed hits
139  */
140  int CountHitsByType(const int view, const HitVector& hitVector) const;
141 
142  /**
143  * @brief Find the start and end points of the true particle in the active region of detector
144  *
145  * @param trueParticle the input true particle
146  * @param startT the true start point
147  * @param endT the true end point
148  */
149  void GetStartAndEndPoints(const art::Ptr<simb::MCParticle> trueParticle,
150  int& startT,
151  int& endT) const;
152 
153  /**
154  * @brief Find the length of the true particle trajectory through the active region of the detector
155  *
156  * @param trueParticle the input true particle
157  * @param startT the true start point
158  * @param endT the true end point
159  */
160  double GetLength(const art::Ptr<simb::MCParticle> trueParticle,
161  const int startT,
162  const int endT) const;
163 
164  TTree* m_pRecoTree; ///<
165 
166  int m_run; ///<
167  int m_event; ///<
168  int m_index; ///<
169 
170  int m_nMCParticles; ///<
171  int m_nNeutrinoPfos; ///<
172  int m_nPrimaryPfos; ///<
173  int m_nDaughterPfos; ///<
174 
175  int m_mcPdg; ///<
176  int m_mcNuPdg; ///<
177  int m_mcParentPdg; ///<
178  int m_mcPrimaryPdg; ///<
179  int m_mcIsNeutrino; ///<
180  int m_mcIsPrimary; ///<
181  int m_mcIsDecay; ///<
182  int m_mcIsCC; ///<
183 
184  int m_pfoPdg; ///<
185  int m_pfoNuPdg; ///<
186  int m_pfoParentPdg; ///<
187  int m_pfoPrimaryPdg; ///<
188  int m_pfoIsNeutrino; ///<
189  int m_pfoIsPrimary; ///<
190  int m_pfoIsStitched; ///<
191 
192  int m_pfoTrack; ///<
193  int m_pfoVertex; ///<
194  double m_pfoVtxX; ///<
195  double m_pfoVtxY; ///<
196  double m_pfoVtxZ; ///<
197  double m_pfoEndX; ///<
198  double m_pfoEndY; ///<
199  double m_pfoEndZ; ///<
200  double m_pfoDirX; ///<
201  double m_pfoDirY; ///<
202  double m_pfoDirZ; ///<
203  double m_pfoLength; ///<
204  double m_pfoStraightLength; ///<
205 
206  int m_mcVertex; ///<
207  double m_mcVtxX; ///<
208  double m_mcVtxY; ///<
209  double m_mcVtxZ; ///<
210  double m_mcEndX; ///<
211  double m_mcEndY; ///<
212  double m_mcEndZ; ///<
213  double m_mcDirX; ///<
214  double m_mcDirY; ///<
215  double m_mcDirZ; ///<
216  double m_mcEnergy; ///<
217  double m_mcLength; ///<
218  double m_mcStraightLength; ///<
219 
220  double m_completeness; ///<
221  double m_purity; ///<
222 
223  int m_nMCHits; ///<
224  int m_nPfoHits; ///<
225  int m_nMatchedHits; ///<
226 
227  int m_nMCHitsU; ///<
228  int m_nMCHitsV; ///<
229  int m_nMCHitsW; ///<
230 
231  int m_nPfoHitsU; ///<
232  int m_nPfoHitsV; ///<
233  int m_nPfoHitsW; ///<
234 
235  int m_nMatchedHitsU; ///<
236  int m_nMatchedHitsV; ///<
237  int m_nMatchedHitsW; ///<
238 
239  int
240  m_nTrueWithoutRecoHits; ///< True hits which don't belong to any reconstructed particle - "available"
241  int
242  m_nRecoWithoutTrueHits; ///< Reconstructed hits which don't belong to any true particle - "missing"
243 
244  double m_spacepointsMinX; ///<
245  double m_spacepointsMaxX; ///<
246 
252 
257 
259  bool m_printDebug; ///< switch for print statements (TODO: use message service!)
260  bool
261  m_disableRealDataCheck; ///< Whether to check if the input file contains real data before accessing MC information
262  };
263 
265 
266 } // namespace lar_pandora
267 
268 //------------------------------------------------------------------------------------------------------------------------------------------
269 // implementation follows
270 
274 #include "art_root_io/TFileDirectory.h"
275 #include "art_root_io/TFileService.h"
276 #include "fhiclcpp/ParameterSet.h"
278 
288 #include "lardataobj/RecoBase/Hit.h"
295 
296 #include <iostream>
297 
298 namespace lar_pandora {
299 
301  : art::EDAnalyzer(pset)
302  {
303  this->reconfigure(pset);
304  }
305 
306  //------------------------------------------------------------------------------------------------------------------------------------------
307 
309 
310  //------------------------------------------------------------------------------------------------------------------------------------------
311 
312  void
314  {
315  m_trackLabel = pset.get<std::string>("TrackModule", "pandoraTracks");
316  m_particleLabel = pset.get<std::string>("PFParticleModule", "pandora");
317  m_hitfinderLabel = pset.get<std::string>("HitFinderModule", "gaushit");
318  m_backtrackerLabel = pset.get<std::string>("BackTrackerModule", "gaushitTruthMatch");
319  m_geantModuleLabel = pset.get<std::string>("GeantModule", "largeant");
320 
321  m_useDaughterPFParticles = pset.get<bool>("UseDaughterPFParticles", false);
322  m_useDaughterMCParticles = pset.get<bool>("UseDaughterMCParticles", true);
323  m_addDaughterPFParticles = pset.get<bool>("AddDaughterPFParticles", true);
324  m_addDaughterMCParticles = pset.get<bool>("AddDaughterMCParticles", true);
325 
326  m_recursiveMatching = pset.get<bool>("RecursiveMatching", false);
327  m_printDebug = pset.get<bool>("PrintDebug", false);
328  m_disableRealDataCheck = pset.get<bool>("DisableRealDataCheck", false);
329  }
330 
331  //------------------------------------------------------------------------------------------------------------------------------------------
332 
333  void
335  {
336  mf::LogDebug("LArPandora") << " *** PFParticleMonitoring::beginJob() *** " << std::endl;
337 
338  //
340 
341  m_pRecoTree = tfs->make<TTree>("pandora", "LAr Reco vs True");
342  m_pRecoTree->Branch("run", &m_run, "run/I");
343  m_pRecoTree->Branch("event", &m_event, "event/I");
344  m_pRecoTree->Branch("index", &m_index, "index/I");
345  m_pRecoTree->Branch("nMCParticles", &m_nMCParticles, "nMCParticles/I");
346  m_pRecoTree->Branch("nNeutrinoPfos", &m_nNeutrinoPfos, "nNeutrinoPfos/I");
347  m_pRecoTree->Branch("nPrimaryPfos", &m_nPrimaryPfos, "nPrimaryPfos/I");
348  m_pRecoTree->Branch("nDaughterPfos", &m_nDaughterPfos, "nDaughterPfos/I");
349  m_pRecoTree->Branch("mcPdg", &m_mcPdg, "mcPdg/I");
350  m_pRecoTree->Branch("mcNuPdg", &m_mcNuPdg, "mcNuPdg/I");
351  m_pRecoTree->Branch("mcParentPdg", &m_mcParentPdg, "mcParentPdg/I");
352  m_pRecoTree->Branch("mcPrimaryPdg", &m_mcPrimaryPdg, "mcPrimaryPdg/I");
353  m_pRecoTree->Branch("mcIsNeutrino", &m_mcIsNeutrino, "mcIsNeutrino/I");
354  m_pRecoTree->Branch("mcIsPrimary", &m_mcIsPrimary, "mcIsPrimary/I");
355  m_pRecoTree->Branch("mcIsDecay", &m_mcIsDecay, "mcIsDecay/I");
356  m_pRecoTree->Branch("mcIsCC", &m_mcIsCC, "mcIsCC/I");
357  m_pRecoTree->Branch("pfoPdg", &m_pfoPdg, "pfoPdg/I");
358  m_pRecoTree->Branch("pfoNuPdg", &m_pfoNuPdg, "pfoNuPdg/I");
359  m_pRecoTree->Branch("pfoParentPdg", &m_pfoParentPdg, "pfoParentPdg/I");
360  m_pRecoTree->Branch("pfoPrimaryPdg", &m_pfoPrimaryPdg, "pfoPrimaryPdg/I");
361  m_pRecoTree->Branch("pfoIsNeutrino", &m_pfoIsNeutrino, "pfoIsNeutrino/I");
362  m_pRecoTree->Branch("pfoIsPrimary", &m_pfoIsPrimary, "pfoIsPrimary/I");
363  m_pRecoTree->Branch("pfoIsStitched", &m_pfoIsStitched, "pfoIsStitched/I");
364  m_pRecoTree->Branch("pfoTrack", &m_pfoTrack, "pfoTrack/I");
365  m_pRecoTree->Branch("pfoVertex", &m_pfoVertex, "pfoVertex/I");
366  m_pRecoTree->Branch("pfoVtxX", &m_pfoVtxX, "pfoVtxX/D");
367  m_pRecoTree->Branch("pfoVtxY", &m_pfoVtxY, "pfoVtxY/D");
368  m_pRecoTree->Branch("pfoVtxZ", &m_pfoVtxZ, "pfoVtxZ/D");
369  m_pRecoTree->Branch("pfoEndX", &m_pfoEndX, "pfoEndX/D");
370  m_pRecoTree->Branch("pfoEndY", &m_pfoEndY, "pfoEndY/D");
371  m_pRecoTree->Branch("pfoEndZ", &m_pfoEndZ, "pfoEndZ/D");
372  m_pRecoTree->Branch("pfoDirX", &m_pfoDirX, "pfoDirX/D");
373  m_pRecoTree->Branch("pfoDirY", &m_pfoDirY, "pfoDirY/D");
374  m_pRecoTree->Branch("pfoDirZ", &m_pfoDirZ, "pfoDirZ/D");
375  m_pRecoTree->Branch("pfoLength", &m_pfoLength, "pfoLength/D");
376  m_pRecoTree->Branch("pfoStraightLength", &m_pfoStraightLength, "pfoStraightLength/D");
377  m_pRecoTree->Branch("mcVertex", &m_mcVertex, "mcVertex/I");
378  m_pRecoTree->Branch("mcVtxX", &m_mcVtxX, "mcVtxX/D");
379  m_pRecoTree->Branch("mcVtxY", &m_mcVtxY, "mcVtxY/D");
380  m_pRecoTree->Branch("mcVtxZ", &m_mcVtxZ, "mcVtxZ/D");
381  m_pRecoTree->Branch("mcEndX", &m_mcEndX, "mcEndX/D");
382  m_pRecoTree->Branch("mcEndY", &m_mcEndY, "mcEndY/D");
383  m_pRecoTree->Branch("mcEndZ", &m_mcEndZ, "mcEndZ/D");
384  m_pRecoTree->Branch("mcDirX", &m_mcDirX, "mcDirX/D");
385  m_pRecoTree->Branch("mcDirY", &m_mcDirY, "mcDirY/D");
386  m_pRecoTree->Branch("mcDirZ", &m_mcDirZ, "mcDirZ/D");
387  m_pRecoTree->Branch("mcEnergy", &m_mcEnergy, "mcEnergy/D");
388  m_pRecoTree->Branch("mcLength", &m_mcLength, "mcLength/D");
389  m_pRecoTree->Branch("mcStraightLength", &m_mcStraightLength, "mcStraightLength/D");
390  m_pRecoTree->Branch("completeness", &m_completeness, "completeness/D");
391  m_pRecoTree->Branch("purity", &m_purity, "purity/D");
392  m_pRecoTree->Branch("nMCHits", &m_nMCHits, "nMCHits/I");
393  m_pRecoTree->Branch("nPfoHits", &m_nPfoHits, "nPfoHits/I");
394  m_pRecoTree->Branch("nMatchedHits", &m_nMatchedHits, "nMatchedHits/I");
395  m_pRecoTree->Branch("nMCHitsU", &m_nMCHitsU, "nMCHitsU/I");
396  m_pRecoTree->Branch("nMCHitsV", &m_nMCHitsV, "nMCHitsV/I");
397  m_pRecoTree->Branch("nMCHitsW", &m_nMCHitsW, "nMCHitsW/I");
398  m_pRecoTree->Branch("nPfoHitsU", &m_nPfoHitsU, "nPfoHitsU/I");
399  m_pRecoTree->Branch("nPfoHitsV", &m_nPfoHitsV, "nPfoHitsV/I");
400  m_pRecoTree->Branch("nPfoHitsW", &m_nPfoHitsW, "nPfoHitsW/I");
401  m_pRecoTree->Branch("nMatchedHitsU", &m_nMatchedHitsU, "nMatchedHitsU/I");
402  m_pRecoTree->Branch("nMatchedHitsV", &m_nMatchedHitsV, "nMatchedHitsV/I");
403  m_pRecoTree->Branch("nMatchedHitsW", &m_nMatchedHitsW, "nMatchedHitsW/I");
404  m_pRecoTree->Branch("nTrueWithoutRecoHits", &m_nTrueWithoutRecoHits, "nTrueWithoutRecoHits/I");
405  m_pRecoTree->Branch("nRecoWithoutTrueHits", &m_nRecoWithoutTrueHits, "nRecoWithoutTrueHits/I");
406  m_pRecoTree->Branch("spacepointsMinX", &m_spacepointsMinX, "spacepointsMinX/D");
407  m_pRecoTree->Branch("spacepointsMaxX", &m_spacepointsMaxX, "spacepointsMaxX/D");
408  }
409 
410  //------------------------------------------------------------------------------------------------------------------------------------------
411 
412  void
414  {}
415 
416  //------------------------------------------------------------------------------------------------------------------------------------------
417 
418  void
420  {
421  if (m_printDebug) std::cout << " *** PFParticleMonitoring::analyze(...) *** " << std::endl;
422 
423  m_run = evt.run();
424  m_event = evt.id().event();
425  m_index = 0;
426 
427  m_nMCParticles = 0;
428  m_nNeutrinoPfos = 0;
429  m_nPrimaryPfos = 0;
430  m_nDaughterPfos = 0;
431 
432  m_mcPdg = 0;
433  m_mcNuPdg = 0;
434  m_mcParentPdg = 0;
435  m_mcPrimaryPdg = 0;
436  m_mcIsNeutrino = 0;
437  m_mcIsPrimary = 0;
438  m_mcIsDecay = 0;
439  m_mcIsCC = 0;
440 
441  m_pfoPdg = 0;
442  m_pfoNuPdg = 0;
443  m_pfoParentPdg = 0;
444  m_pfoPrimaryPdg = 0;
445  m_pfoIsNeutrino = 0;
446  m_pfoIsPrimary = 0;
447  m_pfoIsStitched = 0;
448  m_pfoTrack = 0;
449  m_pfoVertex = 0;
450  m_pfoVtxX = 0.0;
451  m_pfoVtxY = 0.0;
452  m_pfoVtxZ = 0.0;
453  m_pfoEndX = 0.0;
454  m_pfoEndY = 0.0;
455  m_pfoEndZ = 0.0;
456  m_pfoDirX = 0.0;
457  m_pfoDirY = 0.0;
458  m_pfoDirZ = 0.0;
459  m_pfoLength = 0.0;
460  m_pfoStraightLength = 0.0;
461 
462  m_mcVertex = 0;
463  m_mcVtxX = 0.0;
464  m_mcVtxY = 0.0;
465  m_mcVtxZ = 0.0;
466  m_mcEndX = 0.0;
467  m_mcEndY = 0.0;
468  m_mcEndZ = 0.0;
469  m_mcDirX = 0.0;
470  m_mcDirY = 0.0;
471  m_mcDirZ = 0.0;
472  m_mcEnergy = 0.0;
473  m_mcLength = 0.0;
474  m_mcStraightLength = 0.0;
475 
476  m_completeness = 0.0;
477  m_purity = 0.0;
478 
479  m_nMCHits = 0;
480  m_nPfoHits = 0;
481  m_nMatchedHits = 0;
482  m_nMCHitsU = 0;
483  m_nMCHitsV = 0;
484  m_nMCHitsW = 0;
485  m_nPfoHitsU = 0;
486  m_nPfoHitsV = 0;
487  m_nPfoHitsW = 0;
488  m_nMatchedHitsU = 0;
489  m_nMatchedHitsV = 0;
490  m_nMatchedHitsW = 0;
491 
494 
495  m_spacepointsMinX = 0.0;
496  m_spacepointsMaxX = 0.0;
497 
498  if (m_printDebug) {
499  std::cout << " Run: " << m_run << std::endl;
500  std::cout << " Event: " << m_event << std::endl;
501  }
502 
503  // Collect Hits
504  // ============
505  HitVector hitVector;
507 
508  if (m_printDebug) std::cout << " Hits: " << hitVector.size() << std::endl;
509 
510  // Collect SpacePoints and SpacePoint <-> Hit Associations
511  // =======================================================
512  SpacePointVector spacePointVector;
513  SpacePointsToHits spacePointsToHits;
514  HitsToSpacePoints hitsToSpacePoints;
516  evt, m_particleLabel, spacePointVector, spacePointsToHits, hitsToSpacePoints);
517 
518  if (m_printDebug) std::cout << " SpacePoints: " << spacePointVector.size() << std::endl;
519 
520  // Collect Tracks and PFParticle <-> Track Associations
521  // ====================================================
522  TrackVector recoTrackVector;
523  PFParticlesToTracks recoParticlesToTracks;
524  LArPandoraHelper::CollectTracks(evt, m_trackLabel, recoTrackVector, recoParticlesToTracks);
525 
526  if (m_printDebug) std::cout << " Tracks: " << recoTrackVector.size() << std::endl;
527 
528  // Collect TOs and PFParticle <-> T0 Associations
529  // ==============================================
530  T0Vector t0Vector;
531  PFParticlesToT0s particlesToT0s;
532  LArPandoraHelper::CollectT0s(evt, m_particleLabel, t0Vector, particlesToT0s);
533 
534  // Collect Vertices and PFParticle <-> Vertex Associations
535  // =======================================================
536  VertexVector recoVertexVector;
537  PFParticlesToVertices recoParticlesToVertices;
539  evt, m_particleLabel, recoVertexVector, recoParticlesToVertices);
540 
541  if (m_printDebug) std::cout << " Vertices: " << recoVertexVector.size() << std::endl;
542 
543  // Collect PFParticles and match Reco Particles to Hits
544  // ====================================================
545  PFParticleVector recoParticleVector;
546  PFParticleVector recoNeutrinoVector;
547  PFParticlesToHits recoParticlesToHits;
548  HitsToPFParticles recoHitsToParticles;
549 
550  LArPandoraHelper::CollectPFParticles(evt, m_particleLabel, recoParticleVector);
551  LArPandoraHelper::SelectNeutrinoPFParticles(recoParticleVector, recoNeutrinoVector);
553  evt,
555  recoParticlesToHits,
556  recoHitsToParticles,
560 
561  if (m_printDebug) {
562  std::cout << " RecoNeutrinos: " << recoNeutrinoVector.size() << std::endl;
563  std::cout << " RecoParticles: " << recoParticleVector.size() << std::endl;
564  }
565 
566  // Collect MCParticles and match True Particles to Hits
567  // ====================================================
568  MCParticleVector trueParticleVector;
569  MCTruthToMCParticles truthToParticles;
570  MCParticlesToMCTruth particlesToTruth;
571  MCParticlesToHits trueParticlesToHits;
572  HitsToMCParticles trueHitsToParticles;
573 
574  if (m_disableRealDataCheck || !evt.isRealData()) {
577  evt, m_geantModuleLabel, truthToParticles, particlesToTruth);
578 
580  evt,
582  hitVector,
583  trueParticlesToHits,
584  trueHitsToParticles,
586  LArPandoraHelper::kUseDaughters) :
587  LArPandoraHelper::kIgnoreDaughters));
588 
589  if (trueHitsToParticles.empty()) {
590  if (m_backtrackerLabel.empty())
591  throw cet::exception("LArPandora") << " PFParticleMonitoring::analyze - no sim channels "
592  "found, backtracker module must be set in FHiCL "
593  << std::endl;
594 
596  evt,
600  trueParticlesToHits,
601  trueHitsToParticles,
603  LArPandoraHelper::kUseDaughters) :
604  LArPandoraHelper::kIgnoreDaughters));
605  }
606  }
607 
608  if (m_printDebug) {
609  std::cout << " TrueParticles: " << particlesToTruth.size() << std::endl;
610  std::cout << " TrueEvents: " << truthToParticles.size() << std::endl;
611  std::cout << " MatchedParticles: " << trueParticlesToHits.size() << std::endl;
612  }
613 
614  if (trueParticlesToHits.empty()) {
615  m_pRecoTree->Fill();
616  return;
617  }
618 
619  // Build Reco and True Particle Maps (for Parent/Daughter Navigation)
620  // =================================================================
621  MCParticleMap trueParticleMap;
622  PFParticleMap recoParticleMap;
623 
624  LArPandoraHelper::BuildMCParticleMap(trueParticleVector, trueParticleMap);
625  LArPandoraHelper::BuildPFParticleMap(recoParticleVector, recoParticleMap);
626 
627  m_nMCParticles = trueParticlesToHits.size();
628  m_nNeutrinoPfos = 0;
629  m_nPrimaryPfos = 0;
630  m_nDaughterPfos = 0;
631 
632  // Count reconstructed particles
633  for (PFParticleVector::const_iterator iter = recoParticleVector.begin(),
634  iterEnd = recoParticleVector.end();
635  iter != iterEnd;
636  ++iter) {
637  const art::Ptr<recob::PFParticle> recoParticle = *iter;
638 
639  if (LArPandoraHelper::IsNeutrino(recoParticle)) { m_nNeutrinoPfos++; }
640  else if (LArPandoraHelper::IsFinalState(recoParticleMap, recoParticle)) {
641  m_nPrimaryPfos++;
642  }
643  else {
644  m_nDaughterPfos++;
645  }
646  }
647 
648  // Match Reco Neutrinos to True Neutrinos
649  // ======================================
650  PFParticlesToHits recoNeutrinosToHits;
651  HitsToPFParticles recoHitsToNeutrinos;
652  HitsToMCTruth trueHitsToNeutrinos;
653  MCTruthToHits trueNeutrinosToHits;
655  recoParticleMap, recoParticlesToHits, recoNeutrinosToHits, recoHitsToNeutrinos);
657  truthToParticles, trueParticlesToHits, trueNeutrinosToHits, trueHitsToNeutrinos);
658 
659  MCTruthToPFParticles matchedNeutrinos;
660  MCTruthToHits matchedNeutrinoHits;
661  this->GetRecoToTrueMatches(
662  recoNeutrinosToHits, trueHitsToNeutrinos, matchedNeutrinos, matchedNeutrinoHits);
663 
664  for (MCTruthToHits::const_iterator iter = trueNeutrinosToHits.begin(),
665  iterEnd = trueNeutrinosToHits.end();
666  iter != iterEnd;
667  ++iter) {
668  const art::Ptr<simb::MCTruth> trueEvent = iter->first;
669  const HitVector& trueHitVector = iter->second;
670 
671  if (trueHitVector.empty()) continue;
672 
673  if (!trueEvent->NeutrinoSet()) continue;
674 
675  const simb::MCNeutrino trueNeutrino(trueEvent->GetNeutrino());
676  const simb::MCParticle trueParticle(trueNeutrino.Nu());
677 
678  m_mcIsCC = ((simb::kCC == trueNeutrino.CCNC()) ? 1 : 0);
679  m_mcPdg = trueParticle.PdgCode();
680  m_mcNuPdg = m_mcPdg;
681  m_mcParentPdg = 0;
682  m_mcPrimaryPdg = 0;
683  m_mcIsNeutrino = 1;
684  m_mcIsPrimary = 0;
685  m_mcIsDecay = 0;
686 
687  m_mcVertex = 1;
688  m_mcVtxX = trueParticle.Vx();
689  m_mcVtxY = trueParticle.Vy();
690  m_mcVtxZ = trueParticle.Vz();
691  m_mcEndX = m_mcVtxX;
692  m_mcEndY = m_mcVtxY;
693  m_mcEndZ = m_mcVtxZ;
694  m_mcDirX = trueParticle.Px() / trueParticle.P();
695  m_mcDirY = trueParticle.Py() / trueParticle.P();
696  m_mcDirZ = trueParticle.Pz() / trueParticle.P();
697  m_mcEnergy = trueParticle.E();
698  m_mcLength = 0.0;
699  m_mcStraightLength = 0.0;
700 
701  m_nMCHits = trueHitVector.size();
702  m_nMCHitsU = this->CountHitsByType(geo::kU, trueHitVector);
703  m_nMCHitsV = this->CountHitsByType(geo::kV, trueHitVector);
704  m_nMCHitsW = this->CountHitsByType(geo::kW, trueHitVector);
705 
706  m_pfoPdg = 0;
707  m_pfoNuPdg = 0;
708  m_pfoParentPdg = 0;
709  m_pfoPrimaryPdg = 0;
710  m_pfoIsNeutrino = 0;
711  m_pfoIsPrimary = 0;
712  m_pfoIsStitched = 0;
713  m_pfoTrack = 0;
714  m_pfoVertex = 0;
715  m_pfoVtxX = 0.0;
716  m_pfoVtxY = 0.0;
717  m_pfoVtxZ = 0.0;
718  m_pfoEndX = 0.0;
719  m_pfoEndY = 0.0;
720  m_pfoEndZ = 0.0;
721  m_pfoDirX = 0.0;
722  m_pfoDirY = 0.0;
723  m_pfoDirZ = 0.0;
724  m_pfoLength = 0.0;
725  m_pfoStraightLength = 0.0;
726 
727  m_nPfoHits = 0;
728  m_nPfoHitsU = 0;
729  m_nPfoHitsV = 0;
730  m_nPfoHitsW = 0;
731 
732  m_nMatchedHits = 0;
733  m_nMatchedHitsU = 0;
734  m_nMatchedHitsV = 0;
735  m_nMatchedHitsW = 0;
736 
739 
740  m_spacepointsMinX = 0.0;
741  m_spacepointsMaxX = 0.0;
742 
743  m_completeness = 0.0;
744  m_purity = 0.0;
745 
746  for (HitVector::const_iterator hIter1 = trueHitVector.begin(),
747  hIterEnd1 = trueHitVector.end();
748  hIter1 != hIterEnd1;
749  ++hIter1) {
750  if (recoHitsToNeutrinos.find(*hIter1) == recoHitsToNeutrinos.end())
752  }
753 
754  MCTruthToPFParticles::const_iterator pIter1 = matchedNeutrinos.find(trueEvent);
755  if (matchedNeutrinos.end() != pIter1) {
756  const art::Ptr<recob::PFParticle> recoParticle = pIter1->second;
757  m_pfoPdg = recoParticle->PdgCode();
760  m_pfoPrimaryPdg = 0;
761  m_pfoIsNeutrino = 1;
762  m_pfoIsPrimary = 0;
763 
764  if (!LArPandoraHelper::IsNeutrino(recoParticle))
765  std::cout << " Warning: Found neutrino with an invalid PDG code " << std::endl;
766 
767  PFParticlesToHits::const_iterator pIter2 = recoNeutrinosToHits.find(recoParticle);
768  if (recoParticlesToHits.end() != pIter2) {
769  const HitVector& recoHitVector = pIter2->second;
770 
771  for (HitVector::const_iterator hIter2 = recoHitVector.begin(),
772  hIterEnd2 = recoHitVector.end();
773  hIter2 != hIterEnd2;
774  ++hIter2) {
775  if (trueHitsToNeutrinos.find(*hIter2) == trueHitsToNeutrinos.end())
777  }
778 
779  MCTruthToHits::const_iterator pIter3 = matchedNeutrinoHits.find(trueEvent);
780  if (matchedNeutrinoHits.end() != pIter3) {
781  const HitVector& matchedHitVector = pIter3->second;
782 
783  m_nPfoHits = recoHitVector.size();
784  m_nPfoHitsU = this->CountHitsByType(geo::kU, recoHitVector);
785  m_nPfoHitsV = this->CountHitsByType(geo::kV, recoHitVector);
786  m_nPfoHitsW = this->CountHitsByType(geo::kW, recoHitVector);
787 
788  m_nMatchedHits = matchedHitVector.size();
789  m_nMatchedHitsU = this->CountHitsByType(geo::kU, matchedHitVector);
790  m_nMatchedHitsV = this->CountHitsByType(geo::kV, matchedHitVector);
791  m_nMatchedHitsW = this->CountHitsByType(geo::kW, matchedHitVector);
792 
794  recoParticlesToVertices.find(recoParticle);
795  if (recoParticlesToVertices.end() != pIter4) {
796  const VertexVector& vertexVector = pIter4->second;
797  if (!vertexVector.empty()) {
798  if (vertexVector.size() != 1 && m_printDebug)
799  std::cout << " Warning: Found particle with more than one associated vertex "
800  << std::endl;
801 
802  const art::Ptr<recob::Vertex> recoVertex = *(vertexVector.begin());
803  double xyz[3] = {0.0, 0.0, 0.0};
804  recoVertex->XYZ(xyz);
805 
806  m_pfoVertex = 1;
807  m_pfoVtxX = xyz[0];
808  m_pfoVtxY = xyz[1];
809  m_pfoVtxZ = xyz[2];
810  }
811  }
812  }
813  }
814  }
815 
816  m_purity =
817  ((m_nPfoHits == 0) ? 0.0 :
818  static_cast<double>(m_nMatchedHits) / static_cast<double>(m_nPfoHits));
820  ((m_nPfoHits == 0) ? 0.0 :
821  static_cast<double>(m_nMatchedHits) / static_cast<double>(m_nMCHits));
822 
823  if (m_printDebug)
824  std::cout << " MCNeutrino [" << m_index << "]"
825  << " trueNu=" << m_mcNuPdg << ", truePdg=" << m_mcPdg
826  << ", recoNu=" << m_pfoNuPdg << ", recoPdg=" << m_pfoPdg
827  << ", mcHits=" << m_nMCHits << ", pfoHits=" << m_nPfoHits
828  << ", matchedHits=" << m_nMatchedHits
829  << ", availableHits=" << m_nTrueWithoutRecoHits << std::endl;
830 
831  m_pRecoTree->Fill();
832  ++m_index; // Increment index number
833  }
834 
835  // Match Reco Particles to True Particles
836  // ======================================
837  MCParticlesToPFParticles matchedParticles;
838  MCParticlesToHits matchedParticleHits;
839  this->GetRecoToTrueMatches(
840  recoParticlesToHits, trueHitsToParticles, matchedParticles, matchedParticleHits);
841 
842  // Compare true and reconstructed particles
843  for (MCParticlesToHits::const_iterator iter = trueParticlesToHits.begin(),
844  iterEnd = trueParticlesToHits.end();
845  iter != iterEnd;
846  ++iter) {
847  const art::Ptr<simb::MCParticle> trueParticle = iter->first;
848  const HitVector& trueHitVector = iter->second;
849 
850  if (trueHitVector.empty()) continue;
851 
852  m_mcPdg = trueParticle->PdgCode();
853  m_mcNuPdg = 0;
854  m_mcParentPdg = 0;
855  m_mcPrimaryPdg = 0;
856  m_mcIsNeutrino = 0;
857  m_mcIsPrimary = 0;
858  m_mcIsDecay = 0;
859  m_mcIsCC = 0;
860 
861  m_pfoPdg = 0;
862  m_pfoNuPdg = 0;
863  m_pfoParentPdg = 0;
864  m_pfoPrimaryPdg = 0;
865  m_pfoIsNeutrino = 0;
866  m_pfoIsPrimary = 0;
867  m_pfoIsStitched = 0;
868  m_pfoTrack = 0;
869  m_pfoVertex = 0;
870  m_pfoVtxX = 0.0;
871  m_pfoVtxY = 0.0;
872  m_pfoVtxZ = 0.0;
873  m_pfoEndX = 0.0;
874  m_pfoEndY = 0.0;
875  m_pfoEndZ = 0.0;
876  m_pfoDirX = 0.0;
877  m_pfoDirY = 0.0;
878  m_pfoDirZ = 0.0;
879  m_pfoLength = 0.0;
880  m_pfoStraightLength = 0.0;
881 
882  m_mcVertex = 0;
883  m_mcVtxX = 0.0;
884  m_mcVtxY = 0.0;
885  m_mcVtxZ = 0.0;
886  m_mcEndX = 0.0;
887  m_mcEndY = 0.0;
888  m_mcEndZ = 0.0;
889  m_mcDirX = 0.0;
890  m_mcDirY = 0.0;
891  m_mcDirZ = 0.0;
892  m_mcEnergy = 0.0;
893  m_mcLength = 0.0;
894  m_mcStraightLength = 0.0;
895 
896  m_completeness = 0.0;
897  m_purity = 0.0;
898 
899  m_nMCHits = 0;
900  m_nMCHitsU = 0;
901  m_nMCHitsV = 0;
902  m_nMCHitsW = 0;
903 
904  m_nPfoHits = 0;
905  m_nPfoHitsU = 0;
906  m_nPfoHitsV = 0;
907  m_nPfoHitsW = 0;
908 
909  m_nMatchedHits = 0;
910  m_nMatchedHitsU = 0;
911  m_nMatchedHitsV = 0;
912  m_nMatchedHitsW = 0;
913 
916 
917  m_spacepointsMinX = 0.0;
918  m_spacepointsMaxX = 0.0;
919 
920  // Set true properties
921  try {
922  int startT(-1);
923  int endT(-1);
924  this->GetStartAndEndPoints(trueParticle, startT, endT);
925 
926  // vertex and end positions
927  m_mcVertex = 1;
928  m_mcVtxX = trueParticle->Vx(startT);
929  m_mcVtxY = trueParticle->Vy(startT);
930  m_mcVtxZ = trueParticle->Vz(startT);
931  m_mcEndX = trueParticle->Vx(endT);
932  m_mcEndY = trueParticle->Vy(endT);
933  m_mcEndZ = trueParticle->Vz(endT);
934 
935  const double dx(m_mcEndX - m_mcVtxX);
936  const double dy(m_mcEndY - m_mcVtxY);
937  const double dz(m_mcEndZ - m_mcVtxZ);
938 
939  m_mcStraightLength = std::sqrt(dx * dx + dy * dy + dz * dz);
940  m_mcLength = this->GetLength(trueParticle, startT, endT);
941 
942  // energy and momentum
943  const double Ptot(trueParticle->P(startT));
944 
945  if (Ptot > 0.0) {
946  m_mcDirX = trueParticle->Px(startT) / Ptot;
947  m_mcDirY = trueParticle->Py(startT) / Ptot;
948  m_mcDirZ = trueParticle->Pz(startT) / Ptot;
949  m_mcEnergy = trueParticle->E(startT);
950  }
951  }
952  catch (cet::exception& e) {
953  }
954 
955  // Get the true parent neutrino
956  MCParticlesToMCTruth::const_iterator nuIter = particlesToTruth.find(trueParticle);
957  if (particlesToTruth.end() == nuIter)
958  throw cet::exception("LArPandora") << " PFParticleMonitoring::analyze --- Found a true "
959  "particle without any ancestry information ";
960 
961  const art::Ptr<simb::MCTruth> trueEvent = nuIter->second;
962 
963  if (trueEvent->NeutrinoSet()) {
964  const simb::MCNeutrino neutrino(trueEvent->GetNeutrino());
965  m_mcNuPdg = neutrino.Nu().PdgCode();
966  m_mcIsCC = ((simb::kCC == neutrino.CCNC()) ? 1 : 0);
967  }
968 
969  // Get the true 'parent' and 'primary' particles
970  try {
971  const art::Ptr<simb::MCParticle> parentParticle(
972  LArPandoraHelper::GetParentMCParticle(trueParticleMap, trueParticle));
973  const art::Ptr<simb::MCParticle> primaryParticle(
974  LArPandoraHelper::GetFinalStateMCParticle(trueParticleMap, trueParticle));
975  m_mcParentPdg = ((parentParticle != trueParticle) ? parentParticle->PdgCode() : 0);
976  m_mcPrimaryPdg = primaryParticle->PdgCode();
977  m_mcIsPrimary = (primaryParticle == trueParticle);
978  m_mcIsDecay = ("Decay" == trueParticle->Process());
979  }
980  catch (cet::exception& e) {
981  }
982 
983  // Find min and max X positions of space points
984  bool foundSpacePoints(false);
985 
986  for (HitVector::const_iterator hIter1 = trueHitVector.begin(),
987  hIterEnd1 = trueHitVector.end();
988  hIter1 != hIterEnd1;
989  ++hIter1) {
990  const art::Ptr<recob::Hit> hit = *hIter1;
991 
992  HitsToSpacePoints::const_iterator hIter2 = hitsToSpacePoints.find(hit);
993  if (hitsToSpacePoints.end() == hIter2) continue;
994 
995  const art::Ptr<recob::SpacePoint> spacepoint = hIter2->second;
996  const double X(spacepoint->XYZ()[0]);
997 
998  if (!foundSpacePoints) {
1000  m_spacepointsMaxX = X;
1001  foundSpacePoints = true;
1002  }
1003  else {
1006  }
1007  }
1008 
1009  // Count number of available hits
1010  for (HitVector::const_iterator hIter1 = trueHitVector.begin(),
1011  hIterEnd1 = trueHitVector.end();
1012  hIter1 != hIterEnd1;
1013  ++hIter1) {
1014  if (recoHitsToParticles.find(*hIter1) == recoHitsToParticles.end())
1016  }
1017 
1018  // Match true and reconstructed hits
1019  m_nMCHits = trueHitVector.size();
1020  m_nMCHitsU = this->CountHitsByType(geo::kU, trueHitVector);
1021  m_nMCHitsV = this->CountHitsByType(geo::kV, trueHitVector);
1022  m_nMCHitsW = this->CountHitsByType(geo::kW, trueHitVector);
1023 
1024  MCParticlesToPFParticles::const_iterator pIter1 = matchedParticles.find(trueParticle);
1025  if (matchedParticles.end() != pIter1) {
1026  const art::Ptr<recob::PFParticle> recoParticle = pIter1->second;
1027  m_pfoPdg = recoParticle->PdgCode();
1028  m_pfoNuPdg = LArPandoraHelper::GetParentNeutrino(recoParticleMap, recoParticle);
1029  m_pfoIsPrimary = LArPandoraHelper::IsFinalState(recoParticleMap, recoParticle);
1030 
1031  const art::Ptr<recob::PFParticle> parentParticle =
1032  LArPandoraHelper::GetParentPFParticle(recoParticleMap, recoParticle);
1033  m_pfoParentPdg = parentParticle->PdgCode();
1034 
1035  const art::Ptr<recob::PFParticle> primaryParticle =
1036  LArPandoraHelper::GetFinalStatePFParticle(recoParticleMap, recoParticle);
1037  m_pfoPrimaryPdg = primaryParticle->PdgCode();
1038 
1039  PFParticlesToHits::const_iterator pIter2 = recoParticlesToHits.find(recoParticle);
1040  if (recoParticlesToHits.end() == pIter2)
1041  throw cet::exception("LArPandora")
1042  << " PFParticleMonitoring::analyze --- Found a reco particle without any hits ";
1043 
1044  const HitVector& recoHitVector = pIter2->second;
1045 
1046  for (HitVector::const_iterator hIter2 = recoHitVector.begin(),
1047  hIterEnd2 = recoHitVector.end();
1048  hIter2 != hIterEnd2;
1049  ++hIter2) {
1050  if (trueHitsToParticles.find(*hIter2) == trueHitsToParticles.end())
1052  }
1053 
1054  MCParticlesToHits::const_iterator pIter3 = matchedParticleHits.find(trueParticle);
1055  if (matchedParticleHits.end() == pIter3)
1056  throw cet::exception("LArPandora") << " PFParticleMonitoring::analyze --- Found a "
1057  "matched true particle without matched hits ";
1058 
1059  const HitVector& matchedHitVector = pIter3->second;
1060 
1061  m_nPfoHits = recoHitVector.size();
1062  m_nPfoHitsU = this->CountHitsByType(geo::kU, recoHitVector);
1063  m_nPfoHitsV = this->CountHitsByType(geo::kV, recoHitVector);
1064  m_nPfoHitsW = this->CountHitsByType(geo::kW, recoHitVector);
1065 
1066  m_nMatchedHits = matchedHitVector.size();
1067  m_nMatchedHitsU = this->CountHitsByType(geo::kU, matchedHitVector);
1068  m_nMatchedHitsV = this->CountHitsByType(geo::kV, matchedHitVector);
1069  m_nMatchedHitsW = this->CountHitsByType(geo::kW, matchedHitVector);
1070 
1071  PFParticlesToVertices::const_iterator pIter4 = recoParticlesToVertices.find(recoParticle);
1072  if (recoParticlesToVertices.end() != pIter4) {
1073  const VertexVector& vertexVector = pIter4->second;
1074  if (!vertexVector.empty()) {
1075  if (vertexVector.size() != 1 && m_printDebug)
1076  std::cout << " Warning: Found particle with more than one associated vertex "
1077  << std::endl;
1078 
1079  const art::Ptr<recob::Vertex> recoVertex = *(vertexVector.begin());
1080  double xyz[3] = {0.0, 0.0, 0.0};
1081  recoVertex->XYZ(xyz);
1082 
1083  m_pfoVertex = 1;
1084  m_pfoVtxX = xyz[0];
1085  m_pfoVtxY = xyz[1];
1086  m_pfoVtxZ = xyz[2];
1087  }
1088  }
1089 
1090  PFParticlesToTracks::const_iterator pIter5 = recoParticlesToTracks.find(recoParticle);
1091  if (recoParticlesToTracks.end() != pIter5) {
1092  const TrackVector& trackVector = pIter5->second;
1093  if (!trackVector.empty()) {
1094  if (trackVector.size() != 1 && m_printDebug)
1095  std::cout << " Warning: Found particle with more than one associated track "
1096  << std::endl;
1097 
1098  const art::Ptr<recob::Track> recoTrack = *(trackVector.begin());
1099  const auto& vtxPosition = recoTrack->Vertex();
1100  const auto& endPosition = recoTrack->End();
1101  const auto& vtxDirection = recoTrack->VertexDirection();
1102 
1103  m_pfoTrack = 1;
1104  m_pfoVtxX = vtxPosition.x();
1105  m_pfoVtxY = vtxPosition.y();
1106  m_pfoVtxZ = vtxPosition.z();
1107  m_pfoEndX = endPosition.x();
1108  m_pfoEndY = endPosition.y();
1109  m_pfoEndZ = endPosition.z();
1110  m_pfoDirX = vtxDirection.x();
1111  m_pfoDirY = vtxDirection.y();
1112  m_pfoDirZ = vtxDirection.z();
1113  m_pfoStraightLength = (endPosition - vtxPosition).R();
1114  m_pfoLength = recoTrack->Length();
1115  }
1116  }
1117 
1118  m_pfoIsStitched = (particlesToT0s.end() != particlesToT0s.find(recoParticle));
1119  }
1120 
1121  m_purity =
1122  ((m_nPfoHits == 0) ? 0.0 :
1123  static_cast<double>(m_nMatchedHits) / static_cast<double>(m_nPfoHits));
1124  m_completeness =
1125  ((m_nPfoHits == 0) ? 0.0 :
1126  static_cast<double>(m_nMatchedHits) / static_cast<double>(m_nMCHits));
1127 
1128  if (m_printDebug)
1129  std::cout << " MCParticle [" << m_index << "]"
1130  << " trueNu=" << m_mcNuPdg << ", truePdg=" << m_mcPdg
1131  << ", recoNu=" << m_pfoNuPdg << ", recoPdg=" << m_pfoPdg
1132  << ", mcHits=" << m_nMCHits << ", pfoHits=" << m_nPfoHits
1133  << ", matchedHits=" << m_nMatchedHits
1134  << ", availableHits=" << m_nTrueWithoutRecoHits << std::endl;
1135 
1136  m_pRecoTree->Fill();
1137  ++m_index; // Increment index number
1138  }
1139  }
1140 
1141  //------------------------------------------------------------------------------------------------------------------------------------------
1142 
1143  void
1145  const MCParticlesToHits& trueParticlesToHits,
1146  MCTruthToHits& trueNeutrinosToHits,
1147  HitsToMCTruth& trueHitsToNeutrinos) const
1148  {
1149  for (MCTruthToMCParticles::const_iterator iter1 = truthToParticles.begin(),
1150  iterEnd1 = truthToParticles.end();
1151  iter1 != iterEnd1;
1152  ++iter1) {
1153  const art::Ptr<simb::MCTruth> trueNeutrino = iter1->first;
1154  const MCParticleVector& trueParticleVector = iter1->second;
1155 
1156  for (MCParticleVector::const_iterator iter2 = trueParticleVector.begin(),
1157  iterEnd2 = trueParticleVector.end();
1158  iter2 != iterEnd2;
1159  ++iter2) {
1160  const MCParticlesToHits::const_iterator iter3 = trueParticlesToHits.find(*iter2);
1161  if (trueParticlesToHits.end() == iter3) continue;
1162 
1163  const HitVector& hitVector = iter3->second;
1164 
1165  for (HitVector::const_iterator iter4 = hitVector.begin(), iterEnd4 = hitVector.end();
1166  iter4 != iterEnd4;
1167  ++iter4) {
1168  const art::Ptr<recob::Hit> hit = *iter4;
1169  trueHitsToNeutrinos[hit] = trueNeutrino;
1170  trueNeutrinosToHits[trueNeutrino].push_back(hit);
1171  }
1172  }
1173  }
1174  }
1175 
1176  //------------------------------------------------------------------------------------------------------------------------------------------
1177 
1178  void
1180  const PFParticlesToHits& recoParticlesToHits,
1181  PFParticlesToHits& recoNeutrinosToHits,
1182  HitsToPFParticles& recoHitsToNeutrinos) const
1183  {
1184  for (PFParticleMap::const_iterator iter1 = recoParticleMap.begin(),
1185  iterEnd1 = recoParticleMap.end();
1186  iter1 != iterEnd1;
1187  ++iter1) {
1188  const art::Ptr<recob::PFParticle> recoParticle = iter1->second;
1189  const art::Ptr<recob::PFParticle> recoNeutrino =
1190  LArPandoraHelper::GetParentPFParticle(recoParticleMap, recoParticle);
1191 
1192  if (!LArPandoraHelper::IsNeutrino(recoNeutrino)) continue;
1193 
1194  const PFParticlesToHits::const_iterator iter2 = recoParticlesToHits.find(recoParticle);
1195  if (recoParticlesToHits.end() == iter2) continue;
1196 
1197  const HitVector& hitVector = iter2->second;
1198 
1199  for (HitVector::const_iterator iter3 = hitVector.begin(), iterEnd3 = hitVector.end();
1200  iter3 != iterEnd3;
1201  ++iter3) {
1202  const art::Ptr<recob::Hit> hit = *iter3;
1203  recoHitsToNeutrinos[hit] = recoNeutrino;
1204  recoNeutrinosToHits[recoNeutrino].push_back(hit);
1205  }
1206  }
1207  }
1208 
1209  //------------------------------------------------------------------------------------------------------------------------------------------
1210 
1211  void
1213  const HitsToMCTruth& trueHitsToNeutrinos,
1214  MCTruthToPFParticles& matchedNeutrinos,
1215  MCTruthToHits& matchedNeutrinoHits) const
1216  {
1217  PFParticleSet recoVeto;
1218  MCTruthSet trueVeto;
1219 
1220  this->GetRecoToTrueMatches(recoNeutrinosToHits,
1221  trueHitsToNeutrinos,
1222  matchedNeutrinos,
1223  matchedNeutrinoHits,
1224  recoVeto,
1225  trueVeto);
1226  }
1227 
1228  //------------------------------------------------------------------------------------------------------------------------------------------
1229 
1230  void
1232  const HitsToMCTruth& trueHitsToNeutrinos,
1233  MCTruthToPFParticles& matchedNeutrinos,
1234  MCTruthToHits& matchedNeutrinoHits,
1235  PFParticleSet& vetoReco,
1236  MCTruthSet& vetoTrue) const
1237  {
1238  bool foundMatches(false);
1239 
1240  for (PFParticlesToHits::const_iterator iter1 = recoNeutrinosToHits.begin(),
1241  iterEnd1 = recoNeutrinosToHits.end();
1242  iter1 != iterEnd1;
1243  ++iter1) {
1244  const art::Ptr<recob::PFParticle> recoNeutrino = iter1->first;
1245  if (vetoReco.count(recoNeutrino) > 0) continue;
1246 
1247  const HitVector& hitVector = iter1->second;
1248 
1249  MCTruthToHits truthContributionMap;
1250 
1251  for (HitVector::const_iterator iter2 = hitVector.begin(), iterEnd2 = hitVector.end();
1252  iter2 != iterEnd2;
1253  ++iter2) {
1254  const art::Ptr<recob::Hit> hit = *iter2;
1255 
1256  HitsToMCTruth::const_iterator iter3 = trueHitsToNeutrinos.find(hit);
1257  if (trueHitsToNeutrinos.end() == iter3) continue;
1258 
1259  const art::Ptr<simb::MCTruth> trueNeutrino = iter3->second;
1260  if (vetoTrue.count(trueNeutrino) > 0) continue;
1261 
1262  truthContributionMap[trueNeutrino].push_back(hit);
1263  }
1264 
1265  MCTruthToHits::const_iterator mIter = truthContributionMap.end();
1266 
1267  for (MCTruthToHits::const_iterator iter4 = truthContributionMap.begin(),
1268  iterEnd4 = truthContributionMap.end();
1269  iter4 != iterEnd4;
1270  ++iter4) {
1271  if ((truthContributionMap.end() == mIter) ||
1272  (iter4->second.size() > mIter->second.size())) {
1273  mIter = iter4;
1274  }
1275  }
1276 
1277  if (truthContributionMap.end() != mIter) {
1278  const art::Ptr<simb::MCTruth> trueNeutrino = mIter->first;
1279 
1280  MCTruthToHits::const_iterator iter5 = matchedNeutrinoHits.find(trueNeutrino);
1281 
1282  if ((matchedNeutrinoHits.end() == iter5) || (mIter->second.size() > iter5->second.size())) {
1283  matchedNeutrinos[trueNeutrino] = recoNeutrino;
1284  matchedNeutrinoHits[trueNeutrino] = mIter->second;
1285  foundMatches = true;
1286  }
1287  }
1288  }
1289 
1290  if (!foundMatches) return;
1291 
1292  for (MCTruthToPFParticles::const_iterator pIter = matchedNeutrinos.begin(),
1293  pIterEnd = matchedNeutrinos.end();
1294  pIter != pIterEnd;
1295  ++pIter) {
1296  vetoTrue.insert(pIter->first);
1297  vetoReco.insert(pIter->second);
1298  }
1299 
1300  if (m_recursiveMatching)
1301  this->GetRecoToTrueMatches(recoNeutrinosToHits,
1302  trueHitsToNeutrinos,
1303  matchedNeutrinos,
1304  matchedNeutrinoHits,
1305  vetoReco,
1306  vetoTrue);
1307  }
1308 
1309  //------------------------------------------------------------------------------------------------------------------------------------------
1310 
1311  void
1313  const HitsToMCParticles& trueHitsToParticles,
1314  MCParticlesToPFParticles& matchedParticles,
1315  MCParticlesToHits& matchedHits) const
1316  {
1317  PFParticleSet recoVeto;
1318  MCParticleSet trueVeto;
1319 
1320  this->GetRecoToTrueMatches(
1321  recoParticlesToHits, trueHitsToParticles, matchedParticles, matchedHits, recoVeto, trueVeto);
1322  }
1323 
1324  //------------------------------------------------------------------------------------------------------------------------------------------
1325 
1326  void
1328  const HitsToMCParticles& trueHitsToParticles,
1329  MCParticlesToPFParticles& matchedParticles,
1330  MCParticlesToHits& matchedHits,
1331  PFParticleSet& vetoReco,
1332  MCParticleSet& vetoTrue) const
1333  {
1334  bool foundMatches(false);
1335 
1336  for (PFParticlesToHits::const_iterator iter1 = recoParticlesToHits.begin(),
1337  iterEnd1 = recoParticlesToHits.end();
1338  iter1 != iterEnd1;
1339  ++iter1) {
1340  const art::Ptr<recob::PFParticle> recoParticle = iter1->first;
1341  if (vetoReco.count(recoParticle) > 0) continue;
1342 
1343  const HitVector& hitVector = iter1->second;
1344 
1345  MCParticlesToHits truthContributionMap;
1346 
1347  for (HitVector::const_iterator iter2 = hitVector.begin(), iterEnd2 = hitVector.end();
1348  iter2 != iterEnd2;
1349  ++iter2) {
1350  const art::Ptr<recob::Hit> hit = *iter2;
1351 
1352  HitsToMCParticles::const_iterator iter3 = trueHitsToParticles.find(hit);
1353  if (trueHitsToParticles.end() == iter3) continue;
1354 
1355  const art::Ptr<simb::MCParticle> trueParticle = iter3->second;
1356  if (vetoTrue.count(trueParticle) > 0) continue;
1357 
1358  truthContributionMap[trueParticle].push_back(hit);
1359  }
1360 
1361  MCParticlesToHits::const_iterator mIter = truthContributionMap.end();
1362 
1363  for (MCParticlesToHits::const_iterator iter4 = truthContributionMap.begin(),
1364  iterEnd4 = truthContributionMap.end();
1365  iter4 != iterEnd4;
1366  ++iter4) {
1367  if ((truthContributionMap.end() == mIter) ||
1368  (iter4->second.size() > mIter->second.size())) {
1369  mIter = iter4;
1370  }
1371  }
1372 
1373  if (truthContributionMap.end() != mIter) {
1374  const art::Ptr<simb::MCParticle> trueParticle = mIter->first;
1375 
1376  MCParticlesToHits::const_iterator iter5 = matchedHits.find(trueParticle);
1377 
1378  if ((matchedHits.end() == iter5) || (mIter->second.size() > iter5->second.size())) {
1379  matchedParticles[trueParticle] = recoParticle;
1380  matchedHits[trueParticle] = mIter->second;
1381  foundMatches = true;
1382  }
1383  }
1384  }
1385 
1386  if (!foundMatches) return;
1387 
1388  for (MCParticlesToPFParticles::const_iterator pIter = matchedParticles.begin(),
1389  pIterEnd = matchedParticles.end();
1390  pIter != pIterEnd;
1391  ++pIter) {
1392  vetoTrue.insert(pIter->first);
1393  vetoReco.insert(pIter->second);
1394  }
1395 
1396  if (m_recursiveMatching)
1397  this->GetRecoToTrueMatches(recoParticlesToHits,
1398  trueHitsToParticles,
1399  matchedParticles,
1400  matchedHits,
1401  vetoReco,
1402  vetoTrue);
1403  }
1404 
1405  //------------------------------------------------------------------------------------------------------------------------------------------
1406 
1407  int
1408  PFParticleMonitoring::CountHitsByType(const int view, const HitVector& hitVector) const
1409  {
1410  int nHits(0);
1411 
1412  for (HitVector::const_iterator iter = hitVector.begin(), iterEnd = hitVector.end();
1413  iter != iterEnd;
1414  ++iter) {
1415  const art::Ptr<recob::Hit> hit = *iter;
1416  if (hit->View() == view) ++nHits;
1417  }
1418 
1419  return nHits;
1420  }
1421 
1422  //------------------------------------------------------------------------------------------------------------------------------------------
1423 
1424  void
1426  int& startT,
1427  int& endT) const
1428  {
1430 
1431  bool foundStartPosition(false);
1432 
1433  const int numTrajectoryPoints(static_cast<int>(particle->NumberTrajectoryPoints()));
1434 
1435  for (int nt = 0; nt < numTrajectoryPoints; ++nt) {
1436  try {
1437  double pos[3] = {particle->Vx(nt), particle->Vy(nt), particle->Vz(nt)};
1438  unsigned int which_tpc(std::numeric_limits<unsigned int>::max());
1439  unsigned int which_cstat(std::numeric_limits<unsigned int>::max());
1440  theGeometry->PositionToTPC(pos, which_tpc, which_cstat);
1441 
1442  // TODO: Apply fiducial cut due to readout window
1443 
1444  endT = nt;
1445  if (!foundStartPosition) {
1446  startT = endT;
1447  foundStartPosition = true;
1448  }
1449  }
1450  catch (cet::exception& e) {
1451  continue;
1452  }
1453  }
1454 
1455  if (!foundStartPosition) throw cet::exception("LArPandora");
1456  }
1457 
1458  //------------------------------------------------------------------------------------------------------------------------------------------
1459 
1460  double
1462  const int startT,
1463  const int endT) const
1464  {
1465  if (endT <= startT) return 0.0;
1466 
1467  double length(0.0);
1468 
1469  for (int nt = startT; nt < endT; ++nt) {
1470  const double dx(particle->Vx(nt + 1) - particle->Vx(nt));
1471  const double dy(particle->Vy(nt + 1) - particle->Vy(nt));
1472  const double dz(particle->Vz(nt + 1) - particle->Vz(nt));
1473  length += sqrt(dx * dx + dy * dy + dz * dz);
1474  }
1475 
1476  return length;
1477  }
1478 
1479 } //namespace lar_pandora
double E(const int i=0) const
Definition: MCParticle.h:233
static void BuildPFParticleHitMaps(const PFParticleVector &particleVector, const PFParticlesToSpacePoints &particlesToSpacePoints, const SpacePointsToHits &spacePointsToHits, PFParticlesToHits &particlesToHits, HitsToPFParticles &hitsToParticles, const DaughterMode daughterMode=kUseDaughters)
Build mapping between PFParticles and Hits using PFParticle/SpacePoint/Hit maps.
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
Definition: Vertex.cxx:36
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:218
std::map< art::Ptr< recob::Hit >, art::Ptr< simb::MCParticle > > HitsToMCParticles
int PdgCode() const
Definition: MCParticle.h:212
const simb::MCNeutrino & GetNeutrino() const
Definition: MCTruth.h:77
int CountHitsByType(const int view, const HitVector &hitVector) const
Count the number of reconstructed hits in a given wire plane.
static void BuildPFParticleMap(const PFParticleVector &particleVector, PFParticleMap &particleMap)
Build particle maps for reconstructed particles.
double Py(const int i=0) const
Definition: MCParticle.h:231
static int GetParentNeutrino(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the parent neutrino PDG code (or zero for cosmics) for a given reconstructed particle...
Encapsulate the construction of a single cyostat.
void GetRecoToTrueMatches(const PFParticlesToHits &recoNeutrinosToHits, const HitsToMCTruth &trueHitsToNeutrinos, MCTruthToPFParticles &matchedNeutrinos, MCTruthToHits &matchedNeutrinoHits) const
Perform matching between true and reconstructed neutrino events.
std::set< art::Ptr< recob::PFParticle > > PFParticleSet
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
std::string string
Definition: nybbler.cc:12
std::map< art::Ptr< simb::MCTruth >, HitVector > MCTruthToHits
Planes which measure V.
Definition: geo_types.h:130
std::map< art::Ptr< simb::MCParticle >, art::Ptr< simb::MCTruth > > MCParticlesToMCTruth
static art::Ptr< recob::PFParticle > GetFinalStatePFParticle(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the final-state parent particle by navigating up the chain of parent/daughter associations...
double Px(const int i=0) const
Definition: MCParticle.h:230
Vector_t VertexDirection() const
Definition: Track.h:132
std::map< art::Ptr< simb::MCParticle >, art::Ptr< recob::PFParticle > > MCParticlesToPFParticles
int PdgCode() const
Return the type of particle as a PDG ID.
Definition: PFParticle.h:83
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
intermediate_table::const_iterator const_iterator
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:25
std::string Process() const
Definition: MCParticle.h:215
Particle class.
static art::Ptr< recob::PFParticle > GetParentPFParticle(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the top-level parent particle by navigating up the chain of parent/daughter associations...
std::map< art::Ptr< recob::PFParticle >, TrackVector > PFParticlesToTracks
art framework interface to geometry description
std::map< art::Ptr< recob::PFParticle >, VertexVector > PFParticlesToVertices
std::map< int, art::Ptr< recob::PFParticle > > PFParticleMap
void BuildTrueNeutrinoHitMaps(const MCTruthToMCParticles &truthToParticles, const MCParticlesToHits &trueParticlesToHits, MCTruthToHits &trueNeutrinosToHits, HitsToMCTruth &trueHitsToNeutrinos) const
Build mapping from true neutrinos to hits.
geo::TPCGeo const & PositionToTPC(geo::Point_t const &point) const
Returns the TPC at specified location.
std::map< int, art::Ptr< simb::MCParticle > > MCParticleMap
std::set< art::Ptr< simb::MCTruth > > MCTruthSet
static void CollectSpacePoints(const art::Event &evt, const std::string &label, SpacePointVector &spacePointVector, SpacePointsToHits &spacePointsToHits)
Collect the reconstructed SpacePoints and associated hits from the ART event record.
bool isRealData() const
Planes which measure U.
Definition: geo_types.h:129
double GetLength(const art::Ptr< simb::MCParticle > trueParticle, const int startT, const int endT) const
Find the length of the true particle trajectory through the active region of the detector.
int m_nTrueWithoutRecoHits
True hits which don&#39;t belong to any reconstructed particle - "available".
std::map< art::Ptr< recob::PFParticle >, T0Vector > PFParticlesToT0s
std::map< art::Ptr< recob::Hit >, art::Ptr< simb::MCTruth > > HitsToMCTruth
const double e
double Length(size_t p=0) const
Access to various track properties.
Definition: Track.h:167
static art::Ptr< simb::MCParticle > GetParentMCParticle(const MCParticleMap &particleMap, const art::Ptr< simb::MCParticle > daughterParticle)
Return the top-level parent particle by navigating up the chain of parent/daughter associations...
void BuildRecoNeutrinoHitMaps(const PFParticleMap &recoParticleMap, const PFParticlesToHits &recoParticlesToHits, PFParticlesToHits &recoNeutrinosToHits, HitsToPFParticles &recoHitsToNeutrinos) const
Build mapping from reconstructed neutrinos to hits.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::map< art::Ptr< simb::MCParticle >, HitVector > MCParticlesToHits
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
std::map< art::Ptr< simb::MCTruth >, MCParticleVector > MCTruthToMCParticles
std::map< art::Ptr< simb::MCTruth >, art::Ptr< recob::PFParticle > > MCTruthToPFParticles
double P(const int i=0) const
Definition: MCParticle.h:234
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::vector< art::Ptr< recob::SpacePoint > > SpacePointVector
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
Point_t const & Vertex() const
Definition: Track.h:124
bool m_printDebug
switch for print statements (TODO: use message service!)
static void CollectVertices(const art::Event &evt, const std::string &label, VertexVector &vertexVector, PFParticlesToVertices &particlesToVertices)
Collect the reconstructed PFParticles and associated Vertices from the ART event record.
PFParticleMonitoring(fhicl::ParameterSet const &pset)
Constructor.
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::SpacePoint > > HitsToSpacePoints
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
std::vector< art::Ptr< recob::Track > > TrackVector
RunNumber_t run() const
Definition: DataViewImpl.cc:71
static int max(int a, int b)
static void CollectTracks(const art::Event &evt, const std::string &label, TrackVector &trackVector, PFParticlesToTracks &particlesToTracks)
Collect the reconstructed PFParticles and associated Tracks from the ART event record.
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
void GetStartAndEndPoints(const art::Ptr< simb::MCParticle > trueParticle, int &startT, int &endT) const
Find the start and end points of the true particle in the active region of detector.
static void CollectHits(const art::Event &evt, const std::string &label, HitVector &hitVector)
Collect the reconstructed Hits from the ART event record.
Detector simulation of raw signals on wires.
static void SelectNeutrinoPFParticles(const PFParticleVector &inputParticles, PFParticleVector &outputParticles)
Select reconstructed neutrino particles from a list of all reconstructed particles.
double Vx(const int i=0) const
Definition: MCParticle.h:221
std::vector< art::Ptr< recob::Hit > > HitVector
Declaration of signal hit object.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Encapsulate the construction of a single detector plane.
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::PFParticle > > HitsToPFParticles
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
double Pz(const int i=0) const
Definition: MCParticle.h:232
Provides recob::Track data product.
double Vz(const int i=0) const
Definition: MCParticle.h:223
const Double32_t * XYZ() const
Definition: SpacePoint.h:76
std::vector< art::Ptr< recob::Vertex > > VertexVector
EventNumber_t event() const
Definition: EventID.h:116
Point_t const & End() const
Definition: Track.h:125
void reconfigure(fhicl::ParameterSet const &pset)
std::set< art::Ptr< simb::MCParticle > > MCParticleSet
Planes which measure W (third view for Bo, MicroBooNE, etc).
Definition: geo_types.h:131
bool NeutrinoSet() const
Definition: MCTruth.h:78
TCEvent evt
Definition: DataStructs.cxx:7
std::vector< art::Ptr< anab::T0 > > T0Vector
static void CollectT0s(const art::Event &evt, const std::string &label, T0Vector &t0Vector, PFParticlesToT0s &particlesToT0s)
Collect a vector of T0s from the ART event record.
static void BuildMCParticleHitMaps(const art::Event &evt, const HitVector &hitVector, const SimChannelVector &simChannelVector, HitsToTrackIDEs &hitsToTrackIDEs)
Collect the links from reconstructed hits to their true energy deposits.
Event generator information.
Definition: MCNeutrino.h:18
static void CollectMCParticles(const art::Event &evt, const std::string &label, MCParticleVector &particleVector)
Collect a vector of MCParticle objects from the ART event record.
helper function for LArPandoraInterface producer module
static art::Ptr< simb::MCParticle > GetFinalStateMCParticle(const MCParticleMap &particleMap, const art::Ptr< simb::MCParticle > daughterParticle)
Return the final-state parent particle by navigating up the chain of parent/daughter associations...
int m_nRecoWithoutTrueHits
Reconstructed hits which don&#39;t belong to any true particle - "missing".
EventID id() const
Definition: Event.cc:34
double Vy(const int i=0) const
Definition: MCParticle.h:222
static bool IsFinalState(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Determine whether a particle has been reconstructed as a final-state particle.
std::map< art::Ptr< recob::SpacePoint >, art::Ptr< recob::Hit > > SpacePointsToHits
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool m_disableRealDataCheck
Whether to check if the input file contains real data before accessing MC information.
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.
static void BuildMCParticleMap(const MCParticleVector &particleVector, MCParticleMap &particleMap)
Build particle maps for true particles.