LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
PFParticleValidation_module.cc
Go to the documentation of this file.
1 
10 
12 
13 #include <string>
14 
15 //------------------------------------------------------------------------------------------------------------------------------------------
16 
17 namespace lar_pandora
18 {
19 
24 {
25 public:
32 
36  virtual ~PFParticleValidation();
37 
38  void beginJob();
39  void endJob();
40  void analyze(const art::Event &evt);
41  void reconfigure(fhicl::ParameterSet const &pset);
42 
43 private:
48  {
49  public:
54 
62  bool operator<(const SimpleMCPrimary &rhs) const;
63 
64  int m_id;
65  int m_pdgCode;
67  int m_nMCHitsU;
68  int m_nMCHitsV;
69  int m_nMCHitsW;
70  float m_energy;
73  };
74 
75  typedef std::vector<SimpleMCPrimary> SimpleMCPrimaryList;
76 
81  {
82  public:
87 
88  int m_id;
89  int m_parentId;
90  int m_pdgCode;
100  };
101 
102  typedef std::vector<SimpleMatchedPfo> SimpleMatchedPfoList;
103 
108  {
109  public:
113  MatchingDetails();
114 
118  };
119 
120  typedef std::map<int, MatchingDetails> MatchingDetailsMap;
121  typedef std::map<SimpleMCPrimary, SimpleMatchedPfoList> MCPrimaryMatchingMap; // SimpleMCPrimary has a defined operator<
122 
123  typedef std::map< art::Ptr<recob::PFParticle>, HitVector > PFParticleToMatchedHits;
124  typedef std::map< art::Ptr<simb::MCParticle>, PFParticleToMatchedHits > MCParticleMatchingMap;
125 
134  void GetMCParticleMatchingMap(const PFParticlesToHits &recoParticlesToHits, const MCParticlesToHits &trueParticlesToHits,
135  const HitsToMCParticles &hitsToTrueParticles, MCParticleMatchingMap &mcParticleMatchingMap) const;
136 
146  void GetSimpleMCPrimaryList(const art::Event &evt, const MCParticlesToHits &mcParticlesToHits, const HitsToMCParticles &hitsToMCParticles,
147  const MCParticleMatchingMap &mcParticleMatchingMap, SimpleMCPrimaryList &simpleMCPrimaryList) const;
148 
157  void GetMCPrimaryMatchingMap(const SimpleMCPrimaryList &simpleMCPrimaryList, const MCParticleMatchingMap &mcParticleMatchingMap,
158  const PFParticlesToHits &pfParticlesToHits, MCPrimaryMatchingMap &mcPrimaryMatchingMap) const;
159 
168  bool IsNeutrinoInduced(const art::Ptr<simb::MCParticle> pMCParticle, const MCParticlesToMCTruth &artMCParticlesToMCTruth) const;
169 
176  void GetMCTruth(const art::Event &evt, MCTruthVector &mcTruthVector) const;
177 
184  void GetRecoNeutrinos(const art::Event &evt, PFParticleVector &recoNeutrinoVector) const;
185 
193  void PrintAllOutput(const MCTruthVector &mcTruthVector, const PFParticleVector &recoNeutrinoVector, const MCPrimaryMatchingMap &mcPrimaryMatchingMap) const;
194 
201  void PerformMatching(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, MatchingDetailsMap &matchingDetailsMap) const;
202 
203  typedef std::set<int> IntSet;
204 
213  bool GetStrongestPfoMatch(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, IntSet &usedMCIds, IntSet &usedPfoIds, MatchingDetailsMap &matchingDetailsMap) const;
214 
222  void GetRemainingPfoMatches(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const IntSet &usedPfoIds, MatchingDetailsMap &matchingDetailsMap) const;
223 
230  void PrintMatchingOutput(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const MatchingDetailsMap &matchingDetailsMap) const;
231 
239  bool IsGoodMCPrimary(const SimpleMCPrimary &simpleMCPrimary) const;
240 
250  bool HasMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfoList &simpleMatchedPfoList, const MatchingDetailsMap &matchingDetailsMap) const;
251 
260  bool IsGoodMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfo &simpleMatchedPfo) const;
261 
270  unsigned int CountHitsByType(const geo::View_t view, const HitVector &hitVector) const;
271 
280  static bool SortSimpleMCPrimaries(const SimpleMCPrimary &lhs, const SimpleMCPrimary &rhs);
281 
290  static bool SortSimpleMatchedPfos(const SimpleMatchedPfo &lhs, const SimpleMatchedPfo &rhs);
291 
292  std::string m_hitfinderLabel;
293  std::string m_particleLabel;
294  std::string m_geantModuleLabel;
295  std::string m_backtrackerLabel;
296 
299 
301 
305 
310 };
311 
313 
314 } // namespace lar_pandora
315 
316 //------------------------------------------------------------------------------------------------------------------------------------------
317 
318 
320 
321 #include "fhiclcpp/ParameterSet.h"
322 
325 
326 #include "lardataobj/RecoBase/Hit.h"
328 
329 #include <algorithm>
330 #include <iostream>
331 
332 namespace lar_pandora
333 {
334 
336  art::EDAnalyzer(pset)
337 {
338  this->reconfigure(pset);
339 }
340 
341 //------------------------------------------------------------------------------------------------------------------------------------------
342 
344 {
345 }
346 
347 //------------------------------------------------------------------------------------------------------------------------------------------
348 
350 {
351  m_particleLabel = pset.get<std::string>("PFParticleModule", "pandoraNu");
352  m_hitfinderLabel = pset.get<std::string>("HitFinderModule", "gaushit");
353  m_geantModuleLabel = pset.get<std::string>("GeantModule","largeant");
354  m_backtrackerLabel = pset.get<std::string>("BackTrackerModule","gaushitTruthMatch");
355  m_printAllToScreen = pset.get<bool>("PrintAllToScreen", true);
356  m_printMatchingToScreen = pset.get<bool>("PrintMatchingToScreen", true);
357  m_neutrinoInducedOnly = pset.get<bool>("NeutrinoInducedOnly", true);
358  m_matchingMinPrimaryHits = pset.get<int>("MatchingMinPrimaryHits", 15);
359  m_matchingMinHitsForGoodView = pset.get<int>("MatchingMinHitsForGoodView", 5);
360  m_matchingMinPrimaryGoodViews = pset.get<int>("MatchingMinPrimaryGoodViews", 2);
361  m_useSmallPrimaries = pset.get<bool>("UseSmallPrimaries", true);
362  m_matchingMinSharedHits = pset.get<int>("MatchingMinSharedHits", 5);
363  m_matchingMinCompleteness = pset.get<float>("MatchingMinCompleteness", 0.1f);
364  m_matchingMinPurity = pset.get<float>("MatchingMinPurity", 0.5f);
365 }
366 
367 //------------------------------------------------------------------------------------------------------------------------------------------
368 
370 {
371 }
372 
373 //------------------------------------------------------------------------------------------------------------------------------------------
374 
376 {
377 }
378 
379 //------------------------------------------------------------------------------------------------------------------------------------------
380 
382 {
383  HitVector hitVector;
385 
386  PFParticlesToHits pfParticlesToHits;
387  HitsToPFParticles hitsToPfParticles;
389 
390  MCParticlesToHits mcParticlesToHits;
391  HitsToMCParticles hitsToMCParticles;
392 
394  mcParticlesToHits, hitsToMCParticles, LArPandoraHelper::kAddDaughters);
395 
396  if (hitsToMCParticles.empty())
397  {
398  if (m_backtrackerLabel.empty())
399  throw cet::exception("LArPandora") << " PFParticleValidation::analyze - no sim channels found, backtracker module must be set in FHiCL " << std::endl;
400 
402  mcParticlesToHits, hitsToMCParticles, LArPandoraHelper::kAddDaughters);
403  }
404 
405  MCParticleMatchingMap mcParticleMatchingMap;
406  this->GetMCParticleMatchingMap(pfParticlesToHits, mcParticlesToHits, hitsToMCParticles, mcParticleMatchingMap);
407 
408  SimpleMCPrimaryList simpleMCPrimaryList;
409  this->GetSimpleMCPrimaryList(evt, mcParticlesToHits, hitsToMCParticles, mcParticleMatchingMap, simpleMCPrimaryList);
410 
411  MCPrimaryMatchingMap mcPrimaryMatchingMap;
412  this->GetMCPrimaryMatchingMap(simpleMCPrimaryList, mcParticleMatchingMap, pfParticlesToHits, mcPrimaryMatchingMap);
413 
414  MCTruthVector mcTruthVector;
415  this->GetMCTruth(evt, mcTruthVector);
416 
417  PFParticleVector recoNeutrinoVector;
418  this->GetRecoNeutrinos(evt, recoNeutrinoVector);
419 
420  if (m_printAllToScreen)
421  this->PrintAllOutput(mcTruthVector, recoNeutrinoVector, mcPrimaryMatchingMap);
422 
424  {
425  MatchingDetailsMap matchingDetailsMap;
426  this->PerformMatching(mcPrimaryMatchingMap, matchingDetailsMap);
427  this->PrintMatchingOutput(mcPrimaryMatchingMap, matchingDetailsMap);
428  }
429 }
430 
431 //------------------------------------------------------------------------------------------------------------------------------------------
432 
433 void PFParticleValidation::GetMCParticleMatchingMap(const PFParticlesToHits &pfParticlesToHits, const MCParticlesToHits &mcParticlesToHits,
434  const HitsToMCParticles &hitsToMCParticles, MCParticleMatchingMap &mcParticleMatchingMap) const
435 {
436  // Create a placeholder entry for all mc particles with >0 hits
437  for (const MCParticlesToHits::value_type &mcParticleToHitsEntry : mcParticlesToHits)
438  {
439  if (!mcParticleToHitsEntry.second.empty())
440  (void) mcParticleMatchingMap.insert(MCParticleMatchingMap::value_type(mcParticleToHitsEntry.first, PFParticleToMatchedHits()));
441  }
442 
443  // Store true to reco matching details
444  for (const PFParticlesToHits::value_type &recoParticleToHits : pfParticlesToHits)
445  {
446  const art::Ptr<recob::PFParticle> pRecoParticle(recoParticleToHits.first);
447  const HitVector &hitVector(recoParticleToHits.second);
448 
449  for (const art::Ptr<recob::Hit> pHit : hitVector)
450  {
451  HitsToMCParticles::const_iterator mcParticleIter = hitsToMCParticles.find(pHit);
452 
453  if (hitsToMCParticles.end() == mcParticleIter)
454  continue;
455 
456  const art::Ptr<simb::MCParticle> pTrueParticle = mcParticleIter->second;
457  mcParticleMatchingMap[pTrueParticle][pRecoParticle].push_back(pHit);
458  }
459  }
460 }
461 
462 //------------------------------------------------------------------------------------------------------------------------------------------
463 
465  const HitsToMCParticles &hitsToMCParticles, const MCParticleMatchingMap &mcParticleMatchingMap, SimpleMCPrimaryList &simpleMCPrimaryList) const
466 {
467  MCTruthToMCParticles artMCTruthToMCParticles;
468  MCParticlesToMCTruth artMCParticlesToMCTruth;
469  LArPandoraHelper::CollectMCParticles(evt, m_geantModuleLabel, artMCTruthToMCParticles, artMCParticlesToMCTruth);
470 
471  for (const MCParticlesToHits::value_type &mapEntry : mcParticlesToHits)
472  {
473  const art::Ptr<simb::MCParticle> pMCPrimary(mapEntry.first);
474 
475  if (m_neutrinoInducedOnly && !this->IsNeutrinoInduced(pMCPrimary, artMCParticlesToMCTruth))
476  continue;
477 
478  SimpleMCPrimary simpleMCPrimary;
479  // ATTN simpleMCPrimary.m_id assigned later, after sorting
480  simpleMCPrimary.m_pAddress = pMCPrimary.get();
481  simpleMCPrimary.m_pdgCode = pMCPrimary->PdgCode();
482  simpleMCPrimary.m_energy = pMCPrimary->E();
483 
484  MCParticlesToHits::const_iterator trueHitsIter = mcParticlesToHits.find(pMCPrimary);
485 
486  if (mcParticlesToHits.end() != trueHitsIter)
487  {
488  const HitVector &hitVector(trueHitsIter->second);
489  simpleMCPrimary.m_nMCHitsTotal = hitVector.size();
490  simpleMCPrimary.m_nMCHitsU = this->CountHitsByType(geo::kU, hitVector);
491  simpleMCPrimary.m_nMCHitsV = this->CountHitsByType(geo::kV, hitVector);
492  simpleMCPrimary.m_nMCHitsW = this->CountHitsByType(geo::kW, hitVector);
493  }
494 
495  MCParticleMatchingMap::const_iterator matchedPfoIter = mcParticleMatchingMap.find(pMCPrimary);
496 
497  if (mcParticleMatchingMap.end() != matchedPfoIter)
498  simpleMCPrimary.m_nMatchedPfos = matchedPfoIter->second.size();
499 
500  simpleMCPrimaryList.push_back(simpleMCPrimary);
501  }
502 
503  std::sort(simpleMCPrimaryList.begin(), simpleMCPrimaryList.end(), PFParticleValidation::SortSimpleMCPrimaries);
504 
505  int mcPrimaryId(0);
506  for (SimpleMCPrimary &simpleMCPrimary : simpleMCPrimaryList)
507  simpleMCPrimary.m_id = mcPrimaryId++;
508 }
509 
510 //------------------------------------------------------------------------------------------------------------------------------------------
511 
512 bool PFParticleValidation::IsNeutrinoInduced(const art::Ptr<simb::MCParticle> pMCParticle, const MCParticlesToMCTruth &artMCParticlesToMCTruth) const
513 {
514  MCParticlesToMCTruth::const_iterator iter = artMCParticlesToMCTruth.find(pMCParticle);
515 
516  if (artMCParticlesToMCTruth.end() == iter)
517  return false;
518 
519  const art::Ptr<simb::MCTruth> pMCTruth = iter->second;
520  return (simb::kBeamNeutrino == pMCTruth->Origin());
521 }
522 
523 //------------------------------------------------------------------------------------------------------------------------------------------
524 
525 void PFParticleValidation::GetMCPrimaryMatchingMap(const SimpleMCPrimaryList &simpleMCPrimaryList, const MCParticleMatchingMap &mcParticleMatchingMap,
526  const PFParticlesToHits &pfParticlesToHits, MCPrimaryMatchingMap &mcPrimaryMatchingMap) const
527 {
528  for (const SimpleMCPrimary &simpleMCPrimary : simpleMCPrimaryList)
529  {
530  SimpleMatchedPfoList simpleMatchedPfoList;
531  MCParticleMatchingMap::const_iterator matchedPfoIter = mcParticleMatchingMap.end();
532 
533  // ATTN Nasty workaround I
534  for (MCParticleMatchingMap::const_iterator iter = mcParticleMatchingMap.begin(), iterEnd = mcParticleMatchingMap.end(); iter != iterEnd; ++iter)
535  {
536  if (simpleMCPrimary.m_pAddress == iter->first.get())
537  {
538  matchedPfoIter = iter;
539  break;
540  };
541  }
542 
543  if (mcParticleMatchingMap.end() != matchedPfoIter)
544  {
545  for (const PFParticleToMatchedHits::value_type &contribution : matchedPfoIter->second)
546  {
547  const art::Ptr<recob::PFParticle> pMatchedPfo(contribution.first);
548  const HitVector &matchedHitVector(contribution.second);
549 
550  SimpleMatchedPfo simpleMatchedPfo;
551  simpleMatchedPfo.m_pAddress = pMatchedPfo.get();
552  simpleMatchedPfo.m_id = pMatchedPfo->Self();
553 
554  // ATTN Assume pfos have either zero or one parents. Ignore parent neutrino.
555  PFParticlesToHits::const_iterator parentPfoIter = pfParticlesToHits.end();
556 
557  // ATTN Nasty workaround II, bad place for another loop.
558  for (PFParticlesToHits::const_iterator iter = pfParticlesToHits.begin(), iterEnd = pfParticlesToHits.end(); iter != iterEnd; ++iter)
559  {
560  if (pMatchedPfo->Parent() == iter->first->Self())
561  {
562  parentPfoIter = iter;
563  break;
564  };
565  }
566 
567  if ((pfParticlesToHits.end() != parentPfoIter) && !LArPandoraHelper::IsNeutrino(parentPfoIter->first))
568  simpleMatchedPfo.m_parentId = parentPfoIter->first->Self();
569 
570  simpleMatchedPfo.m_pdgCode = pMatchedPfo->PdgCode();
571  simpleMatchedPfo.m_nMatchedHitsTotal = matchedHitVector.size();
572  simpleMatchedPfo.m_nMatchedHitsU = this->CountHitsByType(geo::kU, matchedHitVector);
573  simpleMatchedPfo.m_nMatchedHitsV = this->CountHitsByType(geo::kV, matchedHitVector);
574  simpleMatchedPfo.m_nMatchedHitsW = this->CountHitsByType(geo::kW, matchedHitVector);
575 
576  PFParticlesToHits::const_iterator pfoHitsIter = pfParticlesToHits.find(pMatchedPfo);
577 
578  if (pfParticlesToHits.end() == pfoHitsIter)
579  throw cet::exception("LArPandora") << " PFParticleValidation::analyze --- Presence of PFParticle in map mandatory.";
580 
581  const HitVector &pfoHitVector(pfoHitsIter->second);
582 
583  simpleMatchedPfo.m_nPfoHitsTotal = pfoHitVector.size();
584  simpleMatchedPfo.m_nPfoHitsU = this->CountHitsByType(geo::kU, pfoHitVector);
585  simpleMatchedPfo.m_nPfoHitsV = this->CountHitsByType(geo::kV, pfoHitVector);
586  simpleMatchedPfo.m_nPfoHitsW = this->CountHitsByType(geo::kW, pfoHitVector);
587 
588  simpleMatchedPfoList.push_back(simpleMatchedPfo);
589  }
590  }
591 
592  // Store the ordered vectors of matched pfo details
593  std::sort(simpleMatchedPfoList.begin(), simpleMatchedPfoList.end(), PFParticleValidation::SortSimpleMatchedPfos);
594 
595  if (!mcPrimaryMatchingMap.insert(MCPrimaryMatchingMap::value_type(simpleMCPrimary, simpleMatchedPfoList)).second)
596  throw cet::exception("LArPandora") << " PFParticleValidation::analyze --- Double-counting MC primaries.";
597  }
598 }
599 
600 //------------------------------------------------------------------------------------------------------------------------------------------
601 
602 void PFParticleValidation::GetMCTruth(const art::Event &evt, MCTruthVector &mcTruthVector) const
603 {
604  MCTruthToMCParticles artMCTruthToMCParticles;
605  MCParticlesToMCTruth artMCParticlesToMCTruth;
606  LArPandoraHelper::CollectMCParticles(evt, m_geantModuleLabel, artMCTruthToMCParticles, artMCParticlesToMCTruth);
607 
608  for (const auto &mapEntry : artMCTruthToMCParticles)
609  {
610  const art::Ptr<simb::MCTruth> truth = mapEntry.first;
611 
612  if (!truth->NeutrinoSet())
613  continue;
614 
615  if (mcTruthVector.end() == std::find(mcTruthVector.begin(), mcTruthVector.end(), truth))
616  mcTruthVector.push_back(truth);
617  }
618 }
619 
620 //------------------------------------------------------------------------------------------------------------------------------------------
621 
622 void PFParticleValidation::GetRecoNeutrinos(const art::Event &evt, PFParticleVector &recoNeutrinoVector) const
623 {
624  PFParticleVector allPFParticles;
626  LArPandoraHelper::SelectNeutrinoPFParticles(allPFParticles, recoNeutrinoVector);
627 }
628 
629 //------------------------------------------------------------------------------------------------------------------------------------------
630 
631 void PFParticleValidation::PrintAllOutput(const MCTruthVector &mcTruthVector, const PFParticleVector &recoNeutrinoVector,
632  const MCPrimaryMatchingMap &mcPrimaryMatchingMap) const
633 {
634  std::cout << "---RAW-MATCHING-OUTPUT--------------------------------------------------------------------------" << std::endl;
635 
636  for (const art::Ptr<simb::MCTruth> pMCTruth : mcTruthVector)
637  {
638  std::cout << "MCNeutrino, PDG " << pMCTruth->GetNeutrino().Nu().PdgCode() << ", InteractionType " << pMCTruth->GetNeutrino().InteractionType() << std::endl;
639  }
640 
641  for (const art::Ptr<recob::PFParticle> pPfo : recoNeutrinoVector)
642  {
643  std::cout << "RecoNeutrino, PDG " << pPfo->PdgCode() << ", nDaughters " << pPfo->NumDaughters() << std::endl;
644  }
645 
646  for (const MCPrimaryMatchingMap::value_type &mapValue : mcPrimaryMatchingMap)
647  {
648  const SimpleMCPrimary &simpleMCPrimary(mapValue.first);
649 
650  std::cout << std::endl << "Primary " << simpleMCPrimary.m_id << ", PDG " << simpleMCPrimary.m_pdgCode << ", nMCHits " << simpleMCPrimary.m_nMCHitsTotal
651  << " (" << simpleMCPrimary.m_nMCHitsU << ", " << simpleMCPrimary.m_nMCHitsV << ", " << simpleMCPrimary.m_nMCHitsW << ")" << std::endl;
652 
653  for (const SimpleMatchedPfo &simpleMatchedPfo : mapValue.second)
654  {
655  std::cout << "-MatchedPfo " << simpleMatchedPfo.m_id;
656 
657  if (simpleMatchedPfo.m_parentId >= 0)
658  std::cout << ", ParentPfo " << simpleMatchedPfo.m_parentId;
659 
660  std::cout << ", PDG " << simpleMatchedPfo.m_pdgCode << ", nMatchedHits " << simpleMatchedPfo.m_nMatchedHitsTotal
661  << " (" << simpleMatchedPfo.m_nMatchedHitsU << ", " << simpleMatchedPfo.m_nMatchedHitsV << ", " << simpleMatchedPfo.m_nMatchedHitsW << ")"
662  << ", nPfoHits " << simpleMatchedPfo.m_nPfoHitsTotal << " (" << simpleMatchedPfo.m_nPfoHitsU << ", " << simpleMatchedPfo.m_nPfoHitsV << ", "
663  << simpleMatchedPfo.m_nPfoHitsW << ")" << std::endl;
664  }
665  }
666 
667  std::cout << "------------------------------------------------------------------------------------------------" << std::endl;
668 }
669 
670 //------------------------------------------------------------------------------------------------------------------------------------------
671 
672 void PFParticleValidation::PerformMatching(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, MatchingDetailsMap &matchingDetailsMap) const
673 {
674  // Get best matches, one-by-one, until no more strong matches possible
675  IntSet usedMCIds, usedPfoIds;
676  while (GetStrongestPfoMatch(mcPrimaryMatchingMap, usedMCIds, usedPfoIds, matchingDetailsMap)) {}
677 
678  // Assign any remaining pfos to primaries, based on number of matched hits
679  GetRemainingPfoMatches(mcPrimaryMatchingMap, usedPfoIds, matchingDetailsMap);
680 }
681 
682 //------------------------------------------------------------------------------------------------------------------------------------------
683 
684 bool PFParticleValidation::GetStrongestPfoMatch(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, IntSet &usedMCIds, IntSet &usedPfoIds,
685  MatchingDetailsMap &matchingDetailsMap) const
686 {
687  int bestPfoMatchId(-1);
688  MatchingDetails bestMatchingDetails;
689 
690  for (const MCPrimaryMatchingMap::value_type &mapValue : mcPrimaryMatchingMap)
691  {
692  const SimpleMCPrimary &simpleMCPrimary(mapValue.first);
693 
694  if (!m_useSmallPrimaries && !this->IsGoodMCPrimary(simpleMCPrimary))
695  continue;
696 
697  if (usedMCIds.count(simpleMCPrimary.m_id))
698  continue;
699 
700  for (const SimpleMatchedPfo &simpleMatchedPfo : mapValue.second)
701  {
702  if (usedPfoIds.count(simpleMatchedPfo.m_id))
703  continue;
704 
705  if (!this->IsGoodMatch(simpleMCPrimary, simpleMatchedPfo))
706  continue;
707 
708  if (simpleMatchedPfo.m_nMatchedHitsTotal > bestMatchingDetails.m_nMatchedHits)
709  {
710  bestPfoMatchId = simpleMatchedPfo.m_id;
711  bestMatchingDetails.m_matchedPrimaryId = simpleMCPrimary.m_id;
712  bestMatchingDetails.m_nMatchedHits = simpleMatchedPfo.m_nMatchedHitsTotal;
713  bestMatchingDetails.m_completeness = static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) / static_cast<float>(simpleMCPrimary.m_nMCHitsTotal);
714  }
715  }
716  }
717 
718  if (bestPfoMatchId > -1)
719  {
720  matchingDetailsMap[bestPfoMatchId] = bestMatchingDetails;
721  usedMCIds.insert(bestMatchingDetails.m_matchedPrimaryId);
722  usedPfoIds.insert(bestPfoMatchId);
723  return true;
724  }
725 
726  return false;
727 }
728 
729 //------------------------------------------------------------------------------------------------------------------------------------------
730 
731 void PFParticleValidation::GetRemainingPfoMatches(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const IntSet &usedPfoIds,
732  MatchingDetailsMap &matchingDetailsMap) const
733 {
734  for (const MCPrimaryMatchingMap::value_type &mapValue : mcPrimaryMatchingMap)
735  {
736  const SimpleMCPrimary &simpleMCPrimary(mapValue.first);
737 
738  if (!m_useSmallPrimaries && !this->IsGoodMCPrimary(simpleMCPrimary))
739  continue;
740 
741  for (const SimpleMatchedPfo &simpleMatchedPfo : mapValue.second)
742  {
743  if (usedPfoIds.count(simpleMatchedPfo.m_id))
744  continue;
745 
746  MatchingDetails &matchingDetails(matchingDetailsMap[simpleMatchedPfo.m_id]);
747 
748  if (simpleMatchedPfo.m_nMatchedHitsTotal > matchingDetails.m_nMatchedHits)
749  {
750  matchingDetails.m_matchedPrimaryId = simpleMCPrimary.m_id;
751  matchingDetails.m_nMatchedHits = simpleMatchedPfo.m_nMatchedHitsTotal;
752  matchingDetails.m_completeness = static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) / static_cast<float>(simpleMCPrimary.m_nMCHitsTotal);
753  }
754  }
755  }
756 }
757 
758 //------------------------------------------------------------------------------------------------------------------------------------------
759 
760 void PFParticleValidation::PrintMatchingOutput(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const MatchingDetailsMap &matchingDetailsMap) const
761 {
762  std::cout << "---PROCESSED-MATCHING-OUTPUT--------------------------------------------------------------------" << std::endl;
763  std::cout << "MinPrimaryGoodHits " << m_matchingMinPrimaryHits << ", MinHitsForGoodView " << m_matchingMinHitsForGoodView << ", MinPrimaryGoodViews " << m_matchingMinPrimaryGoodViews << std::endl;
764  std::cout << "UseSmallPrimaries " << m_useSmallPrimaries << ", MinSharedHits " << m_matchingMinSharedHits << ", MinCompleteness " << m_matchingMinCompleteness << ", MinPurity " << m_matchingMinPurity << std::endl;
765 
766  bool isCorrect(true), isCalculable(false);
767 
768  for (const MCPrimaryMatchingMap::value_type &mapValue : mcPrimaryMatchingMap)
769  {
770  const SimpleMCPrimary &simpleMCPrimary(mapValue.first);
771  const bool hasMatch(this->HasMatch(simpleMCPrimary, mapValue.second, matchingDetailsMap));
772  const bool isTargetPrimary(this->IsGoodMCPrimary(simpleMCPrimary) && (2112 != simpleMCPrimary.m_pdgCode));
773 
774  if (!hasMatch && !isTargetPrimary)
775  continue;
776 
777  std::cout << std::endl << (!isTargetPrimary ? "(Non target) " : "")
778  << "Primary " << simpleMCPrimary.m_id << ", PDG " << simpleMCPrimary.m_pdgCode << ", nMCHits " << simpleMCPrimary.m_nMCHitsTotal
779  << " (" << simpleMCPrimary.m_nMCHitsU << ", " << simpleMCPrimary.m_nMCHitsV << ", " << simpleMCPrimary.m_nMCHitsW << ")" << std::endl;
780 
781  if (2112 != simpleMCPrimary.m_pdgCode)
782  isCalculable = true;
783 
784  unsigned int nMatches(0);
785 
786  for (const SimpleMatchedPfo &simpleMatchedPfo : mapValue.second)
787  {
788  if (matchingDetailsMap.count(simpleMatchedPfo.m_id) && (simpleMCPrimary.m_id == matchingDetailsMap.at(simpleMatchedPfo.m_id).m_matchedPrimaryId))
789  {
790  const bool isGoodMatch(this->IsGoodMatch(simpleMCPrimary, simpleMatchedPfo));
791 
792  if (isGoodMatch) ++nMatches;
793  std::cout << "-" << (!isGoodMatch ? "(Below threshold) " : "") << "MatchedPfo " << simpleMatchedPfo.m_id;
794 
795  if (simpleMatchedPfo.m_parentId >= 0) std::cout << ", ParentPfo " << simpleMatchedPfo.m_parentId;
796 
797  std::cout << ", PDG " << simpleMatchedPfo.m_pdgCode << ", nMatchedHits " << simpleMatchedPfo.m_nMatchedHitsTotal
798  << " (" << simpleMatchedPfo.m_nMatchedHitsU << ", " << simpleMatchedPfo.m_nMatchedHitsV << ", " << simpleMatchedPfo.m_nMatchedHitsW << ")"
799  << ", nPfoHits " << simpleMatchedPfo.m_nPfoHitsTotal
800  << " (" << simpleMatchedPfo.m_nPfoHitsU << ", " << simpleMatchedPfo.m_nPfoHitsV << ", " << simpleMatchedPfo.m_nPfoHitsW << ")" << std::endl;
801  }
802  }
803 
804  if (isTargetPrimary && (1 != nMatches))
805  isCorrect = false;
806  }
807 
808  std::cout << std::endl << "Is correct? " << (isCorrect && isCalculable) << std::endl;
809  std::cout << "------------------------------------------------------------------------------------------------" << std::endl;
810 }
811 
812 //------------------------------------------------------------------------------------------------------------------------------------------
813 
814 bool PFParticleValidation::IsGoodMCPrimary(const SimpleMCPrimary &simpleMCPrimary) const
815 {
816  if (simpleMCPrimary.m_nMCHitsTotal < m_matchingMinPrimaryHits)
817  return false;
818 
819  int nGoodViews(0);
820  if (simpleMCPrimary.m_nMCHitsU >= m_matchingMinHitsForGoodView) ++nGoodViews;
821  if (simpleMCPrimary.m_nMCHitsV >= m_matchingMinHitsForGoodView) ++nGoodViews;
822  if (simpleMCPrimary.m_nMCHitsW >= m_matchingMinHitsForGoodView) ++nGoodViews;
823 
824  if (nGoodViews < m_matchingMinPrimaryGoodViews)
825  return false;
826 
827  return true;
828 }
829 
830 //------------------------------------------------------------------------------------------------------------------------------------------
831 
832 bool PFParticleValidation::HasMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfoList &simpleMatchedPfoList,
833  const MatchingDetailsMap &matchingDetailsMap) const
834 {
835  for (const SimpleMatchedPfo &simpleMatchedPfo : simpleMatchedPfoList)
836  {
837  if (matchingDetailsMap.count(simpleMatchedPfo.m_id) && (simpleMCPrimary.m_id == matchingDetailsMap.at(simpleMatchedPfo.m_id).m_matchedPrimaryId))
838  return true;
839  }
840 
841  return false;
842 }
843 
844 //------------------------------------------------------------------------------------------------------------------------------------------
845 
846 bool PFParticleValidation::IsGoodMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfo &simpleMatchedPfo) const
847 {
848  const float purity((simpleMatchedPfo.m_nPfoHitsTotal > 0) ? static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) / static_cast<float>(simpleMatchedPfo.m_nPfoHitsTotal) : 0.f);
849  const float completeness((simpleMCPrimary.m_nMCHitsTotal > 0) ? static_cast<float>(simpleMatchedPfo.m_nMatchedHitsTotal) / static_cast<float>(simpleMCPrimary.m_nMCHitsTotal) : 0.f);
850 
851  return ((simpleMatchedPfo.m_nMatchedHitsTotal >= m_matchingMinSharedHits) && (purity >= m_matchingMinPurity) && (completeness >= m_matchingMinCompleteness));
852 }
853 
854 //------------------------------------------------------------------------------------------------------------------------------------------
855 
856 unsigned int PFParticleValidation::CountHitsByType(const geo::View_t view, const HitVector &hitVector) const
857 {
858  unsigned int nHitsOfSpecifiedType(0);
859 
860  for (const art::Ptr<recob::Hit> pHit : hitVector)
861  {
862  if (view == pHit->View())
863  ++nHitsOfSpecifiedType;
864  }
865 
866  return nHitsOfSpecifiedType;
867 }
868 
869 //------------------------------------------------------------------------------------------------------------------------------------------
870 
872 {
873  if (lhs.m_nMCHitsTotal != rhs.m_nMCHitsTotal)
874  return (lhs.m_nMCHitsTotal > rhs.m_nMCHitsTotal);
875 
876  return (lhs.m_energy > rhs.m_energy);
877 }
878 
879 //------------------------------------------------------------------------------------------------------------------------------------------
880 
882 {
884  return (lhs.m_nMatchedHitsTotal > rhs.m_nMatchedHitsTotal);
885 
886  if (lhs.m_nPfoHitsTotal != rhs.m_nPfoHitsTotal)
887  return (lhs.m_nPfoHitsTotal > rhs.m_nPfoHitsTotal);
888 
889  return (lhs.m_id < rhs.m_id);
890 }
891 
892 //------------------------------------------------------------------------------------------------------------------------------------------
893 //------------------------------------------------------------------------------------------------------------------------------------------
894 
896  m_id(-1),
897  m_pdgCode(0),
898  m_nMCHitsTotal(0),
899  m_nMCHitsU(0),
900  m_nMCHitsV(0),
901  m_nMCHitsW(0),
902  m_energy(0.f),
903  m_nMatchedPfos(0),
904  m_pAddress(nullptr)
905 {
906 }
907 
908 //------------------------------------------------------------------------------------------------------------------------------------------
909 
911 {
912  if (this == &rhs)
913  return false;
914 
915  return (m_id < rhs.m_id);
916 }
917 
918 //------------------------------------------------------------------------------------------------------------------------------------------
919 //------------------------------------------------------------------------------------------------------------------------------------------
920 
922  m_id(-1),
923  m_parentId(-1),
924  m_pdgCode(0),
925  m_nPfoHitsTotal(0),
926  m_nPfoHitsU(0),
927  m_nPfoHitsV(0),
928  m_nPfoHitsW(0),
929  m_nMatchedHitsTotal(0),
930  m_nMatchedHitsU(0),
931  m_nMatchedHitsV(0),
932  m_nMatchedHitsW(0),
933  m_pAddress(nullptr)
934 {
935 }
936 
937 //------------------------------------------------------------------------------------------------------------------------------------------
938 //------------------------------------------------------------------------------------------------------------------------------------------
939 
941  m_matchedPrimaryId(-1),
942  m_nMatchedHits(0),
943  m_completeness(0.f)
944 {
945 }
946 
947 } //namespace lar_pandora
double E(const int i=0) const
Definition: MCParticle.h:237
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.
bool GetStrongestPfoMatch(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, IntSet &usedMCIds, IntSet &usedPfoIds, MatchingDetailsMap &matchingDetailsMap) const
Get the strongest pfo match (most matched hits) between an available mc primary and an available pfo...
void GetMCParticleMatchingMap(const PFParticlesToHits &recoParticlesToHits, const MCParticlesToHits &trueParticlesToHits, const HitsToMCParticles &hitsToTrueParticles, MCParticleMatchingMap &mcParticleMatchingMap) const
Performing matching between true and reconstructed particles.
bool HasMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfoList &simpleMatchedPfoList, const MatchingDetailsMap &matchingDetailsMap) const
Whether a provided mc primary has a match, of any quality (use simple matched pfo list and informatio...
bool IsNeutrinoInduced(const art::Ptr< simb::MCParticle > pMCParticle, const MCParticlesToMCTruth &artMCParticlesToMCTruth) const
Whether a mc particle is neutrino induced.
int PdgCode() const
Definition: MCParticle.h:216
void PrintMatchingOutput(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const MatchingDetailsMap &matchingDetailsMap) const
Print the results of the matching procedure.
void PerformMatching(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, MatchingDetailsMap &matchingDetailsMap) const
Apply a well-defined matching procedure to the comprehensive matches in the provided mc primary match...
std::map< art::Ptr< recob::Hit >, art::Ptr< recob::PFParticle > > HitsToPFParticles
std::map< SimpleMCPrimary, SimpleMatchedPfoList > MCPrimaryMatchingMap
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:92
PFParticleValidation(fhicl::ParameterSet const &pset)
Constructor.
float m_matchingMinCompleteness
The minimum particle completeness to declare a match.
const simb::MCParticle * m_pAddress
The address of the mc primary.
static bool IsNeutrino(const art::Ptr< recob::PFParticle > particle)
Determine whether a particle has been reconstructed as a neutrino.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Planes which measure V.
Definition: geo_types.h:77
void GetRecoNeutrinos(const art::Event &evt, PFParticleVector &recoNeutrinoVector) const
Obtain a vector of reco neutrinos.
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
std::map< art::Ptr< simb::MCTruth >, MCParticleVector > MCTruthToMCParticles
Declaration of signal hit object.
bool m_neutrinoInducedOnly
Whether to consider only mc particles that were neutrino induced.
simb::Origin_t Origin() const
Definition: MCTruth.h:71
int m_matchingMinPrimaryHits
The minimum number of good mc primary hits used in matching scheme.
void GetSimpleMCPrimaryList(const art::Event &evt, const MCParticlesToHits &mcParticlesToHits, const HitsToMCParticles &hitsToMCParticles, const MCParticleMatchingMap &mcParticleMatchingMap, SimpleMCPrimaryList &simpleMCPrimaryList) const
Extract details of each mc primary (ordered by number of true hits)
int PdgCode() const
Return the type of particle as a PDG ID.
Definition: PFParticle.h:83
std::map< int, MatchingDetails > MatchingDetailsMap
Particle class.
const recob::PFParticle * m_pAddress
The address of the pf primary.
std::map< art::Ptr< simb::MCParticle >, art::Ptr< simb::MCTruth > > MCParticlesToMCTruth
void PrintAllOutput(const MCTruthVector &mcTruthVector, const PFParticleVector &recoNeutrinoVector, const MCPrimaryMatchingMap &mcPrimaryMatchingMap) const
Print all the raw matching output to screen.
TFile f
Definition: plotHisto.C:6
std::string m_particleLabel
The name/label of the particle producer module.
bool m_useSmallPrimaries
Whether to consider matches to mc primaries with fewer than m_matchingMinPrimaryHits.
std::vector< art::Ptr< simb::MCTruth > > MCTruthVector
Planes which measure U.
Definition: geo_types.h:76
static void BuildMCParticleHitMaps(const HitVector &hitVector, const SimChannelVector &simChannelVector, HitsToTrackIDEs &hitsToTrackIDEs)
Collect the links from reconstructed hits to their true energy deposits.
std::vector< SimpleMCPrimary > SimpleMCPrimaryList
if(nlines<=0)
bool m_printMatchingToScreen
Whether to print matching output to screen.
intermediate_table::const_iterator const_iterator
void GetMCTruth(const art::Event &evt, MCTruthVector &mcTruthVector) const
Obtain a vector of mc truth.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
bool IsGoodMatch(const SimpleMCPrimary &simpleMCPrimary, const SimpleMatchedPfo &simpleMatchedPfo) const
Whether a provided mc primary and pfo are deemed to be a good match.
bool m_printAllToScreen
Whether to print all/raw matching details to screen.
int m_nMatchedHits
The number of times the primary has 0 pfo matches.
size_t Parent() const
Definition: PFParticle.h:96
float m_matchingMinPurity
The minimum particle purity to declare a match.
T get(std::string const &key) const
Definition: ParameterSet.h:231
std::string m_backtrackerLabel
The name/label of the back-tracker module.
int m_matchingMinSharedHits
The minimum number of shared hits used in matching scheme.
int m_matchingMinPrimaryGoodViews
The minimum number of good views for a mc primary.
void GetRemainingPfoMatches(const MCPrimaryMatchingMap &mcPrimaryMatchingMap, const IntSet &usedPfoIds, MatchingDetailsMap &matchingDetailsMap) const
Get the best matches for any pfos left-over after the strong matching procedure.
EDAnalyzer(Table< Config > const &config)
Definition: EDAnalyzer.h:100
std::vector< SimpleMatchedPfo > SimpleMatchedPfoList
static bool SortSimpleMatchedPfos(const SimpleMatchedPfo &lhs, const SimpleMatchedPfo &rhs)
Sort simple matched pfos by number of matched hits.
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticleToMatchedHits
static void CollectPFParticles(const art::Event &evt, const std::string &label, PFParticleVector &particleVector)
Collect the reconstructed PFParticles from the ART event record.
std::vector< art::Ptr< recob::Hit > > HitVector
static void CollectHits(const art::Event &evt, const std::string &label, HitVector &hitVector)
Collect the reconstructed Hits from the ART event record.
std::map< art::Ptr< recob::PFParticle >, HitVector > PFParticlesToHits
std::map< art::Ptr< simb::MCParticle >, PFParticleToMatchedHits > MCParticleMatchingMap
static void SelectNeutrinoPFParticles(const PFParticleVector &inputParticles, PFParticleVector &outputParticles)
Select reconstructed neutrino particles from a list of all reconstructed particles.
bool IsGoodMCPrimary(const SimpleMCPrimary &simpleMCPrimary) const
Whether a provided mc primary passes selection, based on number of "good" hits.
std::map< art::Ptr< simb::MCParticle >, HitVector > MCParticlesToHits
Hierarchical representation of particle flow.
Definition: PFParticle.h:44
int m_matchingMinHitsForGoodView
The minimum number of good mc primary hits in given view to declare view to be good.
T const * get() const
Definition: Ptr.h:321
static bool SortSimpleMCPrimaries(const SimpleMCPrimary &lhs, const SimpleMCPrimary &rhs)
Sort simple mc primaries by number of mc hits.
void reconfigure(fhicl::ParameterSet const &pset)
HLT enums.
void GetMCPrimaryMatchingMap(const SimpleMCPrimaryList &simpleMCPrimaryList, const MCParticleMatchingMap &mcParticleMatchingMap, const PFParticlesToHits &pfParticlesToHits, MCPrimaryMatchingMap &mcPrimaryMatchingMap) const
Obtain a sorted list of matched pfos for each mc primary.
Planes which measure W (third view for Bo, MicroBooNE, etc).
Definition: geo_types.h:78
bool NeutrinoSet() const
Definition: MCTruth.h:75
bool operator<(const SimpleMCPrimary &rhs) const
operator <
std::string m_geantModuleLabel
The name/label of the geant module.
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
unsigned int CountHitsByType(const geo::View_t view, const HitVector &hitVector) const
Count the number of hits, in a provided vector, of a specified view.
Definition: fwd.h:25
std::map< art::Ptr< recob::Hit >, art::Ptr< simb::MCParticle > > HitsToMCParticles
std::string m_hitfinderLabel
The name/label of the hit producer module.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
int m_parentId
The unique identifier of the parent pfo (-1 if no parent set)
Beam neutrinos.
Definition: MCTruth.h:21